Skip to main content
POST

Add a tapback

Method: POST | Endpoint: /v1/messages/{message_id}/reactions Description: React to a message a contact sent you with one of the six iMessage tapbacks: ❤️ love, 👍 like, 👎 dislike, 😂 laugh, ‼️ emphasize or ❓ question. It goes out over iMessage, or over RCS to an Android contact. It can’t go out by SMS. See Tapbacks, read receipts and typing. Authentication: API key in the Authorization header: Authorization: Bearer ib_pk_<64 hex>. Create keys in the dashboard under Settings → API access. Rate limit: 300 conversation actions per 60 seconds per account (tapbacks, mark read and typing together, across all your API keys). Over that, you get 429 rate_limited with a Retry-After header; see Rate limits.

Request Body

The path parameter message_id is the ID of a message you received: the message_id of a message.inbound event, or the id of an inbound message from List messages. Fields not listed above are rejected with 422 validation_error.

How it behaves

  • It’s accepted first, sent second. The answer is 201 with status: "pending". When the tapback reaches the contact’s phone, message.reaction.added fires with direction: "outbound". If it can’t be sent, message.reaction.failed fires with a failed_reason, usually within seconds and always within 10 minutes.
  • One tapback per message. As in iMessage, a different type replaces your previous tapback on that message: the new one is 201, and the old one ends as removed. If the old one had reached the phone, message.reaction.removed fires for it. Tapbacks sent from the dashboard count as yours too.
  • It’s safe to call twice. Sending the type that’s already on the message answers 200 with that same reaction and sends nothing.
  • Groups work. A tapback on a message in a group conversation goes to the group.
  • Blocked and opted-out contacts get none. In a one-to-one conversation, a blocked contact gets 422 contact_blocked and an opted-out one 422 contact_opted_out, as for a send.
  • Not over SMS. If the message came in by SMS, or the conversation’s latest messages are going out by SMS, the answer is 422 sms_not_supported. If iBubbl can’t tell yet, it’s accepted, and a tapback the line then can’t send fires message.reaction.failed with failed_reason: "sms_target".

Responses

201 Created The tapback is accepted and on its way.
200 OK That type is already on the message. The body is the existing reaction (its status may already be sent); nothing new is sent. 401 Unauthorized
Other message values: Authorization Bearer token required, API key required (use Authorization: Bearer ib_pk_…), Invalid API key format, Customer account not found. 403 Forbidden
Your iBubbl account is suspended or cancelled (message is then Account is cancelled). Every API-key endpoint returns this. 404 Not Found
Also returned for a malformed ID and a message that belongs to another account. 422 Unprocessable Entity
Nothing was sent. The error is one of:
  • validation_error: no type, a type that isn’t one of the six, or an unknown field.
  • invalid_target: the message is one you sent. Tapbacks go only on messages you received.
  • contact_blocked: a one-to-one conversation with a contact you blocked.
  • contact_opted_out: a one-to-one conversation with a contact who opted out.
  • sms_not_supported: the message came in by SMS, or the conversation is going out by SMS.
  • target_unsent / target_partly_unsent: the contact unsent the message, or part of it.
429 Too Many Requests
Wait the Retry-After header’s seconds, then send the same request again. 503 Service Unavailable
iBubbl couldn’t confirm the contact hasn’t opted out, so it sent nothing. Retry after a short backoff.

Authorizations

Authorization
string
header
required

Bearer API key. Format: Authorization: Bearer ib_pk_<64 hex> (70 characters). Generate keys from Dashboard → Settings → API Access.

Path Parameters

message_id
string
required

Body

application/json
type
enum<string>
required

One of the six iMessage tapbacks: love, like, dislike, laugh, emphasize, question. Custom emoji tapbacks can't be sent. Fields not listed here are rejected with 422 validation_error.

Available options:
love,
like,
dislike,
laugh,
emphasize,
question
Example:

"love"

Response

That tapback is already on the message; nothing sent.

id
string
required

Reaction ID. The reaction_id in message.reaction.* events.

message_id
string
required

The message the tapback is on.

conversation_id
string | null
required

The conversation that message is in.

type
string
required

love, like, dislike, laugh, emphasize or question.

emoji
string
required

The tapback as an emoji, e.g. ❤️.

direction
enum<string>
required

Always outbound: a tapback you sent.

Available options:
outbound
Allowed value: "outbound"
status
enum<string>
required

pending: accepted, not yet on the contact's phone. sent: delivered to Messages (message.reaction.added fires then). failed: never sent, see failed_reason (message.reaction.failed fires). removed: you removed it, or a newer tapback of yours on the same message replaced it.

Available options:
pending,
sent,
failed,
removed
failed_reason
string | null
required

Why a failed tapback wasn't sent: sms_target, target_not_found, bb_rejected, messages_error, expired, retract_rejected or target_unsent. Null otherwise.

created_at
string | null
required

When you sent the tapback (UTC).

removed_at
string | null
required

When it was removed or replaced (UTC); null while active.