Skip to main content
The TypeScript SDK is the easiest path on Node, but every SenderKit operation is a plain REST call. Reach for raw HTTP when you’re on a runtime without the SDK, calling from another language, or want to control the request yourself. This guide covers the two essentials the SDK otherwise handles for you — idempotency and scheduling — which live in the HTTP layer.

Base URL & authentication

Every request is authenticated with a Bearer API key. The sk_live_ / sk_test_ prefix selects the environment. See Authentication for creating and managing keys.

Send a message

POST /v1/send accepts the same body shape as the SDK’s send(). It enqueues the message and returns 202 immediately — delivery happens out of band.
The 202 body is:
string
Message id, e.g. "msg_…". Use it to look the message up later.
"queued" | "scheduled"
"scheduled" when you passed a future scheduledAt, otherwise "queued". Don’t assume "queued" — branch on both.
boolean
Whether the request ran against live mode (from the key prefix).
For inline content without a template, send the raw shape (channel + content) to the same endpoint — see the send endpoint for the body schema.

Idempotency

Pass an Idempotency-Key header so a retried request never sends twice. Reusing a key returns the original message instead of creating a new one — make it deterministic for the event you’re reacting to (e.g. welcome:usr_123).
The SDK attaches this header automatically (auto-generating a key when you don’t supply one). Over raw HTTP it’s your responsibility — always set it on sends you might retry.

Schedule for later

Add a scheduledAt field to the body — an ISO 8601 timestamp. It must be in the future and within 30 days. The response comes back with status: "scheduled".
A scheduled message can be canceled before it sends with DELETE /v1/messages/{id} (only while scheduled or queued).

Handle errors

Non-2xx responses return { "error": { "code", "message", "issues"? } }. On 429, back off using Retry-After and retry with the same Idempotency-Key so you don’t duplicate the send. (The SDK does this for you.)

Track delivery

Sending is asynchronous, so poll GET /v1/messages to observe progress. Filter and paginate with query params; correlate to your own records via the metadata you attached at send time.
Fetch one message with GET /v1/messages/{id}. For real-time monitoring, the list endpoint also supports a Server-Sent Events stream with ?tail=1 — see the API Reference.

TypeScript SDK

Retries, idempotency, and batching handled for you.

Sending

Why a queued message hasn’t been delivered yet.

Messages

The status lifecycle behind the message log.

API Reference

Full endpoint, parameter, and schema reference.