Messages

Stickers

Stick one emoji, or an image you link to, onto a message — placed, scaled and rotated — or send it as a bubble of its own, and what a Mac that cannot draw one answers.

A sticker is a picture — one emoji, or an image you link to — drawn on its own as a bubble in the thread, or stuck onto a message the contact sent, at a spot you choose on that bubble. An iMessage line — live or test — sends one as a message.send whose payload has kind: "sticker".

{
  "kind": "sticker",
  "emoji": "👍",
  "attachToMessageExternalId": "guid-1",
  "placement": { "x": 0.95, "y": 0.1, "scale": 0.8, "rotation": 12 }
}

emoji — or url, the https link of an image sticker, exactly one of the two — takes the place of text; there is no text beside a sticker. The three other keys are optional, and placement is allowed only beside attachToMessageExternalId — a sticker sent on its own has nothing to be placed on.

Fields

Prop

Type

Where the sticker lands

Each placement field is a plain JSON number, each is optional, and an omitted one keeps its default. A value is rounded to 4 decimal places before it is checked against its range.

FieldDefaultRangeMeaning
x, y0.5−5 to 6The sticker's centre, as a fraction of the bubble from its top-left corner. Outside 0 to 1 it hangs off the bubble.
scale10.1 to 5Multiplier of the standard size, about 48 pt wide for an emoji.
rotation0−180 to 180Degrees, positive clockwise.

With no placement the sticker lands dead centre and covers a short message. Pick a corner instead — the top right, slightly tilted, reads as a reaction rather than a cover-up:

{
  "kind": "sticker",
  "emoji": "🎉",
  "attachToMessageExternalId": "guid-1",
  "placement": { "x": 0.95, "y": 0.1, "rotation": 12 }
}

In place of emoji, url names an image the platform fetches inside the send and hands to the Mac as the sticker — an https link of at most 2048 characters to a PNG, GIF or JPEG of at most 512,000 bytes and 618 px on a side. Anything else — another format, a larger file, a bigger picture, a link the platform cannot fetch — is 422 validation_failed at payload.url, and nothing reaches the Mac. Everything else on this page holds for an image sticker as it does for an emoji: the same placement, the same message to stick to, the same path.

{
  "kind": "sticker",
  "url": "https://example.com/stickers/thumbs-up.png",
  "attachToMessageExternalId": "guid-1",
  "placement": { "x": 0.95, "y": 0.1, "scale": 0.8 }
}

A test line does not rehearse an image sticker: it refuses one at payload.url. Test the picture against a real handset.

Which message it sticks to

attachToMessageExternalId is the transport's own id for the message — externalId on the message frame that delivered it. Take it from the frame and hand it straight back, the way a tapback names its message.

Stick to messages the contact sent. Your own sends have no iMessage id to name yet: on a live iMessage line the command frame's externalId is null until the transport begins naming the message a send created, so a sticker on one of your own messages has nothing to point at.

A sticker stuck to a message is not a reply to it. A reply is target.replyToMessageId, as on any send, and it is never allowed beside attachToMessageExternalId: one or the other, or the send is 422 validation_failed.

Where a sticker can go

A sticker travels on the line's conversation path and nowhere else — the path a thread takes once the transport has confirmed it is a conversation with that one contact, which happens the first time the contact writes into it. See which path a send takes.

Into any other thread the sticker is refused before anything is written: 422 validation_failed at target.conversationId — or at the recipient key you wrote — with reason: conversation_not_confirmed. Send the person a text first; once they answer, the thread is confirmed and the sticker goes. A group conversation is refused at target.conversationId too, and a sticker to a line on any other channel is 404 unsupported_command with reason: not_on_channel.

A sticker is not a text with a picture

You cannot open a conversation with one. A recipient send to somebody who has never written to the line takes the recipient path, which carries text alone, so the first message to a new contact is text — and the sticker follows once they have replied.

Refused before anything is written

Each of these is 422 validation_failed at the field named, and nothing is queued:

  • emoji that is not exactly one emoji — "👍👍", "👍 ", a word, a digit — at payload.emoji.
  • placement without attachToMessageExternalId, a placement value outside its range or not a number, or a partIndex outside 0 to 64, at that field.
  • A reply (target.replyToMessageId) beside attachToMessageExternalId.
  • Any of emoji, attachToMessageExternalId, partIndex or placement without kind: "sticker", at that key.
  • Both emoji and url, or neither — exactly one names the picture — and a transferId, the relay's staged upload, which /v1 never takes: an image goes by link.
  • An image link that is not a PNG, GIF or JPEG, is larger than 512,000 bytes or is more than 618 px on a side — at payload.url; the file is fetched inside the send and reaches no Mac.
  • A thread the transport has not confirmed, at target.conversationId or the recipient key, with reason: conversation_not_confirmed (above).

What the Mac may still refuse

What the Mac behind the line can draw is not known before a sticker is sent. A Mac whose helper has not announced emoji stickers — or placement, for a placed sticker, or replies on a sticker, for a reply — is sent nothing: the command is accepted with a 202 and then settles failed on the stream with capability_constraint_violation, failureClass: capability.

There is no field to ask in advance, so watch the stream, and treat that settlement as "this line does not draw stickers" rather than something to retry unchanged: send the same sentiment as text instead. See Capabilities.

In test mode the sandbox phone draws an emoji sticker as its own bubble holding the emoji, whether or not it is stuck to a message; an image sticker is not rehearsed there and is refused at payload.url. Live, iMessage draws it on the message it is stuck to, at its placement — so the placement is worth checking against a real handset once, not against the sandbox.

A worked example

Reacting to a booking confirmation the contact just sent, in a conversation they opened themselves:

curl -X POST https://api.mapier.ai/v1/commands/message.send \
  -H "Authorization: Bearer $MAPIER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: sticker-on-guid-1" \
  -d '{
    "target": {
      "kind": "conversation",
      "conversationId": "a0000000-0000-4000-8000-000000000001"
    },
    "payload": {
      "kind": "sticker",
      "emoji": "🎉",
      "attachToMessageExternalId": "guid-1",
      "placement": { "x": 0.95, "y": 0.1, "rotation": 12 }
    }
  }'

The 202 is the same as any send's, and the command frame that follows says whether the Mac drew it. succeeded means the sticker went out; the frame's externalId stays null on a live iMessage line, so a later command cannot name the sticker itself.

On this page