Send a template message
/v1/template-messagesSend an approved WhatsApp template to a customer.
A send that is taken answers 202 with status accepted as soon as the
sending service has it — the reply carries no delivery outcome. Poll
GET /template-messages/{event_id} for what became of it; no webhook
reports a send outcome today.
Idempotent on event_id: repeating one returns the state of the first
request and never produces a second message.
A 422 names the offending field: a phone outside strict E.164, a template
that is not approved for this merchant in that language, or a missing
template variable. It also covers the two account-level refusals that no
payload can fix — an account that is not on the conversational rail this
API sends from, and an account with no connected WhatsApp sender number —
each carrying its own type. Neither is worth a retry.
An event older than the freshness window, or one whose conversation is
paused, is not an error either: it answers 200 with status discarded
and the reason in status_detail.
A 402 means the account cannot pay for the message and nothing was sent.
insufficient_funds and wallet_sends_paused clear as soon as the account
adds funds, and the same event_id may be sent again once it has;
wallet_currency_mismatch needs us. Retrying without adding funds returns
the same answer.
Ejemplo
curl -X POST "https://api.ya.onl/v1/template-messages" \
-H "X-API-Key: yv_live_v1_…" \
-H "Content-Type: application/json" \
-d '{"event_id":"…","phone":"…","template":"…"}'Cuerpo de la petición
event_idstringYour identifier for the event. Idempotency key and lookup key for the status endpoint; must be stable across retries. The charset is bounded because this value travels in the status URL
phonestringDestination phone in strict E.164 (+ country code, 8-15 digits). A number outside the format is rejected with 422 — the country code is never inferred
templateTemplateRefApproved template to send, by name and language
variablesobjectTemplate variable values, keyed exactly as required_variables lists them in GET /v1/templates: by position on a positional template ("1" fills {{1}}), by name on a template authored with named placeholders ("name" fills {{name}}). A missing or unknown key is a 422
occurred_atstring | nullISO 8601 UTC timestamp of the originating event. An event older than the freshness window is discarded instead of sent
metadataTemplateMessageMetadata | nullOptional attribution metadata
Respuestas
200event_id had already been received and the stored state is returned, or the event settled without being sent202GET /template-messages/{event_id} for it401402type says which: insufficient_funds (no funds left), wallet_sends_paused (sending stopped when the funds ran out) or wallet_currency_mismatch. The first two clear as soon as the account adds funds, and sending resumes on its own; the third does not and needs us. Retrying without adding funds returns the same answer403outbound:send scope409event_id is bound to a different message, or it aged out of the idempotency window. Send the event under a new event_id422429502