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.
  • TemplatesGuidesFifty-seven starters sorted by goal, and how to keep a campaign as a template.
  • 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.
  • Mail appsGuidesComing soon: your Rasket address in Apple Mail, Outlook and the Gmail app.
  • Inbox APIGuidesOpen, read and answer support conversations from your app, with the same key.
  • Support inbox in your appGuidesA Contact us form that opens a conversation your team answers, in five minutes.
  • Replies to your emailsGuidesOne field on a send, and the customer's reply opens a conversation.
  • Let an agent triageGuidesAn AI agent reads, notes and drafts over MCP; a person sends.
  • 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, Zapier and n8n, a WordPress plugin, and Notion contacts.
  • 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.
  • VercelGuidesAdd Rasket on Vercel: a Sending key in each project as RASKET_API_KEY, no copying.
  • WordPressGuidesThe Rasket plugin: every email your site sends, through Rasket, with a safe fallback.
  • NotionGuidesTurn a Notion database of people into contacts in a segment, once or every hour.
  • Migrating to RasketGuidesBring contacts, unsubscribes, lists and templates from Mailchimp, Klaviyo and more.
  • 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.
  • InboxAPI referenceChannels, conversations, messages, notes and search in your support inbox.

API referenceTemplates

Templates

Reusable email content with typed variables. Write it once, publish it, and send it by ID or alias with the values filled in.

Versions

A template is a name, an optional alias, and a series of versions of its content — from, subject, reply_to, html, text and the variables they use. Creating a template writes version 1 as a draft. publish makes the current version the one sends use; updating a published template opens the next draft without changing what is sent, until you publish again.

  • Retrieving a template shows the current version. When that is an open draft, has_unpublished_versions is true.
  • A send records the exact version it used, so a later edit never changes what an already-sent email said.
  • Only a published template can be sent. Naming a draft in POST /emails is 422 invalid_parameter.
  • A send may leave out from and subject when the published version sets them. Values in the request win. If neither has one, the send is 422 missing_required_field.

Variables and placeholders

A placeholder is {{key}} — or {{ key }} — with the key matching ^[A-Za-z0-9_]+$. There is no logic, no filter and no nesting: a value that contains {{other}} is inserted as that literal text, never expanded. Every placeholder the bodies use must be declared in variables, and every declared variable must be used, so an editor can point at exactly what is wrong.

Sends supply values as strings or numbers. A value is checked against the declared type; a key the send omits takes the variable's fallback_value, and a declared key with neither is 422 missing_required_field.

How each variable type renders
TypeRendered as
stringInserted as written: HTML-escaped in html, raw in subject and text.
numberWritten out as a number.
booleantrue or false.
objectCompact JSON, HTML-escaped in html.
listCompact JSON, HTML-escaped in html.

Show-when rules, repeats and event data

A visual template can show a block or a section only to some contacts. Its rule is a list of conditions that must all, or any, hold: a contact field or property (the same { field, op, value } a segment filter uses), a topic subscription, membership of a segment, or a property of the flow's trigger event. A rule that names a deleted property, topic or segment hides the block; the send still goes.

A template made for a flow names its trigger event. It can then print the event's data with {{{event.order_id}}} and repeat a group of blocks once per item of a list in it. Inside a repeat, each item is {{{item.name}}}. A missing or empty list draws nothing, and a repeat draws at most 50 items.

An event or item value can end with a fallback and a format: {{{item.total|0|currency:USD}}}, {{{event.placed_at|date:short}}}, {{{item.quantity|number:0}}}. Dates take short, medium or long and print in UTC; currencies take a three-letter code; numbers take 0 to 6 decimals. Output is in US English. A format a save cannot read is 422 validation_error.

Rules are decided per contact when a campaign or a flow sends. A send through POST /emails, a preview and a test have no contact to decide for: they show every block and draw no repeated items.

Addressing a template

  • Every {id} below accepts the template's UUID or its alias. An alias is lower-case, may not be a UUID, and is unique among the team's live templates.
  • Reading and listing work with either kind of key. Creating, updating, publishing, duplicating and deleting need a full_access key; a sending_access key gets 401 restricted_api_key.
  • A template in another team is 404 not_found, indistinguishable from one that does not exist.

Blocks and saved blocks

A template made in the dashboard's visual editor is a layout of sections, each one to three columns, holding blocks: heading, text, image, button, divider, spacer, social, footer, card, video, menu, countdown, html and preheader. Rasket compiles the layout into the version's html and text each time it is saved.

  • A video is its thumbnail and a caption, both linking to where it plays: no inbox plays video. A countdown names its end date in words, and can show a timer picture a countdown service draws each time the email is opened.
  • An html block is your own markup. Scripts, event handlers, style sheets, javascript: links and embeds are removed before it is sent.
  • A preheader is the line most inboxes show after the subject. An email has one, and it comes first.
  • A saved block is a header, a footer or any block or section saved once and placed in many templates. Editing it publishes the change to every template whose published version uses it; deleting it leaves each template sending the copy it last had. A template created from a starter wears your saved header and footer.

Before you send

POST /templates/{id}/checks runs the pre-send checks over a version, rendered as the preview renders it: links, variables with no value, the subject and preview text, alt text, image weight, text beside images, and the unsubscribe link. Each is pass, warn or fail. Nothing is gated on a template; a campaign made from one is checked again when it is sent. Links are read, never visited.

Endpoints

Create a template

POST /templates

A new draft, holding version 1 of its content.

Body

  • namestringRequired

    A name for the dashboard.

  • aliasstring

    A short name to address the template by instead of its ID: lower-case letters, digits, - and _, starting with a letter or digit, at most 63 characters, and never a UUID. Unique among the team's templates.

  • fromstring

    The sender, as Name <address@domain> or a bare address. A send that names its own from overrides it.

  • subjectstring

    The subject line. May carry {{key}} placeholders.

  • htmlstring

    The HTML body. May carry {{key}} placeholders. On create, send this or starter — exactly one.

  • textstring

    The plain-text body. May carry {{key}} placeholders.

  • variablesobject[]

    The variables the bodies use, at most 200: { key, type, fallback_value }, with type one of string, number, boolean, object or list. Every {{key}} must be declared here, and every declared key must be used.

  • starterstring

    The slug of a starter template to copy instead of writing html. Its subject, layout and variables become version 1: the copy opens in the dashboard's visual editor, and its HTML and plain text are compiled from the layout. Send this or html, never both.

2 more fields (reply_to, brand_overrides)
  • reply_tostring[]

    Reply-to addresses.

  • brand_overridesobject | null

    This template's own values for your brand fields, for a one-off that should not wear the project brand: logo_url, primary_color, accent_color, font, button_style, company_name, address, footer_text. A field you leave out follows the project brand; a field set to null uses our plain default even when your brand sets one. null for the whole object means this template pins nothing.

Request

curl -X POST "https://api.rasket.com/templates" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Welcome",
  "alias": "welcome",
  "subject": "Welcome, {{name}}",
  "html": "<p>Hello {{name}}, thanks for joining.</p>",
  "variables": [
    {
      "key": "name",
      "type": "string",
      "fallback_value": "there"
    }
  ]
}'

Response 201

{
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
  "object": "template"
}
  • A new template is a draft. Nothing can be sent from it until you publish it.
  • Send exactly one of html and starter. Neither is 422 missing_required_field; both is 422 invalid_parameter. The schema cannot express "exactly one", so a client will not catch it for you.
  • starter is one of the slugs GET /starters lists. Any other value is 400 validation_error.
  • With starter, anything else you send wins over the starter's: subject, text and variables override it, and alias, from and reply_to are yours to set. A text you send is kept as the plain text instead of the one generated from the layout. The copy keeps no link to the library, so improving a starter never changes it.
  • This route takes no Idempotency-Key. A retry with no alias creates a second template; set an alias, or check the list first.
  • A {{key}} the bodies use but variables does not declare — or a declared key the bodies never use — is 422 validation_error, with one entry in errors[] per key.
  • An alias another live template holds is 422 validation_error. Deleting a template frees its alias.
  • brand_overrides is not a send variable and declares nothing: a brand field is your project's and a {{key}} is the recipient's, so the declaration rule never sees one.
  • An unknown field name inside brand_overrides is 400 validation_error rather than ignored, and a font or button_style outside its list is too. Everything else it refuses is 422 invalid_parameter.

List templates

GET /templates

Every template, most recently changed first.

Query parameters

  • 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

    Only templates whose name or alias contains this, ignoring case. At most 200 characters.

  • statusstring

    Only templates in this status: draft or published.

Request

curl -X GET "https://api.rasket.com/templates?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-6f2b8a0e5d17",
      "name": "Welcome",
      "status": "published",
      "published_at": "2026-09-11T12:00:00.000Z",
      "created_at": "2026-09-11T12:00:00.000Z",
      "updated_at": "2026-09-11T12:00:00.000Z",
      "alias": "welcome"
    }
  ]
}
  • Items carry no content. Retrieve one template for its bodies and variables.
  • alias is present only on templates that have one.

Retrieve a template

GET /templates/{id}

By ID or by alias, with the current version's content.

Path parameters

  • idstringRequired

    The template's ID or its alias. An alias is matched case-insensitively.

Request

curl -X GET "https://api.rasket.com/templates/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "template",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
  "current_version_id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d18",
  "name": "Welcome",
  "alias": "welcome",
  "from": "Acme <hello@acme.com>",
  "subject": "Welcome, {{name}}",
  "reply_to": null,
  "html": "<p>Hello {{name}}, thanks for joining.</p>",
  "text": "Hello {{name}}, thanks for joining.",
  "variables": [
    {
      "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d19",
      "key": "name",
      "type": "string",
      "fallback_value": "there",
      "created_at": "2026-09-11T12:00:00.000Z",
      "updated_at": "2026-09-11T12:00:00.000Z"
    }
  ],
  "brand_overrides": null,
  "created_at": "2026-09-11T12:00:00.000Z",
  "updated_at": "2026-09-11T12:00:00.000Z",
  "status": "published",
  "published_at": "2026-09-11T12:00:00.000Z",
  "has_unpublished_versions": false
}
  • The content shown is the **current** version — the open draft, if there is one. has_unpublished_versions: true means it differs from what sends use.
  • alias, from, subject and text are absent, not null, when unset.
  • brand_overrides is null when the template pins nothing, and carries only the fields it does pin — the rest come from your project brand.
  • A template that belongs to another team, or that has been deleted, is 404 not_found.

Update a template

PATCH /templates/{id}

Write the draft. Sends keep using the published version.

Path parameters

  • idstringRequired

    The template's ID or its alias. An alias is matched case-insensitively.

Body

  • namestring

    A new name.

  • aliasstring | null

    A new alias, or null to remove the current one.

  • fromstring | null

    The sender, as Name <address@domain> or a bare address. A send that names its own from overrides it. null clears it.

  • subjectstring | null

    The subject line. May carry {{key}} placeholders. null clears it.

  • htmlstring

    The HTML body. May carry {{key}} placeholders. On create, send this or starter — exactly one.

  • textstring

    The plain-text body. May carry {{key}} placeholders.

  • variablesobject[]

    The variables the bodies use, at most 200: { key, type, fallback_value }, with type one of string, number, boolean, object or list. Every {{key}} must be declared here, and every declared key must be used.

2 more fields (reply_to, brand_overrides)
  • reply_tostring[]

    Reply-to addresses.

  • brand_overridesobject | null

    This template's own values for your brand fields, for a one-off that should not wear the project brand: logo_url, primary_color, accent_color, font, button_style, company_name, address, footer_text. A field you leave out follows the project brand; a field set to null uses our plain default even when your brand sets one. null for the whole object means this template pins nothing.

Request

curl -X PATCH "https://api.rasket.com/templates/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0" \
  -H "Content-Type: application/json" \
  -d '{
  "subject": "Welcome aboard, {{name}}"
}'

Response 200

{
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
  "object": "template"
}
  • On a published template with no open draft, the first update starts a new version; later updates edit that draft in place. Publish it when it is ready.
  • Only the fields you send change. The declaration rule applies to the merged result: the bodies after your change must still declare and use exactly the same keys as variables.
  • An empty body is 422 invalid_parameter.
  • brand_overrides replaces what the template pinned rather than merging into it: send the whole set you want, or null to stop pinning anything. A per-field merge could not tell "stop pinning the accent colour" from "leave the accent colour alone".
  • On a template built in the dashboard's visual editor — which every copy of a starter is — an html that differs from the stored one switches it to code editing: the update starts a new version holding your HTML and no layout — even over an open draft — and keeps the plain text unless you send text too. Sending back the unchanged html switches nothing, and restoring an earlier version from the history brings the visual editor back.

Delete a template

DELETE /templates/{id}

Remove it and free its alias.

Path parameters

  • idstringRequired

    The template's ID or its alias. An alias is matched case-insensitively.

Request

curl -X DELETE "https://api.rasket.com/templates/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "template",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
  "deleted": true
}
  • The template answers 404 not_found from this moment, and a send that names it is 422 invalid_parameter.
  • Emails already sent from it keep their record of which version they used.

Publish a template

POST /templates/{id}/publish

Make the current version the one sends use.

Path parameters

  • idstringRequired

    The template's ID or its alias. An alias is matched case-insensitively.

Request

curl -X POST "https://api.rasket.com/templates/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/publish" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
  "object": "template"
}
  • Publishing takes effect for the next send. Emails already queued keep the version they resolved.
  • Publishing a template whose current version is already published changes nothing and still answers 200.

Duplicate a template

POST /templates/{id}/duplicate

A new draft holding a copy of the current version.

Path parameters

  • idstringRequired

    The template's ID or its alias. An alias is matched case-insensitively.

Request

curl -X POST "https://api.rasket.com/templates/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/duplicate" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d2a",
  "object": "template"
}
  • The copy is named <name> (copy), has no alias, and is a draft. The source is untouched.
  • What is copied is the current version — the open draft, if there is one — not the published one.

Preview a template

POST /templates/{id}/preview

Render a version with values filled in, the way a send would. Nothing is stored.

Path parameters

  • idstringRequired

    The template's ID or its alias. An alias is matched case-insensitively.

Body

  • variablesobject

    Values by key, strings or numbers, as a send takes them. An undeclared key or a value of the wrong type is 422 invalid_parameter.

  • versioninteger

    The version number to render. The current version when absent.

Request

curl -X POST "https://api.rasket.com/templates/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/preview" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0" \
  -H "Content-Type: application/json" \
  -d '{
  "variables": {
    "name": "Ronald"
  }
}'

Response 200

{
  "object": "template_preview",
  "template_id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
  "version_number": 1,
  "subject": "Welcome, Ronald",
  "html": "<p>Hello Ronald, thanks for joining.</p>",
  "text": "Hello Ronald, thanks for joining.",
  "missing_variables": []
}
  • A declared variable with neither a value nor a fallback is listed in missing_variables, and its placeholder is left in place.
  • html has been sanitised, with remote images withheld. Show it in a sandboxed iframe, never straight in a page.

Check a template

POST /templates/{id}/checks

The pre-send checks over a version, rendered as the preview renders it. Nothing is stored.

Path parameters

  • idstringRequired

    The template's ID or its alias. An alias is matched case-insensitively.

Body

  • variablesobject

    Values by key, as the preview takes them. The body may be omitted.

  • versioninteger

    The version number to check. The current version when absent.

Request

curl -X POST "https://api.rasket.com/templates/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/checks" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0" \
  -H "Content-Type: application/json" \
  -d '{
  "variables": {
    "name": "Ronald"
  }
}'

Response 200

{
  "object": "email_checks",
  "checks": [
    {
      "code": "alt_text",
      "status": "warn",
      "title": "Alt text",
      "message": "1 image has no alt text. Readers with images off, or using a screen reader, get nothing in its place."
    },
    {
      "code": "links",
      "status": "pass",
      "title": "Links",
      "message": "2 links, all well-formed. Checked as written, without visiting them."
    }
  ]
}
  • Advisory: nothing is gated on a template. A campaign made from it is checked again when it is sent.
  • A visual template's findings can name the block they are about, in block_id.

Send a test of a template

POST /templates/{id}/test

Send the current version to up to five inboxes.

Path parameters

  • idstringRequired

    The template's ID or its alias. An alias is matched case-insensitively.

Headers

1 more field (Idempotency-Key)
  • Idempotency-Keystring

    Retries with the same key send the test once.

Body

  • tostring[]Required

    One to five addresses.

  • fromstring

    The sender for the test. Needed when the template has none.

  • variablesobject

    Values by key, strings or numbers. A variable you leave out uses its fallback; one without a fallback must be given.

Request

curl -X POST "https://api.rasket.com/templates/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/test" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0" \
  -H "Content-Type: application/json" \
  -d '{
  "to": ["you@acme.example"],
  "variables": {
    "name": "Ronald"
  }
}'

Response 202

{
  "object": "template_test",
  "template_id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
  "version_number": 2,
  "data": [
    {
      "id": "4ef9a417-02e9-4d39-ad75-9611e0fcc33c",
      "to": "you@acme.example"
    }
  ]
}
  • The current version is sent: the open draft, if there is one. The subject starts with [Test] .
  • Each test counts as a send. The token also needs permission to send email.

List template versions

GET /templates/{id}/versions

Every version of a template, newest first.

Path parameters

  • idstringRequired

    The template's ID or its alias. An alias is matched case-insensitively.

Query parameters

  • 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.

Request

curl -X GET "https://api.rasket.com/templates/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/versions?limit=20" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "list",
  "has_more": false,
  "data": [
    {
      "object": "template_version",
      "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d18",
      "version_number": 1,
      "current": true,
      "published": true,
      "published_at": "2026-09-11T12:00:00.000Z",
      "created_at": "2026-09-11T12:00:00.000Z",
      "subject": "Welcome, {{name}}",
      "variables": []
    }
  ]
}
  • current is the version you read and edit; published is the one sends use.
  • Bodies are left out. Preview a template with version to see an older version's content.

Restore a template version

POST /templates/{id}/versions/{version_number}/restore

Make a new draft from an earlier version.

Path parameters

  • idstringRequired

    The template's ID or its alias. An alias is matched case-insensitively.

  • version_numberintegerRequired

    The version to copy.

Request

curl -X POST "https://api.rasket.com/templates/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17/versions/{version_number}/restore" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "template",
  "id": "0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17",
  "version_number": 3
}
  • Sends keep using the published version until you publish the new draft.
  • An unpublished draft you had open stays in the version list.

List the starter templates

GET /starters

The curated library a template can be started from.

Query parameters

  • goalstring

    Only the starters for one goal: welcome, launch, newsletter, winback, receipts, event, promotion, digest or basics.

Request

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

Response 200

{
  "object": "list",
  "has_more": false,
  "data": [
    {
      "object": "starter",
      "slug": "receipt",
      "name": "Receipt",
      "summary": "What was paid, for what, and where to find the invoice.",
      "category": "Billing",
      "goal": "basics",
      "kind": "transactional",
      "tags": ["payment", "billing", "plain"],
      "subject": "Your receipt from {{brand.company_name}}",
      "variables": [
        {
          "key": "amount",
          "type": "string"
        }
      ]
    }
  ]
}
  • The same catalogue for every project, in the order the dashboard shows it. It is not paginated.
  • goal is what a starter is for. kind says how a copy is usually sent: campaign, flow or transactional.
  • Items carry no bodies. Retrieve one starter for its HTML and plain text.
  • Pass a slug to create a template as starter to copy it.

Retrieve a starter template

GET /starters/{slug}

One starter in full, with both bodies and sample values.

Path parameters

  • slugstringRequired

    The starter's slug.

Request

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

Response 200

{
  "object": "starter",
  "slug": "receipt",
  "name": "Receipt",
  "summary": "What was paid, for what, and where to find the invoice.",
  "category": "Billing",
  "goal": "basics",
  "kind": "transactional",
  "tags": ["payment", "billing", "plain"],
  "subject": "Your receipt from {{brand.company_name}}",
  "variables": [
    {
      "key": "amount",
      "type": "string"
    }
  ],
  "html": "<p>You paid {{amount}}.</p>",
  "text": "You paid {{amount}}.",
  "sample_variables": {
    "amount": "$42.00"
  }
}
  • {{brand.*}} is your project's brand settings and resolves when the copy is rendered; {{key}} is a send variable and a copy declares every one of them.
  • sample_variables is for previewing only. It is never sent and never stored.
  • A slug that is not one of ours is 404 not_found.

Create a saved block

POST /saved-blocks

A header, a footer or any block your visual templates place by reference.

Body

  • namestringRequired

    At most 100 characters.

  • kindstringRequired

    header, footer or block. A header and a footer are whole sections, and a project has one of each.

  • documentobjectRequired

    The block or section, exactly as the visual editor writes it: a section, or one of the content blocks (heading, text, image, button, divider, spacer, social, footer, card, video, menu, countdown, html). It may not place another saved block or hold a preheader.

Request

curl -X POST "https://api.rasket.com/saved-blocks" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Shared footer",
  "kind": "footer",
  "document": {
    "id": "s-footer",
    "type": "section",
    "layout": "1",
    "style": {
      "background_color": null,
      "padding_top": 16,
      "padding_bottom": 24,
      "full_width": false
    },
    "columns": [
      {
        "id": "c-footer",
        "type": "column",
        "style": {
          "vertical_align": "top"
        },
        "blocks": [
          {
            "id": "b-footer",
            "type": "footer",
            "company_name": true,
            "address": true,
            "footer_text": true,
            "unsubscribe_label": "Unsubscribe",
            "style": {
              "align": "center",
              "color": "#6b7280",
              "font_family": "{{brand.font}}",
              "font_size": 12,
              "line_height": 1.5,
              "padding_x": 24,
              "padding_y": 16,
              "link_color": "#6b7280"
            }
          }
        ]
      }
    ]
  }
}'

Response 201

{
  "object": "saved_block",
  "id": "0192f6f0-5c3a-7b1e-9d2a-4f1e8c7b6a01",
  "name": "Shared footer",
  "kind": "footer",
  "shape": "section",
  "document": {
    "id": "s-footer",
    "type": "section",
    "layout": "1",
    "style": {
      "background_color": null,
      "padding_top": 16,
      "padding_bottom": 24,
      "full_width": false
    },
    "columns": [
      {
        "id": "c-footer",
        "type": "column",
        "style": {
          "vertical_align": "top"
        },
        "blocks": [
          {
            "id": "b-footer",
            "type": "footer",
            "company_name": true,
            "address": true,
            "footer_text": true,
            "unsubscribe_label": "Unsubscribe",
            "style": {
              "align": "center",
              "color": "#6b7280",
              "font_family": "{{brand.font}}",
              "font_size": 12,
              "line_height": 1.5,
              "padding_x": 24,
              "padding_y": 16,
              "link_color": "#6b7280"
            }
          }
        ]
      }
    ]
  },
  "used_in": 0,
  "created_at": "2026-09-11T12:00:00.000Z",
  "updated_at": "2026-09-11T12:00:00.000Z"
}
  • A second live header or footer is 422 invalid_parameter: edit the one you have, or delete it first.
  • Once you have a header or a footer, a template created from a starter wears yours instead of its own.
  • In the dashboard, select a block or a section and save it from the editor's Saved blocks tab.

List saved blocks

GET /saved-blocks

Every saved block, most recently edited first.

Request

curl -X GET "https://api.rasket.com/saved-blocks" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "list",
  "has_more": false,
  "data": [
    {
      "object": "saved_block",
      "id": "0192f6f0-5c3a-7b1e-9d2a-4f1e8c7b6a01",
      "name": "Shared footer",
      "kind": "footer",
      "shape": "section",
      "document": {
        "id": "s-footer",
        "type": "section",
        "layout": "1",
        "style": {
          "background_color": null,
          "padding_top": 16,
          "padding_bottom": 24,
          "full_width": false
        },
        "columns": [
          {
            "id": "c-footer",
            "type": "column",
            "style": {
              "vertical_align": "top"
            },
            "blocks": [
              {
                "id": "b-footer",
                "type": "footer",
                "company_name": true,
                "address": true,
                "footer_text": true,
                "unsubscribe_label": "Unsubscribe",
                "style": {
                  "align": "center",
                  "color": "#6b7280",
                  "font_family": "{{brand.font}}",
                  "font_size": 12,
                  "line_height": 1.5,
                  "padding_x": 24,
                  "padding_y": 16,
                  "link_color": "#6b7280"
                }
              }
            ]
          }
        ]
      },
      "used_in": 4,
      "created_at": "2026-09-11T12:00:00.000Z",
      "updated_at": "2026-09-11T12:00:00.000Z"
    }
  ]
}
  • used_in counts the live templates whose current or published version places the block.
  • It is not paginated.

Retrieve a saved block

GET /saved-blocks/{id}

One saved block, with its content.

Path parameters

  • idstringRequired

    The saved block's ID.

Request

curl -X GET "https://api.rasket.com/saved-blocks/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "saved_block",
  "id": "0192f6f0-5c3a-7b1e-9d2a-4f1e8c7b6a01",
  "name": "Shared footer",
  "kind": "footer",
  "shape": "section",
  "document": {
    "id": "s-footer",
    "type": "section",
    "layout": "1",
    "style": {
      "background_color": null,
      "padding_top": 16,
      "padding_bottom": 24,
      "full_width": false
    },
    "columns": [
      {
        "id": "c-footer",
        "type": "column",
        "style": {
          "vertical_align": "top"
        },
        "blocks": [
          {
            "id": "b-footer",
            "type": "footer",
            "company_name": true,
            "address": true,
            "footer_text": true,
            "unsubscribe_label": "Unsubscribe",
            "style": {
              "align": "center",
              "color": "#6b7280",
              "font_family": "{{brand.font}}",
              "font_size": 12,
              "line_height": 1.5,
              "padding_x": 24,
              "padding_y": 16,
              "link_color": "#6b7280"
            }
          }
        ]
      }
    ]
  },
  "used_in": 4,
  "created_at": "2026-09-11T12:00:00.000Z",
  "updated_at": "2026-09-11T12:00:00.000Z"
}

Update a saved block

PATCH /saved-blocks/{id}

Rename it or change its content, and publish the change to the templates that use it.

Path parameters

  • idstringRequired

    The saved block's ID.

Body

  • namestring

    At most 100 characters.

  • documentobject

    The block or section, exactly as the visual editor writes it: a section, or one of the content blocks (heading, text, image, button, divider, spacer, social, footer, card, video, menu, countdown, html). It may not place another saved block or hold a preheader. A section stays a section, and a block a block.

Request

curl -X PATCH "https://api.rasket.com/saved-blocks/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0" \
  -H "Content-Type: application/json" \
  -d '{
  "document": {
    "id": "s-footer",
    "type": "section",
    "layout": "1",
    "style": {
      "background_color": null,
      "padding_top": 16,
      "padding_bottom": 24,
      "full_width": false
    },
    "columns": [
      {
        "id": "c-footer",
        "type": "column",
        "style": {
          "vertical_align": "top"
        },
        "blocks": [
          {
            "id": "b-footer",
            "type": "footer",
            "company_name": true,
            "address": true,
            "footer_text": true,
            "unsubscribe_label": "Unsubscribe",
            "style": {
              "align": "center",
              "color": "#6b7280",
              "font_family": "{{brand.font}}",
              "font_size": 12,
              "line_height": 1.5,
              "padding_x": 24,
              "padding_y": 16,
              "link_color": "#6b7280"
            }
          }
        ]
      }
    ]
  }
}'

Response 200

{
  "object": "saved_block",
  "id": "0192f6f0-5c3a-7b1e-9d2a-4f1e8c7b6a01",
  "name": "Shared footer",
  "kind": "footer",
  "shape": "section",
  "document": {
    "id": "s-footer",
    "type": "section",
    "layout": "1",
    "style": {
      "background_color": null,
      "padding_top": 16,
      "padding_bottom": 24,
      "full_width": false
    },
    "columns": [
      {
        "id": "c-footer",
        "type": "column",
        "style": {
          "vertical_align": "top"
        },
        "blocks": [
          {
            "id": "b-footer",
            "type": "footer",
            "company_name": true,
            "address": true,
            "footer_text": true,
            "unsubscribe_label": "Unsubscribe",
            "style": {
              "align": "center",
              "color": "#6b7280",
              "font_family": "{{brand.font}}",
              "font_size": 12,
              "line_height": 1.5,
              "padding_x": 24,
              "padding_y": 16,
              "link_color": "#6b7280"
            }
          }
        ]
      }
    ]
  },
  "used_in": 4,
  "created_at": "2026-09-11T12:00:00.000Z",
  "updated_at": "2026-09-11T12:00:00.000Z",
  "templates_published": 3,
  "templates_skipped": []
}
  • A new document reaches what is sent: every live visual template whose published version places the block gets a new version carrying it, compiled and published. templates_published counts them.
  • A template with an unpublished draft keeps the draft as it is; the draft picks the change up the next time it is saved.
  • A template that cannot take the change is named in templates_skipped with the reason, and picks it up when it is next saved.
  • The kind never changes.

Delete a saved block

DELETE /saved-blocks/{id}

Templates that use it keep sending the copy they last compiled.

Path parameters

  • idstringRequired

    The saved block's ID.

Request

curl -X DELETE "https://api.rasket.com/saved-blocks/0199d2f1-4c4e-7a20-9c31-6f2b8a0e5d17" \
  -H "Authorization: Bearer $RASKET_API_KEY" \
  -H "User-Agent: acme-billing/1.0"

Response 200

{
  "object": "saved_block",
  "id": "0192f6f0-5c3a-7b1e-9d2a-4f1e8c7b6a01",
  "deleted": true
}
  • The dashboard's editor marks each place a deleted saved block was used; detach it there to edit that copy.
  • Deleting your header or footer frees the slot for a new one.