---
title: "Change a sequence"
method: PATCH
path: "/v1/projects/{project}/sequences/{sequence}"
tags: ["Recovery Sequences"]
---

# Change a sequence

`PATCH /v1/projects/{project}/sequences/{sequence}`

## Request

- Base URL: `https://api.subscriby.net`
- URL: `https://api.subscriby.net/v1/projects/{project}/sequences/{sequence}`
- Auth: HTTP bearer

```bash
curl -X PATCH https://api.subscriby.net/v1/projects/7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13/sequences/9d2f4b6a-1c3e-4f58-8a7b-6e5d4c3b2a19 \
  -H "Authorization: Bearer sbt_..." \
  -H "Idempotency-Key: 0c4e8a2d-6f1b-4c9e-8d3a-5b7f9e1c2d64" \
  -H "Content-Type: application/json" \
  -d '{"active": false}'
```

Any subset of the name, the trigger and the switch; fields left out keep their stored values. Switching a sequence off lets every member part-way through go, as `sequence.exited` with the reason `disabled`, and enrols nobody until it runs again; switching it back on enrols nobody retroactively.

`steps`, when present, replaces the whole list in order: a step still at its place keeps its id and a member due it keeps their position, the rest are appended and the extra ones removed from the end. Send `[]` to remove every step. One `sequence.updated` announces the sequence as it then stands.

## Path parameters

- `project` string, uuid, required
- `sequence` string, uuid, required

## Headers

- `Idempotency-Key` string, uuid, required

## Request body

- UpdateSequenceRequest: The changes to a sequence: any subset of the name, the trigger and the switch, and optionally the whole list of steps in order. Fields left out keep their stored values.
  - `name` string: A new creator-facing label, 1 to 120 characters.
  - `trigger` 'churned' | 'lead' | 'stalled_checkout' | 'trial_ending': What enrols a member: `churned`, `lead`, `stalled_checkout` or `trial_ending`. Members already part-way through keep their passage.
  - `active` boolean: Switch the sequence on or off. Off lets every member part-way through go, as `sequence.exited` with the reason `disabled`, and enrols nobody until it runs again.
  - `steps` object[]: The whole list of steps in order, at most 8; it replaces the stored list. A step still at its place keeps its id and a member due it keeps their position. Omit to leave the steps alone; send `[]` to remove them all.
    - `delay_days` integer, required: Days after the trigger for the first step, 0 to 180 (`0` goes out on the next hourly run); days after the step before for the rest, 1 to 180.
    - `body` string, required: The message in the creator's words, 1 to 1,000 characters, with `{name}`, `{project}`, `{coupon}`, `{discount}` and `{link}` filled per member at send time.
    - `coupon_id` string, nullable: One of this project's coupons to carry with the step, or `null`.

## Response `200`

The sequence as it now reads.

- object
  - `data` SequenceResource, required: A sequence: the ordered messages a member receives on the days the creator chose after one of four moments (they left, they arrived as a lead, their checkout stalled, their trial is about to end), each with the way to the plan and, optionally, a coupon; with how many members it enrolled, how many are still receiving it and how many paid while it ran.
    - `id` string, required: The sequence's id.
    - `project_id` string, required: The project the sequence belongs to.
    - `name` string, required: A creator-facing label.
    - `trigger` string, required: What enrols a member: `churned` (their last live membership ended), `lead` (they arrived without buying), `stalled_checkout` (a checkout stayed open past the project's window) or `trial_ending` (a trial without a card is about to end).
    - `active` boolean, required: Whether the sequence enrols and sends.
    - `steps` SequenceStepResource[]: The steps in order, present when the relation is loaded.
      - `id` string, required: The step's id. A step rewritten in place keeps it.
      - `position` integer, required: The step's place, contiguous from 1.
      - `delay_days` integer, required: Days after the trigger for the first step, 0 to 180 (`0` goes out on the next hourly run); days after the step before for the rest, 1 to 180.
      - `body` string, required: The message with its placeholders unfilled: `{name}`, `{project}`, `{coupon}`, `{discount}` and `{link}`.
      - `coupon` object, nullable: The coupon the step carries, present when the relation is loaded; `null` without one.
        - `id` string, required: The coupon's id.
        - `code` string, required: The coupon's code.
    - `counts` object, required: How the sequence has done, all time.
      - `enrolled` string, required: Every member ever enrolled.
      - `open` string, required: Members still receiving steps.
      - `completed` string, required: Members who received every step.
      - `won_back` string, required: Members for whom a payment settled while the sequence ran.
    - `created_at` string, nullable, required: When the sequence was built, ISO 8601.
    - `updated_at` string, nullable, required: When it last changed, ISO 8601.
    - `deleted_at` string, nullable, required: When the creator deleted it, ISO 8601; `null` while in use.

## Other responses

- `400`: `IDEMPOTENCY_KEY_MISSING`: every write needs an `Idempotency-Key` header. Send a fresh UUID per distinct operation.
- `401`: `AUTHENTICATION_REQUIRED`: the request carries no bearer token, or one that is revoked, malformed, or minted for another environment (an `sbt_test_` token on production).
- `403`: `TOKEN_MISSING_ABILITY`: the token is valid but does not carry the ability this endpoint requires; `error.context.required_ability` names the one to grant. An endpoint that also checks who owns a row or which tier the account is on answers `FORBIDDEN`, `TEAM_TIER_REQUIRED` or `CONNECTOR_TIER_REQUIRED` with the same status, and says so in its own description.
- `404`: `RESOURCE_NOT_FOUND`: an id in the path names nothing the token can see. `TENANT_MISMATCH`: the project sits outside the token's `scope:project:` allow-list, or the token carries no team scope. Both answer 404 rather than 403 so that existence outside the token's scope cannot be inferred.
- `409`: `IDEMPOTENCY_KEY_REUSED`: the key was already used in the last 24 hours with a different request body.
- `422`: `VALIDATION_FAILED`: the payload broke a rule, and `error.fields` maps each offending key to its messages. A refusal from the domain, such as a plan that cannot go on sale or a member who cannot be removed, uses the same code with `error.message` saying why and no `fields`.
- `425`: `IDEMPOTENCY_REPLAY_IN_PROGRESS`: the first request with this key is still running; retry in a few seconds and the original response is replayed.
- `429`: `RATE_LIMITED`: the token has spent its 300 requests a minute or 10,000 an hour; `Retry-After` says when the next one is accepted.

---

[API](https://skmtc.dev/memberpass/apis/subscriby-rest-api.md) · [All operations](https://skmtc.dev/memberpass/apis/subscriby-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/memberpass/apis/subscriby-rest-api/revisions/59c4df91d764?raw)
