Skip to main content
Sends one message to one person, with failover: each step of the route names a channel, what counts as done on it (sent, delivered, read, or answered for a call) and how long to wait. A channel that refuses, fails or runs out of time hands over to the next. The first step is tried before the answer comes back; what happens next arrives as message.* webhook events, or read it back with GET /v1/messages/{message_id}.
Needs the messages:send scope.

Body

What each channel takes as content: SMS {"text"}; WhatsApp {"text"} inside the 24-hour window, and {"template", "language", "params"} (an approved WhatsApp template and its values, in order) outside it. A message to someone who has asked not to be contacted fails at once on every channel; one inside their quiet hours is postponed until they end. Send an Idempotency-Key header to make a retry safe: the same key with the same body is answered once, and the first answer repeated (with Idempotent-Replayed: true).

Request

Response

202 Accepted — the message as it stands after its first step.

The message

An attempt is refused when its channel can’t take the message now and the next step runs at once. Its code says why: channel_off, no_content, window_closed (WhatsApp’s 24-hour window is closed and no approved template was given), no_dlt_match (the SMS text fills in none of your registered DLT templates), not_permitted or provider_refused.

Errors

Every refusal is {"error": {"code", "message", "field"}}; field is there when one input is at fault. Any request can also be refused for its key, its account or its rate (key_required, invalid_key, account_suspended, plan_excludes_api, address_not_allowed, rate_limited); see the overview.