Kraiter
API Reference

Sequences

Create, manage, and monitor automated email sequences with steps, delays, and conditions.

Sequences are automated drip campaigns that send a series of emails to contacts over time. Each sequence is defined as a YAML document with steps, delays, and conditions. Contacts are enrolled in sequences manually or via event-based triggers.

Create or update sequence

PUT /api/sequences/:id

Creates a new sequence or updates an existing one. The sequence body is a YAML document. You can send it two ways:

  • Raw YAML — set Content-Type: text/yaml (or omit JSON) and put the YAML in the request body.
  • JSON wrapper — set Content-Type: application/json and send { "content": "<yaml>", "name"?, "enabled"? }.

The sequence's name and trigger come from the YAML (top-level name and trigger.event), unless overridden by the JSON name. Every template referenced by the YAML steps must already exist, or the request fails with TEMPLATE_NOT_FOUND. Per the engine contract, a PUT with new content never re-enables a disabled sequence — use PATCH { "enabled": true } for that.

Path parameters

ParameterTypeDescription
idstringA unique identifier for the sequence (e.g. onboarding, re-engagement).

Request body (JSON form)

FieldTypeRequiredDescription
contentstringYesThe YAML sequence definition. Must include a trigger.event and (for create) a name.
namestringNoOverrides the name from the YAML.
enabledbooleanNoSets the enabled state on create.

Response

Returns the sequence metadata (201 on create, 200 on update). The YAML content itself is not echoed back; fetch it with GET /api/sequences/:id.

{
  "sequenceId": "onboarding",
  "name": "Onboarding Sequence",
  "version": 4,
  "enabled": true,
  "triggerEvent": "signed_up",
  "createdAt": "2025-09-10T08:00:00.000Z",
  "updatedAt": "2025-09-15T14:00:00.000Z"
}

If the YAML validates with warnings, a warnings array is also included.

Errors

CodeDescription
VALIDATION_ERRORInvalid YAML, missing sequence name, or missing trigger event.
TEMPLATE_NOT_FOUNDThe YAML references a template that does not exist.
PLAN_LIMIT_EXCEEDEDThe plan's sequence limit has been reached.

Examples

curl -X PUT https://api.kraiter.com/api/sequences/onboarding \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "name: Onboarding Sequence\ntrigger:\n  event: signed_up\nsteps:\n  - send: welcome-email\n  - delay: 1d\n  - send: getting-started\n  - delay: 3d\n  - send: tips-and-tricks\n"
  }'
const sequence = await kraiter.sequences.put("onboarding", {
  content: `name: Onboarding Sequence
trigger:
  event: signed_up
steps:
  - send: welcome-email
  - delay: 1d
  - send: getting-started
  - delay: 3d
  - send: tips-and-tricks`,
});

Partial update sequence

PATCH /api/sequences/:id

Updates a sequence's metadata without replacing the YAML definition. This is how you enable or disable a sequence. At least one field must be provided.

Path parameters

ParameterTypeDescription
idstringThe sequence ID.

Request body

FieldTypeRequiredDescription
namestringNoNew name for the sequence.
enabledbooleanNoEnable (true) or disable (false) the sequence.
triggerEventstringNoChange the event that enrols contacts into the sequence.

A sequence does not have a draft/active/paused status. Its running state is the boolean enabled field: a disabled sequence (enabled: false) enrols no new contacts and executes no steps. Enabled flags never flip implicitly — only an explicit PATCH { "enabled": ... } changes them.

Examples

curl -X PATCH https://api.kraiter.com/api/sequences/onboarding \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": true }'
const sequence = await kraiter.sequences.update("onboarding", {
  enabled: true,
});

List sequences

GET /api/sequences

Returns a paginated list of sequences.

Query parameters

ParameterTypeDefaultDescription
cursorstringPagination cursor.
limitnumber20Number of sequences to return (max 100).

The response is an object with an items array and a nextCursor.

Examples

curl "https://api.kraiter.com/api/sequences?limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
const sequences = await kraiter.sequences.list({ limit: 20 });

Get sequence

GET /api/sequences/:id

Returns a single sequence including its full YAML definition and triggers.

Path parameters

ParameterTypeDescription
idstringThe sequence ID.

Errors

CodeDescription
NOT_FOUNDNo sequence with this ID exists.

Examples

curl https://api.kraiter.com/api/sequences/onboarding \
  -H "Authorization: Bearer YOUR_API_KEY"
const sequence = await kraiter.sequences.get("onboarding");

Delete sequence

DELETE /api/sequences/:id

Permanently deletes a sequence. Active enrolments are cancelled and pending steps are removed.

Response

Returns 204 No Content on success.

Errors

CodeDescription
NOT_FOUNDNo sequence with this ID exists.

Examples

curl -X DELETE https://api.kraiter.com/api/sequences/onboarding \
  -H "Authorization: Bearer YOUR_API_KEY"
await kraiter.sequences.delete("onboarding");

Get sequence run status

GET /api/sequences/:id/status

Returns the sequence metadata plus a breakdown of enrolled contacts by state.

Response

{
  "sequenceId": "onboarding",
  "name": "Onboarding Sequence",
  "enabled": true,
  "version": "01H8...",
  "createdAt": "2025-09-10T08:00:00.000Z",
  "updatedAt": "2025-09-15T14:00:00.000Z",
  "contacts": {
    "active": 340,
    "paused": 0,
    "completed": 870,
    "exited": 40
  }
}

Examples

curl https://api.kraiter.com/api/sequences/onboarding/status \
  -H "Authorization: Bearer YOUR_API_KEY"
const status = await kraiter.sequences.getStatus("onboarding");

List enrolled contacts

GET /api/sequences/:id/contacts

Returns contacts currently enrolled in the sequence.

Examples

curl "https://api.kraiter.com/api/sequences/onboarding/contacts?limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
const contacts = await kraiter.sequences.listContacts("onboarding");

List sends from sequence

GET /api/sequences/:id/sends

Returns all emails sent as part of this sequence.

Examples

curl "https://api.kraiter.com/api/sequences/onboarding/sends" \
  -H "Authorization: Bearer YOUR_API_KEY"
const sends = await kraiter.sequences.listSends("onboarding");

Dry-run sequence

POST /api/sequences/:id/dry-run

Evaluates all gates, step conditions, and exit conditions for a specific contact without persisting anything or sending. Returns a step-by-step decision path explaining the outcome.

Request body

FieldTypeRequiredDescription
contactIdstringYesThe contact to simulate the sequence for.
stepIdstringNoEvaluate a specific step. Defaults to the contact's current step (or the first step).

Response

{
  "outcome": "would_send",
  "decisionPath": [
    { "stage": "gates", "passed": true, "explanation": "All gates passed", "details": {} },
    { "stage": "step_conditions", "passed": true, "explanation": "Step conditions met", "details": {} }
  ],
  "stepInfo": { "stepId": "welcome-email", "templateId": "welcome-email" },
  "templatePreview": { "subject": "Welcome, Alice!", "textPreview": "Hello Alice..." },
  "contactInfo": {
    "contactId": "cnt_01H8MZXK...",
    "email": "alice@example.com",
    "subscribed": true,
    "suppressed": false
  },
  "sequenceInfo": {
    "sequenceId": "onboarding",
    "name": "Onboarding Sequence",
    "enabled": true,
    "version": "01H8..."
  },
  "inSequence": false,
  "timestamp": "2025-09-15T14:00:00.000Z"
}

outcome is one of would_send, would_skip, would_exit, or blocked. templatePreview is present only when the outcome is would_send.

Examples

curl -X POST https://api.kraiter.com/api/sequences/onboarding/dry-run \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "contactId": "cnt_01H8MZXK..." }'
const dryRun = await kraiter.sequences.dryRun("onboarding", {
  contactId: "cnt_01H8MZXK...",
});