Skip to main content
Three ways to change your mind about a message: Edit and Undo Send are iMessage features: they work on messages that went out over iMessage (channel: "imessage"), and a message that went out by SMS or RCS gets 422 sms_not_supported. Cancel works on any message that hasn’t gone out yet. message_id is the id from Send a message. Messages sent from the dashboard can be changed too; find them with List messages.
Messages sent through the API never get a link preview card. A link in a message you send with POST /v1/messages goes out as part of a single text bubble, so the recipient sees the link as text. iBubbl builds a rich preview card only for a message typed in the dashboard (fetching the page for a card would count as a click on a tracked or one-time link). A dashboard message with a link is two bubbles, the text and the card: Unsend takes back both, and Edit changes only the text before the link.

Edit a message

What happens next:
  1. The answer is 202 with edit_status: "pending". body already shows the new text.
  2. A few seconds later the edit reaches the recipient. message.edited fires with direction: "outbound", edit_status becomes edited, and edit_count goes up by one.
  3. If it doesn’t land, message.edit_failed fires, edit_status becomes failed, and body goes back to the text the recipient has.
The rules:
  • Up to 5 edits, within 14 minutes 30 seconds of sent_at. iMessage allows 15 minutes; iBubbl stops 30 seconds early so an edit never arrives too late to apply. Then 422 edit_window_expired or 422 edit_limit_reached: send a follow-up message instead.
  • One at a time. A second edit while one is on its way gets 409 edit_in_flight. Wait for message.edited, then send the next.
  • Retries are safe. Sending the text the message already has answers 200 and doesn’t use up an edit, so you can retry a request that timed out.
  • Text only. The text of a message can be edited, including a caption beside files; a message that is only files can’t (422 not_editable).
  • Not to blocked or opted-out contacts. An edit reaches them as a change, so a one-to-one conversation with a blocked or opted-out contact is refused (contact_blocked, contact_opted_out).

Undo Send

Never rely on Undo Send for legal compliance, for confidentiality, or to retract sensitive or personal information. A recipient on an older iPhone, iPad or Mac keeps the original message, and anyone may have read, copied or been notified of it before it was unsent. Messages that went out by SMS or RCS can’t be unsent at all. Treat every message as delivered the moment you send it.
What happens next:
  1. The answer is 202 with unsend_status: "pending", and body is already "".
  2. A few seconds later the message is gone: message.unsent fires with direction: "outbound" and scope: "message", and unsend_status becomes unsent.
  3. If it doesn’t land, message.unsend_failed fires, unsend_status becomes failed, and body comes back. Calling Unsend again tries once more, while the 110 seconds last.
The rules:
  • Within 110 seconds of sent_at. iMessage allows 2 minutes; iBubbl stops 10 seconds early. Then 422 unsend_window_expired.
  • One bubble. A text message, or a single file on its own, is unsent whole. A message with files and text, or several files, gets 422 multi_part: unsending part of a message is available in the dashboard only, for now. A dashboard message with a link preview is unsent text and card together.
  • Retries are safe. Calling again while it’s pending or done answers 200 and changes nothing.
  • Not during an edit. While an edit of the message is on its way, 409 edit_in_flight.
  • Opt-outs don’t block it. Undo Send only removes content, so it works for any contact.

Cancel a message before it goes out

A message can wait before it’s sent: for the contact’s sending hours or the line’s hourly limit for new contacts (status: "pending", with a held_reason), or behind a capacity hold (status: "queued"). While it waits, you can stop it.
  • The answer is 200 with status: "cancelled", and message.cancelled fires. The contact never sees it. Calling again answers 200 and fires nothing more.
  • Once your line has picked the message up to send it, it’s too late: 409 message_dispatching, and it goes out. After it’s sent, use Unsend instead.
  • A message that already went out, failed or expired gets 422 not_cancellable.
  • Retrying the original send with the same idempotency_key returns the cancelled message; it doesn’t send it. Use a new key to send it after all.

What the recipient sees

What Edit and Undo Send look like depends on the recipient’s software. Apple describes it in Unsend or edit messages on iPhone. In a group, only members using iMessage see an edit.
edited and unsent mean iMessage accepted the change, not that the recipient’s device applied it. iBubbl can’t see which software version the recipient runs, so edit_status: "edited", unsend_status: "unsent" and their webhooks look the same whether the bubble changed or the recipient still has the original.

Webhooks

A failure carries failed_reason: expired when your line didn’t confirm the change within 3 minutes (for example, it was offline), or rejected when iMessage refused it (usually because the window had passed on its side).

Where it stands

Retrieve a message and List messages show the current state on every message: A message’s status doesn’t change when it’s edited or unsent: it stays sent, delivered or read.

Rate limits

Edit, Unsend and Cancel count toward the conversation-actions budget, with tapbacks, mark read and typing: 300 requests per 60 seconds per account, across all your API keys. Over it, you get 429 rate_limited with a Retry-After header. See Rate limits.

Next