> ## Documentation Index
> Fetch the complete documentation index at: https://docs.open.cx/llms.txt
> Use this file to discover all available pages before exploring further.

> Skip one pending step for a contact while preserving their enrollment, remaining outreach, and waits. Use before continuing a sequence after a reply.

# Skip one pending step for a contact

Requires `sequences:write`. This operation changes one contact's enrollment. It keeps the enrollment ID, previous sends, personalization, and history, and leaves the shared sequence unchanged.

## Choose the pending step

| `mode`          | Additional input                           | Selection                                                                              |
| --------------- | ------------------------------------------ | -------------------------------------------------------------------------------------- |
| `next_pending`  | None                                       | First pending step at or after the contact's current position, on any channel.         |
| `next_channel`  | `channel`: `voice`, `whatsapp`, or `email` | First pending step on that channel. Phone is `voice`. Intervening steps stay in place. |
| `specific_step` | `step_index`: nonnegative integer          | That sequence position, starting at zero.                                              |

A pending step has not been sent, completed, or skipped. A failed attempt that remains retryable is still pending once dispatch has finished. A step that is being sent returns `dispatch_in_progress`; the request does not cancel it. Missing mode-dependent inputs, invalid channels, and negative or fractional indexes return HTTP 400. Inputs for another mode are ignored.

A phone call that connected is already sent even if its sequence send record is still being reconciled. An unresolved dial cannot be skipped or continued past until its outcome is known.

The optional `reason` is a nonempty string up to 2,000 characters. The contact's [journey history](/api-reference/sequences/get-contact-events) records the step, channel, reason, timestamp, and workflow, operator, or API-key attribution. Without a reason, history shows “Requested skip.” The journey shows **Skipped**, including future steps.

## Status and waiting time

* **Active:** the current due time stays in place. At that time the skipped slot is consumed and the next step's wait begins. Future skips take effect when reached.
* **Parked:** status and park reason stay unchanged. Resolve the existing park through its normal controls before the sender progresses.
* **Exited after a reply:** the skip is saved, but the enrollment stays exited. Call [Continue Sequence for Contact](/api-reference/sequences/continue-contact) separately.
* **Completed, suppressed, removed, or candidate:** no step is newly skipped and no enrollment is revived.

Sequence pauses and consent restrictions still apply when the sender reaches a recorded skip. A temporary restriction covering every available channel defers progress until it expires; permanent suppression covering every available channel exits the enrollment.

Skipped steps retain their waits. A 30-minute wait before a skipped call followed by a 60-minute wait before an email keeps a 90-minute gap. Sending windows are applied at each slot in the contact's timezone, using the sequence's normal timezone fallback. Closed hours can lengthen the gap; later processing can also delay it.

Continuation starts waiting **when the contact is resumed**. It adds the waits of skipped slots before the next pending step, applying the same sending windows. In the example, the email becomes due no earlier than 90 minutes after continuation. If no pending steps remain, continuation returns `nothing_to_continue` and the enrollment stays exited.

If you later edit the pending step's wait, it is recalculated from the latest continuation or the previous step's effective completion time. Other history events do not restart that wait.

## Results and retries

The response uses HTTP 201 for both a new skip and an expected no-op:

```json theme={"dark"}
{
  "outcome": "skipped",
  "skipped": true,
  "contact_id": "01960000-0000-7000-8000-000000000002",
  "enrollment_id": "01960000-0000-7000-8000-000000000003",
  "step_index": 2,
  "channel": "voice"
}
```

| Outcome                | Meaning                                                                                 |
| ---------------------- | --------------------------------------------------------------------------------------- |
| `skipped`              | This request newly skipped the identified step.                                         |
| `already_skipped`      | The step or idempotent request was already applied. Original history is retained.       |
| `contact_not_found`    | No live enrollment, including a removed enrollment.                                     |
| `not_skippable`        | The enrollment is completed, suppressed, a candidate, or otherwise ineligible.          |
| `no_pending_step`      | No pending step matches the next-step selection.                                        |
| `step_not_found`       | The specific index is outside this sequence.                                            |
| `step_not_pending`     | The specific step was already sent, completed, or passed.                               |
| `dispatch_in_progress` | Sending has started and cannot safely be skipped. Wait for its outcome before retrying. |

`skipped` is true only for a new skip. Index/channel fields identify the selected step where available; otherwise they are null. A missing or inaccessible sequence returns HTTP 404; insufficient scope returns HTTP 403.

Specific-step requests are always idempotent. For either next-step mode, supply an `idempotency_key` of up to 200 characters and reuse it on retries. The key is scoped to this enrollment and identifies the original selection, even if the cursor later moves. Use a new key for a new skip intent. Workflow executions supply a key automatically for each action in a run.

Recorded skips pin their step positions: removing that shared step or an earlier step is refused. Full replacement of a draft containing recorded skips is also refused. Use content/delay edits or append steps instead.

The MCP equivalent is `skip_sequence_step`, with `sequence_id`, `contact_id`, and the same body fields.

## Skip the next phone step

```json theme={"dark"}
{
  "mode": "next_channel",
  "channel": "voice",
  "reason": "Customer cannot talk now",
  "idempotency_key": "reply-123-skip-phone"
}
```

After `skipped` or `already_skipped`, continue the same contact using the separate continuation operation. See the [workflow example](/phone/follow-up-workflows#skip-a-sequence-call-after-a-reply).


## OpenAPI

````yaml post /sequences/{sequenceId}/contacts/{contactId}/skip-step
openapi: 3.1.0
info:
  title: OpenCX API
  description: >

    OpenCX is an AI-powered, all-in-one platform for customer support and
    outbound communications.


    Use this API to manage your OpenCX organization's AI agents, actions,
    conversations, contacts, and more.


    To get started, generate a new API key from the dashboard.


    ## Authentication

    All API endpoints require authentication using a Bearer token. You can
    generate an API key from your OpenCX dashboard.


    ## Rate Limiting

    API requests are rate limited to ensure fair usage. The current limits are:

    - 100 requests per minute for standard endpoints

    - 1000 requests per minute for streaming endpoints


    ## Error Handling

    The API uses standard HTTP status codes and returns detailed error messages
    in the response body.
  version: 1.0-beta
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
servers:
  - url: http://localhost:8080
    description: Development
  - url: https://api.open.cx
    description: Production
security:
  - bearerAuth: []
paths:
  /sequences/{sequenceId}/contacts/{contactId}/skip-step:
    post:
      summary: Skip one pending step for a contact
      description: >-
        Marks only this enrollment. Does not resume or unpark it. Skipped waits
        are preserved, including when continuing after a reply. A dispatch
        already started cannot be skipped. Phone uses channel voice. Retry
        next-step requests with the same idempotency_key.
      operationId: skipSequenceStep
      parameters:
        - schema:
            type: string
            format: uuid
            pattern: >-
              ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
          in: path
          name: sequenceId
          required: true
          description: The unique identifier of the sequence
        - schema:
            type: string
            format: uuid
            pattern: >-
              ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
          in: path
          name: contactId
          required: true
          description: The person's contact id (from enroll results or the people list)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SkipSequenceStepBody'
      responses:
        '201':
          description: Default Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SkipSequenceStepResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorDto'
components:
  schemas:
    SkipSequenceStepBody:
      $schema: https://json-schema.org/draft/2020-12/schema
      $id: '#/components/schemas/SkipSequenceStepBodyInput'
      type: object
      properties:
        mode:
          type: string
          enum:
            - next_pending
            - next_channel
            - specific_step
        channel:
          description: Required for next_channel. Phone uses voice.
          type: string
          enum:
            - whatsapp
            - voice
            - email
        step_index:
          description: Required for specific_step; zero-based.
          type: integer
          minimum: 0
          maximum: 9007199254740991
        reason:
          type: string
          minLength: 1
          maxLength: 2000
        idempotency_key:
          description: >-
            Reuse for retries of a next-step request in this enrollment.
            Specific-step skips are always idempotent.
          type: string
          minLength: 1
          maxLength: 200
      required:
        - mode
    SkipSequenceStepResponse:
      $schema: https://json-schema.org/draft/2020-12/schema
      $id: '#/components/schemas/SkipSequenceStepResponse'
      type: object
      properties:
        outcome:
          type: string
          enum:
            - skipped
            - already_skipped
            - contact_not_found
            - not_skippable
            - no_pending_step
            - step_not_found
            - step_not_pending
            - dispatch_in_progress
        skipped:
          type: boolean
          description: True only when this request newly skipped a step.
        contact_id:
          anyOf:
            - type: string
            - type: 'null'
        enrollment_id:
          anyOf:
            - type: string
            - type: 'null'
        step_index:
          anyOf:
            - type: integer
              minimum: -9007199254740991
              maximum: 9007199254740991
            - type: 'null'
        channel:
          anyOf:
            - type: string
              enum:
                - whatsapp
                - voice
                - email
            - type: 'null'
      required:
        - outcome
        - skipped
        - contact_id
        - enrollment_id
        - step_index
        - channel
      additionalProperties: false
    ErrorDto:
      type: object
      properties:
        statusCode:
          type: integer
        message:
          type: string
        error:
          type: string
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````