---
title: "Fetch Step"
method: GET
path: "/workflows/steps/{id}"
tags: ["Workflows::Step"]
---

# Fetch Step

`GET /workflows/steps/{id}`

Retrieve a single workflow step.

## Path parameters

- `id` string, required

## Response `200`

OK

- WorkflowsStepAttributes — A single action or split step within a workflow. `step_type` equals the single key inside `step_type_settings` and identifies which step class this is. The full list of step types, the per-type settings each one carries, the write-only `send_email_step` inline-body fields, and how FK ids are serialized are all documented on the **`step_type_settings`** field below — that field is the single canonical reference, and the Create Step / Update Step request bodies point to it. `parent_step_id` and `branch` report where a step sits when it lives inside a split branch; see the Create Step / Update Step schemas for setting placement on write.
  - `id` integer — Step ID
  - `public_id` string, nullable — Obfuscated step ID
  - `workflow_id` integer — Integer ID of the parent workflow
  - `step_type` string — The step class key (same as the single key in `step_type_settings`).
  - `name` string — Human-readable step name.
  - `sort_order` integer — Zero-based position **within this step's own container** (the trunk, or a split's branch/convergence sequence). It is therefore **container-local, not globally unique** — it restarts at 0 for steps after a split. In `/structure`, follow the `steps` array order for execution flow, not `sort_order`.
  - `state` 'active' | 'notSetup' | 'notDefined' — Setup state of the step.
  - `parent_step_id` integer, nullable — Raw integer id of the parent split step when this step lives inside a branch. Null for trunk steps.
  - `branch` string, nullable — For conditional splits — `matched` or `unmatched`. For split tests — the 0-based variant index as a string. Null for trunk steps.
  - `convergence_step_id` integer, nullable — Id of the step a split's branches reconverge at — the first step that runs after the split, which every branch continues to. Example: a conditional_split_step (id 203) whose matched/unmatched branches both lead to the same next step (id 206) → convergence_step_id 206. It is null in two cases: a split that ends the flow (nothing follows it), and any non-split step (the field only applies to conditional_split_step / split_test_step). Use step_type to tell them apart — a null on a non-split step just means the field does not apply. When non-null, the referenced step always appears in this response.
  - `step_type_settings` object — A single-key map: the one key is the step type (identical to `step_type`) and its value carries that type's settings. **This is the canonical reference for step settings — the Create Step and Update Step request bodies point here.** Available types — **Action steps** (non-branching): `send_email_step`, `send_asset_step`, `send_chat_message_step`, `contact_tag_step`, `contact_custom_attribute_step`, `delay_step`, `notify_step`, `deliver_webhook_step`, `enroll_step`, `unenroll_contact_step`, `grant_community_access_step`, `revoke_community_access_step`, `create_opportunity_step`, `move_step` **Split steps** (branching): `conditional_split_step`, `split_test_step` ### Per-type fields - `send_email_step`: `subject`, `preheadline`, `template_id`, `from_address_id`, `reply_to_address_id`, plus write-only `html_body`/`text_body` (see "send_email_step inline body" below) - `send_asset_step`: `asset_id` - `send_chat_message_step`: `inbox_key`, `message`, `subject`, `start_new_conversation` - `contact_tag_step`: `action` (`"Add Tags"` or `"Remove Tags"`), `contacts_tag_ids` (array of raw integer tag ids) - `contact_custom_attribute_step`: `action`, `value`, `field_id` (a Forms::Field id — discoverable via the Forms API) - `delay_step`: `delay_type` (`relative`/`day_of_week`/`day_of_month`), `duration`, `interval`, `time_zone`, `use_contact_time_zone`, `use_execution_window`, `day_of_week`, `date_of_month`, `start_time`, `end_time`, `execution_window_days` - `notify_step`: `message`, `notify_type` (array), `user_ids` (array of user ids — must be team members; discover via `GET /teams/{team_id}/memberships` → `user_id`. A non-member id is rejected 422.) - `deliver_webhook_step`: `webhooks_outgoing_endpoint_id` - `enroll_step`: `course_ids` (array), `section_ids` (array). **Enrollment happens per `section_ids`** — provide the section ids to enroll in (discover via `GET /api/v2/courses/{course_id}/sections`). `course_ids` alone is accepted and the step reads `active`, but enrolls nothing at run time. - `unenroll_contact_step`: `course_ids` (array), `section_ids` (array). Unenroll honors both `course_ids` and `section_ids`. - `grant_community_access_step`: `space_ids` (array) - `revoke_community_access_step`: `space_ids` (array) - `create_opportunity_step`: `name`, `value`, `assignment_strategy`, `move_existing`, `sales_pipelines_stage_id`, `sales_pipeline_id`, `membership_id`, `membership_ids` (array) - `move_step`: `workflow_id` - `conditional_split_step`: `condition` object with `filter_id` (raw integer RefineFilter id on read; integer id or public_id on write) and `is_setup` boolean - `split_test_step`: `variants` array, each with `weight` (0..100, two entries summing to 100) ### `send_email_step` — template & inline body A `send_email_step` always owns its email. On **create**, a provided `template_id` is **copied** into a fresh step-owned template (it is never a live reference to the original), and an inline `html_body`/`text_body` instead mints a new step-owned template. This deliberately mirrors the builder UI, which always makes its own copy so edits to a step's email never touch the source. `template_id` takes precedence when both a `template_id` and an inline body are supplied. Because the step owns its template, `template_id` is **create-only and cannot be changed on update** — a `PATCH` that includes `template_id` returns `422`. To change an existing step's email, edit it **in place** by sending `html_body`/`text_body` (this patches the step's own template — no new template is created); to use a different template, create a new step. `html_body`/`text_body` are write-only and are never returned in `step_type_settings`. Prefer a verified sending address for `from_address_id`/`reply_to_address_id`. ### FK id serialization Response FK values (`*_id`, `*_ids`) are serialized as **raw integers**. On write, those same FK fields accept either integer ids or obfuscated public_ids in the same workspace/team scope.
  - `created_at` string, date-time
  - `updated_at` string, date-time

## Other responses

- `401` — Unauthorized
- `403` — Forbidden
- `404` — Not Found

---

[API](https://skmtc.net/myclickfunnels/apis/clickfunnels-api.md) · [All operations](https://skmtc.net/myclickfunnels/apis/clickfunnels-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/myclickfunnels/clickfunnels-api/revisions/ae6313eaa176/schema)
