reaction.tapback

React to a message in a conversation the contact has written into, with explicit add and remove.

POST /v1/commands/reaction.tapback

Applies one of the six classic tapbacks to a message you can still see, in a conversation the contact has written into.

Honours Idempotency-Key.

Target

A conversation target. On an iMessage line, live or test, the conversation at target.conversationId must be one the transport has named, which it does when the contact first writes into it. A tapback addressed by a phone number or an email instead, or into a conversation the transport has not named, is 422 validation_failed at target.conversationId before anything is sent.

Prop

Type

Payload

Prop

Type

The message is named at payload.targetMessageExternalId, by the externalId its message frame carried, or by the message's own messageId where the contact sent it. On a test line a tapback names it the same way, and the externalId there is the simulated device's own id for the message. A messageId for a message the line sent — there is no iMessage id on it to name — or for one another conversation holds is 422 validation_failed at payload.targetMessageExternalId, before anything is sent.

Request

curl https://api.mapier.ai/v1/commands/reaction.tapback \
  -H "Authorization: Bearer $MAPIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target": {
      "kind": "conversation",
      "conversationId": "a0000000-0000-4000-8000-000000000001"
    },
    "payload": { "reaction": "love", "targetMessageExternalId": "guid-1" }
  }'

Removing it again is the same call with remove:

{ "reaction": "love", "targetMessageExternalId": "guid-1", "remove": true }

Response

202 Accepted
{
  "commandId": "cmd-2",
  "status": "queued",
  "disposition": "queued",
  "lineId": "0192a7b0-3e4f-7051-8c6d-7e8f9a0b1c2d",
  "lineSelection": "reused_active_chat"
}

A reaction that was added, one that was removed, and one that was already in the state you asked for all settle succeeded with errorCode: null. The settlement event carries no field distinguishing them, so the stream cannot tell you whether this command was the one that changed anything.

event: command
{
  "commandId": "cmd-2",
  "logicalActionId": "cmd-2",
  "status": "succeeded",
  "errorCode": null,
  "failureClass": null
}

Errors

A command answers the one set of HTTP refusals POST /v1/commands/{type} publishes — every type the same codes, service_busy and no_line_capacity (capacity_exhausted from 2026-10-15) among them — so that table is the one to handle. What is particular to this type:

The two 422s above, before anything is sent. The common settlement failure is stale_target, when the line can no longer find the message:

  • it aged out of the line's bounded history — react promptly after receiving a message rather than hours later;
  • on a live line, the conversation is one the transport named with a group's id, and the message was sent one to one.

unsupported_capability is the other failed code you will meet.

tapback_unverified is not a failure: its command frame settles ambiguous, meaning the reaction may have been applied and could not be confirmed.

On this page