Topolo Docs Topolo Platform
Open workspace

Get sequence

Read sequence history, the current draft and latest published version.

Outcome

Read sequence history, the current draft and latest published version.

Before you start

  • Verify the environment, credential, authorized organization and the published action permission workspace:read.
  • Discover an accessible Engage workspace and bind resourceType=workspace and its resourceId separately from action input. Fixture identifiers grant no access.

Discover the target

  • Discover the sequence through sequences.list using the retained campaignId, then read sequences.get in the same authorized workspace. Inspect sequence.status, draft, published and versions before planning.
topolo whoami --json
topolo actions get app_topolo_engage.sequences.get --json
topolo workspaces list topolo-engage --json

Input fields

FieldRequiredMeaning and constraints
idYesRequired sequence identifier discovered through sequences.list in the selected workspace, trimmed non-empty string up to 128 characters.

Validate, plan and execute

Set ENGAGE_WORKSPACE_ID to the identifier of your selected workspace. Prepare payload.json from the current input schema and discovered identifiers. Use the same payload for validation, planning and execution.

: "${ENGAGE_WORKSPACE_ID:?Set ENGAGE_WORKSPACE_ID to your selected workspace identifier}"
topolo actions validate app_topolo_engage.sequences.get --data @payload.json --json
topolo actions plan app_topolo_engage.sequences.get --resource-type workspace --resource-id "$ENGAGE_WORKSPACE_ID" --data @payload.json --json

Execute the unchanged validated read in the selected workspace.

: "${ENGAGE_WORKSPACE_ID:?Set ENGAGE_WORKSPACE_ID to your selected workspace identifier}"
topolo actions call app_topolo_engage.sequences.get --resource-type workspace --resource-id "$ENGAGE_WORKSPACE_ID" --data @payload.json --json

For MCP, use topolo_get_action, topolo_validate_action, topolo_plan_action and topolo_call_action. Pass the selected resource context separately; confirm:true is required for mutations.

Worked requests and responses

Captured sequences.get · HTTP 200

Action input

{
  "id": "eng_seq_1"
}

Actual local response

{
  "sequence": {
    "id": "eng_seq_1",
    "campaignId": "eng_cmp_1",
    "name": "Main",
    "status": "active",
    "createdAt": "2026-10-06T08:30:00.000Z",
    "updatedAt": "2026-10-06T08:30:00.000Z"
  },
  "versions": [
    {
      "id": "eng_seqv_1",
      "version": 1,
      "status": "published",
      "publishedAt": "2026-10-06T08:30:00.000Z"
    }
  ],
  "draft": null,
  "published": {
    "id": "eng_seqv_1",
    "sequenceId": "eng_seq_1",
    "version": 1,
    "status": "published",
    "publishedAt": "2026-10-06T08:30:00.000Z",
    "createdAt": "2026-10-06T08:30:00.000Z",
    "steps": [
      {
        "id": "eng_stp_1",
        "position": 1,
        "type": "linkedin_task",
        "delayDays": 0,
        "subjectTemplate": "",
        "bodyTemplate": "",
        "threadWithPrevious": false,
        "instructions": "Send a connection request mentioning the webinar.",
        "dueDays": 2
      },
      {
        "id": "eng_stp_2",
        "position": 2,
        "type": "email",
        "delayDays": 3,
        "subjectTemplate": "Hello {{first_name}}",
        "bodyTemplate": "Hi {{first_name}}",
        "threadWithPrevious": false,
        "instructions": "",
        "dueDays": 0
      },
      {
        "id": "eng_stp_3",
        "position": 3,
        "type": "call_task",
        "delayDays": 2,
        "subjectTemplate": "",
        "bodyTemplate": "",
        "threadWithPrevious": false,
        "instructions": "Call the main office.",
        "dueDays": 0
      }
    ]
  }
}

Source test: task steps in sequences > stores linkedin_task and call_task steps with instructions and a due offset, and copies them into a new version. Actual route handlers with SQLite repositories; synthetic identity/workspace grants and provider ports.

Captured sequences.get · HTTP 200

Action input

{
  "id": "eng_seq_1"
}

Actual local response

{
  "sequence": {
    "id": "eng_seq_1",
    "campaignId": "eng_cmp_1",
    "name": "Main",
    "status": "active",
    "createdAt": "2026-10-06T08:30:00.000Z",
    "updatedAt": "2026-10-06T08:30:00.000Z"
  },
  "versions": [
    {
      "id": "eng_seqv_2",
      "version": 2,
      "status": "draft",
      "publishedAt": null
    },
    {
      "id": "eng_seqv_1",
      "version": 1,
      "status": "published",
      "publishedAt": "2026-10-06T08:30:00.000Z"
    }
  ],
  "draft": {
    "id": "eng_seqv_2",
    "sequenceId": "eng_seq_1",
    "version": 2,
    "status": "draft",
    "publishedAt": null,
    "createdAt": "2026-10-06T08:30:00.000Z",
    "steps": [
      {
        "id": "eng_stp_3",
        "position": 1,
        "type": "email",
        "delayDays": 0,
        "subjectTemplate": "Quick question, {{first_name}}",
        "bodyTemplate": "Hi {{first_name}},\n\nHow is {{company}} handling outreach?\n\n{{sender_name}}",
        "threadWithPrevious": false,
        "instructions": "",
        "dueDays": 0
      },
      {
        "id": "eng_stp_4",
        "position": 2,
        "type": "email",
        "delayDays": 4,
        "subjectTemplate": "",
        "bodyTemplate": "Following up, {{first_name}}.",
        "threadWithPrevious": true,
        "instructions": "",
        "dueDays": 0
      }
    ]
  },
  "published": {
    "id": "eng_seqv_1",
    "sequenceId": "eng_seq_1",
    "version": 1,
    "status": "published",
    "publishedAt": "2026-10-06T08:30:00.000Z",
    "createdAt": "2026-10-06T08:30:00.000Z",
    "steps": [
      {
        "id": "eng_stp_1",
        "position": 1,
        "type": "email",
        "delayDays": 0,
        "subjectTemplate": "Quick question, {{first_name}}",
        "bodyTemplate": "Hi {{first_name}},\n\nHow is {{company}} handling outreach?\n\n{{sender_name}}",
        "threadWithPrevious": false,
        "instructions": "",
        "dueDays": 0
      },
      {
        "id": "eng_stp_2",
        "position": 2,
        "type": "email",
        "delayDays": 4,
        "subjectTemplate": "",
        "bodyTemplate": "Following up, {{first_name}}.",
        "threadWithPrevious": true,
        "instructions": "",
        "dueDays": 0
      }
    ]
  }
}

Source test: sequence routes > creates a sequence with an empty draft, edits steps, publishes and freezes the version. Actual route handlers with SQLite repositories; synthetic identity/workspace grants and provider ports.

Captured sequences.get · HTTP 200

Action input

{
  "id": "eng_seq_1"
}

Actual local response

{
  "sequence": {
    "id": "eng_seq_1",
    "campaignId": "eng_cmp_1",
    "name": "Main",
    "status": "draft",
    "createdAt": "2026-10-06T08:30:00.000Z",
    "updatedAt": "2026-10-06T08:30:00.000Z"
  },
  "versions": [
    {
      "id": "eng_seqv_1",
      "version": 1,
      "status": "draft",
      "publishedAt": null
    }
  ],
  "draft": {
    "id": "eng_seqv_1",
    "sequenceId": "eng_seq_1",
    "version": 1,
    "status": "draft",
    "publishedAt": null,
    "createdAt": "2026-10-06T08:30:00.000Z",
    "steps": [
      {
        "id": "eng_stp_1",
        "position": 1,
        "type": "email",
        "delayDays": 0,
        "subjectTemplate": "Hi {{first_name}}",
        "bodyTemplate": "Hello {{first_name}}, see bit.ly/x",
        "threadWithPrevious": false,
        "instructions": "",
        "dueDays": 0
      }
    ]
  },
  "published": null
}

Source test: sequences.copy_check and publish enforcement > refuses to publish a version with copy errors and allows warnings. Actual route handlers with SQLite repositories; synthetic identity/workspace grants and provider ports.

Captured sequences.get · HTTP 200

Action input

{
  "id": "eng_seq_1"
}

Actual local response

{
  "sequence": {
    "id": "eng_seq_1",
    "campaignId": "eng_cmp_1",
    "name": "Main",
    "status": "active",
    "createdAt": "2026-10-06T08:30:00.000Z",
    "updatedAt": "2026-10-06T08:30:00.000Z"
  },
  "versions": [
    {
      "id": "eng_seqv_1",
      "version": 1,
      "status": "published",
      "publishedAt": "2026-10-06T08:30:00.000Z"
    }
  ],
  "draft": null,
  "published": {
    "id": "eng_seqv_1",
    "sequenceId": "eng_seq_1",
    "version": 1,
    "status": "published",
    "publishedAt": "2026-10-06T08:30:00.000Z",
    "createdAt": "2026-10-06T08:30:00.000Z",
    "steps": [
      {
        "id": "eng_stp_1",
        "position": 1,
        "type": "email",
        "delayDays": 0,
        "subjectTemplate": "Hello {{first_name}}",
        "bodyTemplate": "Hi {{first_name}}, a short note about the webinar.",
        "threadWithPrevious": false,
        "instructions": "",
        "dueDays": 0
      },
      {
        "id": "eng_stp_2",
        "position": 2,
        "type": "whatsapp_template",
        "delayDays": 1,
        "subjectTemplate": "",
        "bodyTemplate": "",
        "threadWithPrevious": false,
        "instructions": "",
        "dueDays": 0,
        "whatsappTemplate": {
          "templateName": "webinar_invite",
          "language": "en_GB",
          "variables": [
            "first_name"
          ]
        }
      }
    ]
  }
}

Source test: WhatsApp template steps in sequences > stores the template with its variables, copies it into a new version and gets no email copy findings. Actual route handlers with SQLite repositories; synthetic identity/workspace grants and provider ports.

Effects and response meaning

  • Returns sequence, versions[] ordered by version descending, draft and published. Either draft or published may be null. Each detailed version includes steps ordered by position; published is the latest published version, not every enrollment’s pinned version.
  • Direct reads include archived sequences. This does not restore them, mutate steps or send messages.

Verify the result

  • Check sequence.id and campaignId. Retain exact versions[].id or draft.id/published.id for sequences.versions.get; inspect status and publishedAt before any edit. Existing enrollments may pin older versions.

Recover

Retry the read in the same verified workspace with the exact discovered identifiers. Use status=archived for discovery when appropriate; do not create a replacement sequence or guess another version after not_found.

Refused responses

Captured sequences.get · HTTP 404

Action input

{
  "id": "eng_seq_1"
}

Actual local response

{
  "error": {
    "code": "not_found",
    "message": "Sequence was not found in this workspace."
  }
}

Source test: sequence routes > lists, filters, renames and scopes sequences. Actual route handlers with SQLite repositories; synthetic identity/workspace grants and provider ports.

Error recovery

  • HTTP 403 permission_denied: Stop and inspect the permission required by this action in the current credential. Do not broaden permissions or switch organization automatically.
  • HTTP 422 invalid_action_input: Correct required fields, enums and nested step bounds against the current input schema, then validate the exact intended payload again.
  • HTTP 404 not_found: Rediscover the sequence using sequences.list in the same workspace and campaign; use status=archived when needed. Discover versionId from sequences.get and confirm it belongs to the same sequence. Do not guess another workspace or version.

Evidence and limits

  • contracts/sequences.mjs

  • apps/api/src/sequences/sequences-handlers.ts

  • apps/api/src/sequences/sequences-domain.ts

  • apps/api/src/sequences/sequences-repository.ts

  • apps/api/src/copy-qa/version-steps.ts

  • apps/api/src/copy-qa/copy-qa.ts

  • Actual route handlers with SQLite repositories; synthetic identity/workspace grants and provider ports.

  • Widget/bootstrap use actual app handler but mocked worker runtime and app identity.

  • No gateway execution, live permissions, external delivery or deployed proof.

The examples are local route captures with synthetic context and simulated providers. They do not prove live authorization, CLI/MCP gateway execution, production state or delivery.