Start a conversation

View as Markdown
Sends a first message to a phone number on WhatsApp or to an email address, and records it as a conversation so the recipient's reply threads into it. This is the endpoint behind the dashboard's "New message" composer. Use it when you have an address but not necessarily a contact. If you already have a `contactId` and do not need the message in a thread, `POST /api/whatsapp/send` and `POST /api/email/send` are the lower-level sends. **How it works.** 1. The recipient is validated: E.164 for `whatsapp`, a valid address for `email`. 2. The contact is looked up anywhere in the workspace. Email matching ignores case; WhatsApp matches `whatsapp_number` exactly. An unknown recipient is created in the workspace's "Manual Conversations" campaign. A contact already enrolled elsewhere is **not** moved. 3. The message is delivered through the channel's provider, with every guard of the lower-level send applied (compliance, opt-out, 24-hour window, daily cap). 4. Only after delivery succeeds is the conversation found, reopened or created, using the same thread key inbound messages use, and the message stored with `metadata.manual = true`. On WhatsApp, pass `templateId` to reach a contact outside WhatsApp's 24-hour window. `message` is then optional, and the thread records `[template] <templateId>` as the content. On email, `subject` is required. `webchat`, `instagram` and `messenger` cannot be started from here. **Side effects.** Sends a real WhatsApp message or a real email from the workspace's connected mailbox. Consumes one unit of the channel's daily send cap. The unit is refunded if the provider rejects the send. It does **not** draw on the AI-message allowance. The AI reply to the contact's answer does. May create a contact, and the "Manual Conversations" campaign on first use. Broadcasts a realtime update to the dashboard and writes an audit entry. **Idempotency.** Not idempotent. A retry after a timeout delivers the message a second time. The conversation row is reused, so both copies land in the same thread. Check `GET /api/conversations/{conversationId}` before retrying. **Webhook events.** `audit.log_recorded` for subscribers that selected it explicitly. See [Webhooks](/webhooks). **Access** - **Required scope:** `write`. - **Rate limit:** General API (120–600 requests/min per workspace by plan) **and** the configuration-mutations limiter — 10 requests/min per workspace, a budget shared with other configuration mutations. See [Rate limits](/rate-limits). - **Plan:** Available on every plan. The workspace needs at least one agent, a WhatsApp sender that is `ONLINE` for WhatsApp, and a connected mailbox for email.

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

message is required unless channel is whatsapp and templateId is sent. subject is required when channel is email. Strings are trimmed before validation.

recipientstringRequired1-254 characters

Who to write to. An E.164 phone number (+ and country code) for whatsapp; an email address for email. An invalid value returns 400 with Phone number must be E.164 format (e.g. +14155551234) or Invalid email address.

channelenumRequired
Channel to start the conversation on. - `whatsapp`: sent from the workspace's WhatsApp sender. - `email`: sent from the workspace's connected Gmail, Outlook or Zoho Mail mailbox.
Allowed values:
messagestringOptional1-4096 characters

Text of the message, sent exactly as written. Required unless a WhatsApp templateId is sent. On WhatsApp freeform text is only accepted inside the 24-hour window.

subjectstringOptional1-998 characters

Email subject. Required when channel is email; ignored on WhatsApp.

templateIdstringOptionalformat: "uuid"

WhatsApp only. Id of one of the workspace’s WhatsApp templates. It must be approved, or the call fails with 422 TEMPLATE_NOT_APPROVED. Templates can be sent regardless of the 24-hour window.

templateVariableslist of strings or map from strings to stringsOptional

Values for the template placeholders. Either an ordered list, where the first item fills {{1}}, or an object keyed by placeholder number. Ignored without templateId.

Response

Message delivered and recorded in the conversation.
dataobject

Errors

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