Sending messages
One command, the payload shapes a line takes, and the ones it carries.
Everything you send — a plain sentence, a link card, a photo, a poll — goes through one
command: POST /v1/commands/message.send.
The body is always two objects. target says where the message goes, payload
says what it is.
{
"target": {
"kind": "conversation",
"conversationId": "a0000000-0000-4000-8000-000000000001"
},
"payload": { "text": "Your table is ready." }
}A call the API accepts returns 202 with an id you can correlate later:
{ "commandId": "cmd-1", "status": "queued", "disposition": "queued" }202 means queued, not delivered
The 202 tells you the command was durably queued and nothing more — the outcome settles on the
response stream. What a line cannot carry never gets that far: a
payload key it does not take that carries a value, a kind included, is refused with
422 validation_failed at payload.<key> before anything is queued.
The API checks the body before anything is queued, contents included. A body
over 65,536 bytes is 413 payload_too_large, and one that is not JSON is
400 bad_request. A body, target or payload that is not an object is
422 validation_failed, and so is a target that names nobody (details points
at target.recipientExternalId), a payload with no text (payload.text) and a
payload key the line does not carry (payload.<key>).
The payload shapes
What a payload may carry is decided per channel, by the line the send resolves
to. An iMessage line, live or test, carries plain text — with an effect and
a subject beside it on a conversation the contact has written into, and
textFormatting for bold, animated or
mention ranges — and six kinds in place of the text: a photo or file by link (media), an emoji sticker, a rich_link, a multipart — text and photos as one message — a location_request and a poll.
kind | What it sends | Target | Where it can go |
|---|---|---|---|
| omitted | Plain text — with effect and subject on a confirmed conversation or a group chat | conversation or recipient | Any thread |
media | A photo or file by https link | conversation | Into a confirmed conversation or a group chat |
rich_link | A URL that Messages renders as a preview card | conversation | Into a confirmed conversation or a group chat |
sticker | An emoji or an uploaded image, optionally placed on a message | conversation | The emoji, or an image by link, into a confirmed conversation or a group chat |
multipart | Text and photos as one message, in the order given | conversation | Into a confirmed conversation or a group chat |
location_request | Apple's "Share My Location?" card | conversation | Into a confirmed conversation |
poll | A question with 2 to 12 choices | conversation | Into a confirmed conversation or a group chat |
See Stickers, Rich links and What a line carries.
Two ways to address a send
message.send accepts two of the three target
kinds. The target says who the message is for; it does not
decide how the message travels.
A conversation target replies into a thread you already know about. Its
id comes from an inbound message event on the stream.
A recipient target opens a new thread from an address.
On a live iMessage line the thread, not the target, chooses the
path. A thread the transport has confirmed is with that one contact — it
confirms one the first time the contact writes into it — or has reported as a
group chat takes the conversation path; into a group chat a message reaches
every member, and every kind goes but a location request. That path carries every kind in the table, and an effect, a subject, textFormatting and a quoted reply; a command on it that the line has not taken within 30 seconds settles expired. Every
other thread takes the recipient path, whichever target named it. That path
lets a command wait five minutes, and it:
- carries plain text alone — an
effect, asubjectortextFormattingbeside it is refused with422 validation_failedatpayload.<key>, akindas described below, and a reply attarget.replyToMessageId, before anything is written; - refuses a text that is blank or over 16,384 bytes:
422 validation_failed, withinvalid_textas the entry'sreason; - sends to a phone number in E.164 form, never an email address: an email is
422 validation_failedat the target field you wrote it at (target.recipientExternalId, or whichever of its spellings you used), and attarget.conversationIdwhen it is the peer of a thread you named that takes this path. A group conversation the transport has not named yet is refused attarget.conversationIdtoo.
In test an email address sends. A media link, a sticker, a rich link, a multipart, a location request or a poll into a thread the transport has neither confirmed nor reported as a group chat is 422 validation_failed with
reason: conversation_not_confirmed, at target.conversationId or the
recipient key you wrote: send the person a text first. A location request into
a group chat is refused the same way, and no text changes that: send it into a
member's own one-to-one conversation.
Both targets honour Idempotency-Key: the platform records every send's key
before the line is asked, so a retried send is never delivered twice. It is
adopted when a transport took the first attempt, and refused with
409 conflict when none did — see Idempotency.
The usual pattern is to open with a plain recipient send, wait for the conversation to appear on
the stream, then use its conversationId for everything after. See Addressing a
conversation.
Pick a payload
Text and rich text
The workhorse: plain text, byte limits, effects, subject lines and threaded replies.
Message effects
The 13 bubble and full-screen effects, and who actually sees them.
Rich links
Send a URL as a preview card you do not control.
Stickers
One emoji, placed on a message — or sent as a bubble of its own.
Multipart messages
Text and photos as one message: a caption, an album, or both interleaved.
Location
Ask a contact to share their location, and receive it as events.
Edits and unsends
Change or take back what the line sent, and hear when a contact does.
Polls
Send a poll into a conversation, vote on a poll — yours or a contact's — and read every vote as an event you opt into.
Attachments
Send a photo or file by link, and receive the ones people send you.
Related
Projects with several lines
How a project with many numbers decides which one speaks, how to choose one yourself, and which number to show somebody who will text you first.
Text and rich text
Plain sends and the UTF-8 byte limit — and the effects, subject lines and threaded replies a confirmed conversation carries.