Send message (asynchronous)
Queues the message for sending and responds right away with a jobId. The message is sent in
the background, because communicating with the provider can take a few seconds.
The type field defines the kind of message being sent.
Recipient. Provide one of these, in this order of precedence:
| field | when to use |
|---|---|
ticketId | Send inside a ticket that already exists. Takes precedence over the other two. |
contactId | Send to a contact that already exists, on any channel. Required on channels without a phone number (Instagram, Facebook/Messenger, Webchat, Telegram) — on them you can only message someone who has already talked to the channel. Takes precedence over number. |
number | Phone channels (WhatsApp, RCS). If there is no contact with this number yet, one is created. Not valid on channels without a phone number. |
The recipient is checked before the message is queued:
| code | when it happens |
|---|---|
ERR_API_CONTACT_NOT_IDENTIFIED (400) | None of ticketId, contactId or number — or only number on a channel without a phone number. |
ERR_API_CONTACT_NOT_FOUND (404) | contactId does not exist or belongs to another company. |
ERR_API_CONTACT_UNREACHABLE (422) | The contact cannot receive on this channel: no previous conversation on it (channels without a phone number; on Webchat, no visitor session on this webchat) or no phone number (phone channels). |
Interactive on Webchat. The webchat renders the same interactive messages as the official
WhatsApp API that do not depend on a Meta resource: button, list, cta_url,
location_request_message and carousel. On it, interactive is checked before the message is
queued, with the WhatsApp limits, and the problem comes back right away: 422 with the code
ERR_API_INTERACTIVE_INVALID and, in message, the field and the reason (for example
interactive.action.buttons: de 1 a 3 botões). flow, product, product_list,
catalog_message, address_message, voice_call and call_permission_request do not exist on
webchat. On the other channels the provider does the checking, during the send.
Use Idempotency-Key here. If the call times out and you retry without this key, the
contact may receive the same message twice.
Media is checked before it enters the queue. With type: media, the file is read during the
call itself, and not during the background send — so a problematic file gets a 400 right away,
instead of returning a jobId that would fail later with no warning:
| code | when it happens |
|---|---|
ERR_API_MEDIA_EMPTY | The uploaded file has 0 bytes. |
ERR_API_MEDIA_TYPE_UNKNOWN | There is no way to tell the type: the name came without an extension and the Content-Type of the multipart part was not provided. |
ERR_API_MEDIA_TYPE_MISMATCH | The file contents contradict the declared type (for example, a PDF sent as an image). |
A difference only in format within the same category is not rejected: a PNG declared as JPEG is sent normally. The type used for sending is always the one from the file contents.
curl --request POST \
--url https://api.connectadesk.com/api/v1/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"channelId": 4,
"type": "text",
"number": "5511999999999",
"contactName": "Marina Alves",
"body": "Olá, Marina! Seu pedido #88213 foi confirmado."
}
'{
"data": {
"jobId": "1841",
"status": "queued"
}
}Authorizations
API token in the sk_live_… format.
Headers
Unique key for the operation. If you repeat the call with the same key and the same body, you get the stored response.
200Body
Channel where the conversation takes place. See the available channels at GET /channels.
4
Type of message. It defines which other fields are required:
| value | what it requires |
|---|---|
text | body with the text. |
media | Sent as multipart/form-data, with the file in medias. |
template | template with name and parameters. Required outside the WhatsApp 24h window. |
interactive | interactive in the official WhatsApp API format (buttons, list, link, location request, carousel). |
text, media, template, interactive Recipient on phone channels (WhatsApp, RCS): digits only, with country and area code. If there is no contact with this number yet, one is created. Not valid on channels without a phone number.
"5511999999999"
Recipient by the id of a contact that already exists, on any channel. Required on channels without a phone number (Instagram, Facebook/Messenger, Webchat, Telegram) — on them you can only message someone who has already talked to the channel. The contact must belong to the token's company. Takes precedence over number.
842
Sends inside a ticket that already exists. Takes precedence over contactId and number.
9034
Name given to the contact if it is created by this send (only with number).
"Marina Alves"
Message text, or caption when type: media. Accepts system variables (e.g. {{name}}).
"Olá, Marina! Seu pedido #88213 foi confirmado."
Required when type: template. Accepts the simple form ({ name, parameters }), which is the
recommended one: the API validates the template and builds the message. It also accepts the fully built object with
components, for those who already work with that format.
Show child attributes
Show child attributes
{
"name": "confirmacao_pedido",
"parameters": { "body": ["Maria", "12345"] }
}
Required when type: interactive. The interactive object of the official WhatsApp API (Cloud API),
the same on every channel that has interactive messages: the payload you already send to official
WhatsApp works on Webchat with no changes.
On Webchat, the types and the limits checked during the call:
type | what it takes | limits |
|---|---|---|
button | body, action.buttons[] (type: reply, reply.id, reply.title); optional header and footer | 1 to 3 buttons; title up to 20; id up to 256, no repeats |
list | body, action.button (text of the button that opens the list), action.sections[].rows[] (id, title, description); optional text header and footer | 1 to 10 sections, 1 to 10 rows in total; button up to 20; row title up to 24; description up to 72; section title up to 24 (required with more than one section); id up to 200 |
cta_url | body, action.name: cta_url, action.parameters.display_text and url (http or https); optional header and footer | button text up to 20 |
location_request_message | body, action.name: send_location | no header |
carousel | body, action.cards[]: header (image or video), body and one link button (action.name: cta_url) or reply buttons (action.buttons[], type: quick_reply) | 1 to 10 cards |
On all of them: body.text is required, up to 1024 characters (list: 4096); text header up to 60;
footer up to 60. A media header (image, video, document) only by public http(s) link —
the webchat does not use media by Meta id.
The contact's choice arrives as it does on WhatsApp: a text message with the option title, replying to (quoting) the interactive message.
{
"type": "button",
"body": {
"text": "Podemos confirmar a entrega para amanhã?"
},
"action": {
"buttons": [
{
"type": "reply",
"reply": { "id": "sim", "title": "Sim" }
},
{
"type": "reply",
"reply": { "id": "nao", "title": "Reagendar" }
}
]
}
}
Moves the ticket to this queue after sending.
7
Reopens the ticket if it is closed.
Closes the ticket after sending.
Wrap-up recorded when the ticket is closed with closeTicket.
12
Response
Accepted and queued for sending.
Show child attributes
Show child attributes
curl --request POST \
--url https://api.connectadesk.com/api/v1/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"channelId": 4,
"type": "text",
"number": "5511999999999",
"contactName": "Marina Alves",
"body": "Olá, Marina! Seu pedido #88213 foi confirmado."
}
'{
"data": {
"jobId": "1841",
"status": "queued"
}
}
