mapier docs
Messages

Sending messages

One command, six payload shapes, and how to choose between them.

Everything you send — a plain sentence, a link card, 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:

202 Accepted
{ "commandId": "cmd-1", "status": "queued", "disposition": "queued" }

202 means queued, not delivered

The API does not validate payload at the boundary. A malformed payload — an unknown kind, an effect name that does not exist, a duplicated poll option — still returns 202, then settles failed on the response stream seconds later. The 202 tells you the command was durably queued and nothing more.

The boundary checks the envelope, not the contents. The body must be a JSON object of at most 65,536 bytes carrying a target object and a payload object. Those three conditions do give you a synchronous 400body_too_large, body_not_object and target_and_payload_required respectively — before anything is queued.

The six payload shapes

payload is a union discriminated by kind. Plain text is the exception: it carries no kind at all — only text.

kindWhat it sendsTargetStatus
omittedPlain textconversation or recipientAvailable
rich_textText plus an effect, a threaded reply or a subject lineconversationAvailable
rich_linkA URL that Messages renders as a preview cardconversationAvailable
pollA question with 2–12 optionsconversationAvailable
attachmentA file or voice memoconversationUnavailable — needs an upload endpoint that does not exist
stickerA sticker, optionally pinned to a messageconversationUnavailable — same reason

The two unavailable kinds both require a transferId naming media already staged in Mapier storage, and /v1 exposes no way to produce one. Their schemas are documented on the attachments page so you know what to expect when they land, but you cannot use them today.

Two ways to address a send

message.send accepts two of the three target kinds, and the choice changes more than the address.

A conversation target replies into a thread you already know about. Its id comes from an inbound message event on the stream. This is the only target that accepts rich payloads, it honours Idempotency-Key, and it has a 30-second dispatch deadline.

A recipient target opens a new thread from a phone number or email. It takes plain text only — the server reads payload.text and drops everything else without complaining — and it ignores Idempotency-Key entirely, minting a fresh one per call. A retried recipient send delivers twice.

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

On this page