Skip to main content
Every send is one call to POST /v1/messages. It returns 202 Accepted as soon as iBubbl has the message; your line sends it a moment later. This guide covers the four ways to address a message, what the 202 tells you, how to follow the message after that, and the errors that are specific to sending.
Every request is live. There is no sandbox: each call below sends a real message from your line. Test with your own phone number.

Choose who to send to

Address each message in exactly one of four ways. Sending two of them (or none) returns 422 validation_error. Every request also needs body and an idempotency_key. Generate the key once per message, before the first attempt, and send the same key if you retry; see Idempotency.
to must be E.164: +, the country code, then the number, with no spaces or punctuation.

Reply to a message and send with effects

Two optional fields make a send look like one typed in Messages:
  • reply_to_message_id sends the message as an inline reply that quotes an earlier message. Pass a message id, or the message_id from a message.inbound webhook to reply to something the contact sent.
  • effect adds an iMessage effect, such as confetti or a slam. The values are in the table below.
Use either or both, with to, contact_id or chat_guid. Neither can be combined with attachments (422 validation_error): send the files and the reply or effect as two messages. This example replies to an inbound message with confetti:
The 202 response echoes both fields; they are null on a send without them.

Effects

Send the value in the effect column. Values are lowercase and exact: anything else returns 422 validation_error. A bubble effect animates the message bubble; a screen effect fills the recipient’s screen.
iMessage only. If the message goes out as SMS (RCS included), it is sent as plain text: the quote and the effect are dropped, and the API doesn’t refuse the send. The message.sent webhook carries channel (imessage or sms), so you can see which way it went; GET /v1/messages/{id} returns it too. See Lines and routing.
The reply must be in the same conversation. For a to or contact_id send, reply_to_message_id must be a message in your one-to-one conversation with that contact; for a chat_guid send, a message in that group. Anything else, including an ID from another account, returns 422 reply_target_not_found. A message the contact unsent returns 422 reply_target_unsent, and one they unsent part of returns 422 reply_target_partly_unsent.
Not when creating a group. Neither field is allowed with participant_phones (422 validation_error): a new group has nothing to reply to. Send them on a later message to the group’s chat_guid.
Both fields are part of the idempotency payload when you set them. A retry with the same idempotency_key must send the same effect and reply_to_message_id, or it returns 409 idempotency_conflict. See Idempotency.

Send files

Add attachments, a list of up to 10 https URLs, to send photos, GIFs, videos, PDFs or audio to one contact. body becomes optional and, when set, is the caption; the first message to a contact still needs a body. iBubbl downloads the files before it answers, so allow 60 seconds. Send attachments has the examples, the types and limits, and how each route delivers them.

Read the 202 response

202 means accepted, not sent. Save the id. status is one of: A waiting message is not an error, so don’t resend it: a new key would send a second message once the first goes out. For a group send, to is null and conversation_kind is "group". channel stays null until the message is sent.

Track the message

You have two ways to learn what happened next:
  • Webhooks (recommended). Subscribe to message.sent, message.delivered, message.read, message.failed and message.cancelled; each carries the message_id from the 202, and channel once the message has gone out. See Webhook events and Receive messages.
  • Polling. GET /v1/messages/{id} returns the current status, channel (imessage or sms) and held_* fields.
Use both where it matters. A few changes fire no webhook, such as a queued message moving on to pending. Message lifecycle has every status, which ones are final, and which webhook each fires.

Errors when sending

A refused send creates no message, so its idempotency_key stays unused and you can reuse it once you’ve fixed the request. Branch on detail.error, never on detail.message. The Errors page has the full catalog and the retry rules. 401, 403 and 500 no_owner_rep are account problems, not send problems; see Errors.

Next

Receive messages

Handle replies, attachments and opt-outs, and auto-reply without loops.

Message lifecycle

Every status, which ones are final and which webhook fires.

Limits and queues

The per-line limits, and how to pace sends.

Idempotency

Retry safely without sending twice.