Skip to content
Esc
  • OverviewGuidesWhat exists today, and where to start.
  • QuickstartGuidesKey, domain, first send — in that order.
  • AuthenticationGuidesBearer keys, the mandatory User-Agent, and what each refusal means.
  • ErrorsGuidesThe whole vocabulary, with the status each name carries.
  • IdempotencyGuidesRetry a send without sending it twice.
  • PaginationGuidesCursors are item IDs, not page numbers.
  • Rate limitsGuidesTen a second per team, and the headers that tell you where you are.
  • EventsGuidesEvery event a webhook can carry, with one real payload each.
  • DomainsGuidesThe records, where they go at each registrar, and what the page does while you wait.
  • TrackingGuidesOpens and clicks: one record, two toggles, and what an open really means.
  • ReceivingGuidesInbound mail, and the Inbox: a webhook fires, you read it, you answer it.
  • InboxGuidesChannels, personal mailboxes and seats: who sees what, and where a reply goes.
  • Node SDKGuidesThe rasket package: typed from the API's own document, retries only what is safe.
  • Python SDKGuidesThe rasket package on PyPI: the Node client's methods, in snake_case, over httpx.
  • MCP serverGuidesConnect Claude, ChatGPT or any MCP client: your scopes, no key.
  • AI assistGuidesSubject lines, drafts and diagnosis — in the dashboard and over the API, off until you allow it.
  • AgentsGuidesLet an AI agent set Rasket up: the skill, the rules file, MCP, and the recipe they share.
  • OAuthGuidesLet another app act for a team: register, authorize with PKCE, exchange, refresh.
  • Single sign-onGuidesOIDC login for your team, a domain proved by DNS, enforcement and break-glass.
  • IntegrationsGuidesVercel, Netlify and Cloudflare, plus Zapier and n8n for workflows without code.
  • SMTPGuidesSend from anything that speaks SMTP: settings, setup guides, limits and replies.
  • ZapierGuidesSend email, add contacts and react to email events from a Zap, with no code.
  • n8nGuidesThe Rasket node and trigger for n8n workflows: install, connect, every operation.
  • EmailsAPI referenceSend, batch, retrieve, list, reschedule, cancel, attachments.
  • DomainsAPI referenceAdd a domain, publish its records, verify it.
  • API keysAPI referenceCreate, list, rename and revoke credentials.
  • WebhooksAPI referencePayloads, signature verification, retries and replay.
  • SuppressionsAPI referenceAddresses we will not send to, and why.
  • LogsAPI referenceEvery request made with this team's credentials.
  • MetricsAPI referenceDelivery, bounce, complaint and engagement counts.
  • TemplatesAPI referenceVersioned email content with typed variables, addressed by ID or alias.
  • ContactsAPI referenceYour audience: contacts, their typed properties, segments and topic choices.
  • SegmentsAPI referenceAudiences defined by a filter, by hand, or both.
  • TopicsAPI referenceWhat contacts subscribe to, and the preference page's list.
  • CampaignsAPI referenceCampaigns, at /broadcasts: one message to a segment, from draft to results.
  • ImportsAPI referenceCSV uploads: column mapping, conflicts and counts.
  • AutomationsAPI referenceWorkflows that run per contact: the graph, its versions, and every run.
  • Custom eventsAPI referenceThe names your product fires, and what starts a workflow.
  • ReceivingAPI referenceMail sent to you: the message, its attachments, its raw source.
  • OAuthAPI referenceClient registration, the token endpoint, and the grants a team has given.
  • TeamAPI referenceThe team a credential belongs to: its plan, sender identity, AI flag and members.
  • BillingAPI referencePlan, usage, invoices and add-ons, and the hosted pages where a customer pays.
  • AI helpersAPI referenceSubject lines, a first draft, and why an email did what it did.

API referenceAutomations

Automations

A workflow that runs per contact. An event enrols someone at the trigger, and the graph carries them through sends, delays and branches until it runs out.

Lifecycle

An automation is an identity plus immutable versions. Creating one writes version 1. A PATCH carrying steps and connections writes the next one and points the automation at it — that PATCH is the publish. A run already in flight keeps the version it started on, so publishing never rewrites what someone is halfway through.

status gates enrolment and nothing else: disabled stops new runs starting and leaves live ones alone. POST /automations/{automation_id}/stop is the one that disables and cancels every run still going; deleting does the same and answers 404 from that moment.

Steps and connections

A graph is a list of steps, each with a key unique within the version, and a list of connections between those keys. Exactly one step is the trigger, every other step is reachable from it, and the whole thing is acyclic. At most 150 steps.

Automation step types
Step typeDoes
triggerThe one entry point. config.event_name is a custom event of yours, or a built-in one under the rasket: prefix.
send_emailSends a published template through the ordinary send transaction: quota, suppressions, unsubscribe headers and email.* events all behave as they do for POST /emails.
delayParks the run until a moment: { duration: "3 days" } or { until: "2026-10-01T09:00:00Z" }, at most 30 days out.
conditionA rule tree over the contact. Its two outgoing edges are condition_met and condition_not_met; it takes no default.
contact_updateSets first name, last name, unsubscribed or declared properties to literal values.
add_to_segmentAdds the contact to one of your segments.
topic_updateOpts the contact in or out of one topic.

A connection is { from, to, type }, where type is default, condition_met or condition_not_met and defaults to default. Every step but a condition has at most one outgoing edge; a condition has at most one of each branch.

The whole graph is checked at once, against your own team: every template, segment, topic, contact property and custom event it names has to resolve. A failure is 422 validation_error with one entry in errors[] per offending step key, so an editor can put each message on its own node rather than fixing one problem per round trip.

Two step types in the schema are not available in this release — wait_for_event and contact_delete — along with the timeout and event_received connections that belong to the first. A graph naming any of them is refused with that reason.

Runs

  • One run per contact per enrolling event. Two sends of the same event are two runs; one send redelivered internally is still one.
  • A run parked on a delay reports running, and ?status=running returns it. A delay is a timestamp the run wakes at, not a process holding a thread — so a worker restart mid-workflow loses nothing, and the public status enum needs no fifth word for it.
  • ?status= on the run list takes a comma-separated list of running, completed, failed and cancelled. A member outside those four is 422 invalid_parameter naming it.
  • A single run's steps[] come back in graph order — a walk from the trigger of the version that run pinned, taking condition_met before condition_not_met.

Endpoints

Create an automation

POST /automations

The workflow and version 1 of its graph, in one call.

Body

  • namestringRequired

    A name for the dashboard.

  • statusstring

    enabled or disabled. Defaults to disabled, so nothing enrols yet.

  • stepsobject[]Required

    The steps of the workflow, at most 150. Each is { key, type, config } with a key unique within the graph. Exactly one step must be a trigger.

  • connectionsobject[]Required

    The edges between steps: { from, to, type }, where from and to are step keys and type is default, condition_met or condition_not_met. Omitting type means default.

Request

curl -X POST "https://api.rasket.com/automations" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Trial nudge",
  "status": "disabled",
  "steps": [
    {
      "key": "start",
      "type": "trigger",
      "config": {
        "event_name": "trial.started"
      }
    },
    {
      "key": "welcome",
      "type": "send_email",
      "config": {
        "template": {
          "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e05",
          "variables": {
            "plan": "pro"
          }
        }
      }
    },
    {
      "key": "wait",
      "type": "delay",
      "config": {
        "duration": "3 days"
      }
    },
    {
      "key": "check",
      "type": "condition",
      "config": {
        "type": "rule",
        "field": "properties.activated",
        "operator": "eq",
        "value": true
      }
    },
    {
      "key": "tag",
      "type": "contact_update",
      "config": {
        "properties": {
          "lifecycle": "activated"
        }
      }
    },
    {
      "key": "onboard",
      "type": "add_to_segment",
      "config": {
        "segment_id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e04"
      }
    }
  ],
  "connections": [
    {
      "from": "start",
      "to": "welcome"
    },
    {
      "from": "welcome",
      "to": "wait"
    },
    {
      "from": "wait",
      "to": "check"
    },
    {
      "from": "check",
      "to": "tag",
      "type": "condition_met"
    },
    {
      "from": "check",
      "to": "onboard",
      "type": "condition_not_met"
    }
  ]
}'

Response 201

{
  "object": "automation",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"
}
  • The whole graph is validated at once. A failure is 422 validation_error with one entry in errors[] per offending step key, not the first problem found.
  • Every template, segment, topic, contact property and custom event the graph names must already exist in your team.
  • wait_for_event and contact_delete are parsed and refused in this release: a graph naming either is 422 validation_error.

List automations

GET /automations

Every automation, newest first.

Query parameters

  • statusstring

    enabled or disabled. Anything else is 422 invalid_parameter.

  • limitinteger

    How many items to return, 1–100. Defaults to 20.

  • afterstring

    Return the page that follows this item ID. Mutually exclusive with before.

  • beforestring

    Return the page that precedes this item ID. Mutually exclusive with after.

  • searchstring

    A case-insensitive substring of the automation's name, at most 200 characters. % and _ match literally; a blank term is 422 invalid_parameter.

Request

curl -X GET "https://api.rasket.com/automations?status=enabled&limit=20" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "list",
  "has_more": false,
  "data": [
    {
      "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01",
      "name": "Trial nudge",
      "status": "enabled",
      "created_at": "2026-09-11T12:00:00.000Z",
      "updated_at": "2026-09-11T12:00:00.000Z"
    }
  ]
}
  • Items carry no graph. Retrieve one automation for its steps and connections.

Retrieve an automation

GET /automations/{automation_id}

With the active version's graph — the one new enrolments will run.

Path parameters

  • automation_idstringRequired

    The automation's ID.

Request

curl -X GET "https://api.rasket.com/automations/{automation_id}" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "automation",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01",
  "name": "Trial nudge",
  "status": "enabled",
  "created_at": "2026-09-11T12:00:00.000Z",
  "updated_at": "2026-09-11T12:00:00.000Z",
  "steps": [
    {
      "key": "start",
      "type": "trigger",
      "config": {
        "event_name": "trial.started"
      }
    },
    {
      "key": "welcome",
      "type": "send_email",
      "config": {
        "template": {
          "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e05",
          "variables": {
            "plan": "pro"
          }
        }
      }
    },
    {
      "key": "wait",
      "type": "delay",
      "config": {
        "duration": "3 days"
      }
    },
    {
      "key": "check",
      "type": "condition",
      "config": {
        "type": "rule",
        "field": "properties.activated",
        "operator": "eq",
        "value": true
      }
    },
    {
      "key": "tag",
      "type": "contact_update",
      "config": {
        "properties": {
          "lifecycle": "activated"
        }
      }
    },
    {
      "key": "onboard",
      "type": "add_to_segment",
      "config": {
        "segment_id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e04"
      }
    }
  ],
  "connections": [
    {
      "from": "start",
      "to": "welcome",
      "type": "default"
    },
    {
      "from": "welcome",
      "to": "wait",
      "type": "default"
    },
    {
      "from": "wait",
      "to": "check",
      "type": "default"
    },
    {
      "from": "check",
      "to": "tag",
      "type": "condition_met"
    },
    {
      "from": "check",
      "to": "onboard",
      "type": "condition_not_met"
    }
  ]
}
  • steps and connections come from the **active** version. A run already in flight keeps the version it started on.
  • Every connection carries a type, even the ones you created without one.
  • An automation that belongs to another team, or that has been deleted, is 404 not_found.

Update an automation

PATCH /automations/{automation_id}

Rename, enable, disable — or publish a new version of the graph.

Path parameters

  • automation_idstringRequired

    The automation's ID.

Body

  • namestring

    A new name.

  • statusstring

    enabled or disabled.

  • stepsobject[]

    The steps of the workflow, at most 150. Each is { key, type, config } with a key unique within the graph. Exactly one step must be a trigger.

  • connectionsobject[]

    The edges between steps: { from, to, type }, where from and to are step keys and type is default, condition_met or condition_not_met. Omitting type means default.

Request

curl -X PATCH "https://api.rasket.com/automations/{automation_id}" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "enabled"
}'

Response 200

{
  "object": "automation",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01"
}
  • Sending steps and connections writes the **next version** and points the automation at it. The two must be sent together; one without the other is 422 validation_error.
  • A PATCH with only name and/or status creates no version.
  • status: "disabled" stops new enrolments and leaves runs already in flight alone. To stop those too, use the stop endpoint.
  • An empty body is 422. Send at least one of name, status, or the graph pair.

Delete an automation

DELETE /automations/{automation_id}

Cancels every live run, then removes it.

Path parameters

  • automation_idstringRequired

    The automation's ID.

Request

curl -X DELETE "https://api.rasket.com/automations/{automation_id}" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "automation",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01",
  "deleted": true
}
  • Soft-deletes: the automation is 404 not_found from this moment, on every operation.
  • Each cancelled run raises automation.run.failed with the reason cancelled.

Duplicate an automation

POST /automations/{automation_id}/duplicate

A disabled copy of the active version, at version 1.

Path parameters

  • automation_idstringRequired

    The automation's ID.

Request

curl -X POST "https://api.rasket.com/automations/{automation_id}/duplicate" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 201

{
  "object": "automation",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e09"
}
  • The copy is named <name> (copy) and is always disabled, whatever the source's status.
  • The graph is copied verbatim and is not re-validated — what it copies was valid when it was published.
  • The source is untouched.

Stop an automation

POST /automations/{automation_id}/stop

Disable it and cancel every run still going.

Path parameters

  • automation_idstringRequired

    The automation's ID.

Request

curl -X POST "https://api.rasket.com/automations/{automation_id}/stop" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "automation",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e01",
  "status": "disabled"
}
  • This is the difference between stop and PATCH { status: "disabled" }: the PATCH stops new enrolments, stop also cancels the runs already in flight.
  • Stopping an automation that is already disabled still cancels its live runs, and still answers 200.

List runs

GET /automations/{automation_id}/runs

One run per contact per enrolling event, newest first.

Path parameters

  • automation_idstringRequired

    The automation's ID.

Query parameters

  • statusstring

    A comma-separated list of running, completed, failed and cancelled. A member outside those four is 422 invalid_parameter.

  • limitinteger

    How many items to return, 1–100. Defaults to 20.

  • afterstring

    Return the page that follows this item ID. Mutually exclusive with before.

  • beforestring

    Return the page that precedes this item ID. Mutually exclusive with after.

  • start_datestring

    ISO 8601, inclusive. Runs created before this are excluded. After end_date is 422 invalid_parameter.

  • end_datestring

    ISO 8601, inclusive. Runs created after this are excluded.

Request

curl -X GET "https://api.rasket.com/automations/{automation_id}/runs?status=running%2Cfailed&limit=20" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "list",
  "has_more": false,
  "data": [
    {
      "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e02",
      "status": "failed",
      "failure_reason": "validation_error",
      "failure_message": "The domain is not verified.",
      "failed_step_key": "welcome",
      "started_at": "2026-09-11T12:00:00.000Z",
      "completed_at": "2026-09-14T12:00:00.000Z",
      "created_at": "2026-09-11T12:00:00.000Z"
    }
  ]
}
  • A run parked on a delay is reported as running, and ?status=running returns it: a delay is a timestamp the run wakes at, not a process holding a thread.
  • A run that failed or was cancelled says why: failure_reason is a stable code, the same one the automation.run.failed webhook carries; failure_message is that ending in a sentence, for a person; failed_step_key is the step it stopped at. All three are null on any other run.
  • Items carry no steps. Retrieve one run for its step log.

Retrieve a run

GET /automations/{automation_id}/runs/{run_id}

One contact's journey, step by step, in graph order.

Path parameters

  • automation_idstringRequired

    The automation's ID.

  • run_idstringRequired

    The run's ID.

Request

curl -X GET "https://api.rasket.com/automations/{automation_id}/runs/{run_id}" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "automation_run",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e02",
  "status": "completed",
  "failure_reason": null,
  "failure_message": null,
  "failed_step_key": null,
  "started_at": "2026-09-11T12:00:00.000Z",
  "completed_at": "2026-09-14T12:00:00.000Z",
  "created_at": "2026-09-11T12:00:00.000Z",
  "steps": [
    {
      "key": "start",
      "type": "trigger",
      "status": "completed",
      "started_at": "2026-09-11T12:00:00.000Z",
      "completed_at": "2026-09-11T12:00:00.000Z",
      "output": {
        "enrolled": true
      },
      "error": null,
      "created_at": "2026-09-11T12:00:00.000Z"
    },
    {
      "key": "welcome",
      "type": "send_email",
      "status": "completed",
      "started_at": "2026-09-11T12:00:00.000Z",
      "completed_at": "2026-09-11T12:00:00.000Z",
      "output": {
        "email_id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e0a"
      },
      "error": null,
      "created_at": "2026-09-11T12:00:00.000Z"
    }
  ]
}
  • steps is a breadth-first walk from the trigger of the version this run pinned, taking condition_met before condition_not_met — the order the editor draws them.
  • output and error are whatever the step produced; their shape depends on the step type. A failed step's error is { reason, message }, the same pair the run's own failure_reason and failure_message carry.
  • On a run that failed or was cancelled, failed_step_key names the step it stopped at and matches one of steps[].key.
  • A run of a different automation, or of another team, is 404 not_found.

List an automation's versions

GET /automations/{automation_id}/versions

Every published graph, newest first, and which one new enrolments run.

Path parameters

  • automation_idstringRequired

    The automation's ID.

Request

curl -X GET "https://api.rasket.com/automations/{automation_id}/versions" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "list",
  "has_more": false,
  "data": [
    {
      "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5e06",
      "version_number": 2,
      "active": true,
      "trigger_event_name": "trial.started",
      "trigger_segment_id": null,
      "steps": [],
      "connections": [],
      "created_by": {
        "type": "api_key",
        "id": "a4d2f0c8-5b31-4e7a-9c62-8f0b1d4e6a75"
      },
      "created_at": "2026-09-11T12:00:00.000Z"
    }
  ]
}
  • steps and connections are the graph as it was published; they are elided here.
  • To run an earlier version again, PATCH /automations/{automation_id} with its steps and connections. That publishes it as the next version.