Reach a contact on WhatsApp

View as Markdown
Delivers something to the contact on WhatsApp without the caller having to know whether WhatsApp's 24-hour window is open. Built for AI agents and automations. - **Window open** (the contact wrote to your line in the last 24 hours): `message` is sent as written. `form` is `freeform`. - **Window closed:** the workspace's **newest approved template** in `language` is sent instead, with no variables. It opens the thread but does **not** carry `message`. `form` is `template`, and `note` says the content still has to be sent once the person replies. If there is no approved template in that language, the call fails with `422 NO_TEMPLATE_AVAILABLE` and nothing is sent. `note` is written for an AI agent to relay honestly. Show or speak what it says, and never claim the material was delivered when `form` is `template`. All the guards of `POST /api/whatsapp/send` apply (compliance, opt-out, daily cap, sender). The message is not added to a conversation thread. **Side effects.** Sends a real WhatsApp message, either freeform or a business-initiated template that WhatsApp bills. Consumes one unit of the daily WhatsApp send cap, refunded if the telephony carrier rejects it. Does not draw on the AI-message allowance. Writes an audit entry. **Idempotency.** Not idempotent. A retry sends again. After a template fallback, a retry sends the template a second time. **Webhook events.** `audit.log_recorded` for subscribers that selected it explicitly. See [Webhooks](/webhooks). **Access** - **Required scope:** `write`. - **Rate limit:** Outbound — 20 requests/min per workspace, fail-closed **and** the configuration-mutations limiter — 10 requests/min per workspace, shared. See [Rate limits](/rate-limits). - **Plan:** Available on every plan. Requires a WhatsApp sender in `ONLINE` status, and an approved template in `language` to reach contacts outside the window.

Authentication

AuthorizationBearer
Workspace API key: `jl_` followed by 64 lowercase hex characters, created by the workspace owner in the dashboard (**Settings → API Keys**) and sent as `Authorization: Bearer jl_...`. The plaintext is shown once, at creation; Jelliu stores only a SHA-256 hash. A workspace can hold up to 25 active keys. | Scope | GET / HEAD | POST / PUT / PATCH / DELETE | Admin-only routes | | --- | --- | --- | --- | | `read` | Yes | No | No | | `write` | Yes | Yes | No | | `full` | Yes | Yes | Yes | Operations restricted to admins or owners reject keys without the `full` scope with `403`, and say so in their description. No key, whatever its scope, can mint or revoke API keys or rotate a webhook secret — that requires a signed-in owner session. A revoked key stops authenticating within about 10 seconds. See [Authentication](/authentication).

Request

This endpoint expects an object.
contactIdstringRequiredformat: "uuid"

Contact to reach. Must belong to the workspace and have a whatsapp_number.

messagestringRequired1-4096 characters
Text to send when the window is open. Not sent when the template fallback is used.
languagestringOptional2-10 charactersDefaults to es

Language code of the fallback template, matched exactly against the template’s language (e.g. es, en, pt_BR).

Response

A message was sent. form says which kind.

dataobject

Errors

400
Bad Request Error
401
Unauthorized Error
403
Forbidden Error
409
Conflict Error
422
Unprocessable Entity Error
423
Locked Error
429
Too Many Requests Error
502
Bad Gateway Error