Skip to main content
Every iBubbl API error response uses the same envelope shape:
The error field is a stable machine-readable code — branch your integration’s logic on this, not on the HTTP status or message. The message field is human-readable and may change without notice.

Request IDs

Every response from api.ibubbl.com, successful or not, carries an X-Request-Id header. It names that one request in iBubbl’s logs. When something goes wrong, log it next to the error and quote it to support@ibubbl.com: it finds your request faster than a timestamp and a request body can.
Send your own ID to trace a request end to end. If your request carries an X-Request-Id header, iBubbl uses it as the request’s ID and returns it unchanged, so the same ID appears in your logs and ours. It must be 1–128 characters of letters, digits, ., _, : and -. Anything else is ignored, and iBubbl generates an ID instead. Reusing one ID for several requests is allowed, but a unique ID per request is easier to find.

Error catalog

401
Missing, malformed, or revoked API key. Verify the Authorization: Bearer ib_pk_<hex> header and that the key is active in your dashboard.
403
Your API key is valid, but your iBubbl account is suspended or cancelled (message is Account is suspended or Account is cancelled). Every API-key endpoint returns this. A resource that belongs to another account is never a 403: it returns not_found.
404
The requested resource doesn’t exist, OR it exists but belongs to a different customer (existence is hidden across tenants). Verify the resource ID is correct and was created on the same account whose key you’re using. A deleted contact answers 404 too, including as the contact_id of a send.
409
You reused an idempotency_key with a request payload that doesn’t match the one originally cached. Either generate a new key for this distinct send, or fix your retry logic to reuse the original payload byte-for-byte. See Idempotency.
422
Generic request-shape failure. The message will identify the field. Common causes: missing required body field, malformed E.164 phone, body length zero, to and contact_id both omitted, neither body nor attachments, an attachments entry that isn’t an https URL (or more than 10 of them), attachments with chat_guid or participant_phones, or attachments with effect or reply_to_message_id. On a list endpoint: an unknown or repeated query parameter, limit outside 1–100, or a time without a time zone.
422
List endpoints only: starting_after is a UUID but not the id of one of your items (another account’s ID, and a contact deleted since, are answered the same way). Pass the id of the last item from the previous page, with the same endpoint. See Pagination.
422
The destination contact has opted out and cannot receive new sends. iBubbl enforces this server-side; there is no programmatic way to override. Add a tapback and Start typing return it too, in a one-to-one conversation. See Suppression & Opt-Outs.
422
A one-to-one send to a contact your account has blocked, in the dashboard or with Block a contact. Nothing was sent. The send works again once the contact is unblocked. If a contact is both opted out and blocked, you get contact_opted_out. Add a tapback and Start typing return it too, in a one-to-one conversation.
422
Refused on the 7th consecutive message to a contact who has never replied: iBubbl allows 6 unanswered messages in a row, then stops. Messages still waiting to go out (pending or queued) count toward the 6. Nothing was sent. The limit lifts as soon as the contact replies; waiting does not reset it.
422
The timezone field on a contact upsert is not in the supported IANA allowlist. The supported set covers US/Canada timezones plus common international zones; if you need a zone that isn’t supported, email support@ibubbl.com.
422
The email on a contact create or update doesn’t look like an email address (name@domain.tld, no spaces, at most 254 characters). Nothing was saved.
422
A tag name is empty, longer than 64 characters, or holds an invisible character. On a contact create, nothing was saved.
422
A tag name collides with an existing tag in a way iBubbl can’t resolve. Rare: choose a different name.
queued
Your line’s Mac is offline. This is not returned as an error: a one-to-one send to a contact your line has messaged before is accepted (202, status: "queued") and goes out automatically when the Mac reconnects. The reason appears only as failed_reason on the message.queued webhook, not in the API response. If it is still queued 60–65 minutes after it was accepted it expires (status: "expired"), and message.failed fires with failed_reason: "queue_expired". A contact with no line yet gets no_eligible_line instead. See Limits and queues.
422
The line has sent 1,000 messages today, its daily ceiling. Every outbound message counts: new contacts, replies, follow-ups, groups, messages still waiting and failed ones. The send fails and is not queued; the count resets at midnight ET (America/New_York), so send again after that. See Limits and queues.
422
The line has messaged 50 new contacts today (contacts your account has no history with). The send fails and is not queued. Messages to contacts already counted today, and to anyone you’ve messaged before, still go out. The count resets at midnight ET (America/New_York). See Limits and queues.
queued
Legacy: not used on any current line. The hourly limit on new contacts is a hold instead: the message stays pending with held_reason: "hourly_limit" and goes out by itself. See Limits and queues.
422
Legacy: not used on any current line. It was a daily cap on follow-ups under the older per-line caps.
422
No line on your account can take this send right now: for example, a contact you haven’t messaged before while your line is offline, or a group whose line is no longer active. Nothing was sent. Send again once your line is back online.
404
The chat_guid doesn’t match a group conversation on your account. A group’s chat_guid can change when someone is added to it, so look up the current one. Retrying the same request won’t help.
422
One or more participants in the group have opted out, so iBubbl won’t send to the group. When the send would create a new group, detail also carries a blocked_phones list naming them. Opt-outs are permanent, so retrying won’t help; send to a group without them.
422
The participant_phones resolve to fewer than 2 different people: for example, the same number written two ways. A group needs at least 2 different participants; for one person, send one-to-one.
422
POST /v1/messages only: reply_to_message_id doesn’t name a message in the conversation you’re sending to. For a to or contact_id send it must be a message with that contact, one-to-one; for a chat_guid send, a message in that group. A message from another account is answered the same way. Check the ID and the addressing field. See Reply and send with effects.
422
POST /v1/messages only: the contact unsent the message reply_to_message_id points to, so it can’t be quoted. Send without reply_to_message_id.
422
POST /v1/messages only: the contact unsent part of the message reply_to_message_id points to, and your line can’t quote what’s left. Send without reply_to_message_id.
422
Add a tapback only: the message is one you sent. Tapbacks go only on messages you received.
422
Add a tapback only: the message came in by SMS, or the conversation’s latest messages are going out by SMS, and tapbacks can’t be sent over SMS. They work over iMessage and RCS. Nothing was sent. See Tapbacks, read receipts and typing.
422
Add a tapback and Remove a tapback: the contact unsent the message, so it can’t get (or lose) a tapback. Also a failed_reason on message.reaction.failed when they unsent it before the tapback went out.
422
Add a tapback and Remove a tapback: the contact unsent part of the message, and your line can’t place a tapback on what’s left.
503
Add a tapback and Start typing: iBubbl couldn’t confirm that the contact hasn’t opted out, so it sent nothing. Retry after a short backoff. (Mark read doesn’t fail this way: it answers 200 with read_receipt_skipped_reason: "opt_out_check_unavailable" and sends no receipt.)
422
POST /v1/messages only: you sent attachments without a body to a contact you’ve never exchanged a message with. Messages can’t open a new conversation with files alone. Add a body. See Captions and the first message.
422
POST /v1/messages only: iBubbl couldn’t download one of the attachments URLs. The message names it by position, for example attachments[1]: attachment fetch answered 404. Causes: the host doesn’t resolve or is a private or internal address, the server answered something other than 200, more than 3 redirects (or one to a non-https URL), an empty file, or the download took too long (about 30 seconds for all the files, or 10 seconds without data). Check the URL works from the public internet, then send again. Nothing was created. See Send attachments.
422
POST /v1/messages only: a file is over its kind’s limit (images and GIFs 25 MiB, video 50 MiB, PDF 10 MB, audio 25 MiB), or the files are over 86 MB in all. The message names the file. Send a smaller file, or split the files across messages. See Supported files and limits.
422
POST /v1/messages only: a file’s type can’t be sent through the API, for example a calendar invite (.ics), WebM or Ogg audio, SVG or a ZIP file. The type comes from the response’s Content-Type (or the URL’s extension when that is application/octet-stream). Convert the file to a supported type.
422
POST /v1/messages only: the files can’t go out together with their caption. With other files, audio must be a single MP3 of 2 MB or less; any other audio, and a second audio file, needs a message of its own. Send it separately.
message.failed
Not an API error: it appears only as failed_reason on a failed message and its message.failed webhook. iMessage couldn’t deliver the message to this number because the number isn’t reachable on iMessage. Resending fails the same way, so reach the contact another way. Other iMessage failures appear as imessage_error:<code>.
500
An unexpected error on iBubbl’s side. These are paired with our error-tracking system; we get paged when they happen. If you see a sustained pattern, email support@ibubbl.com with the response’s X-Request-Id header.One known cause: two POST /v1/messages requests with the same idempotency_key arriving at the same moment. Only one message is created, and the other request gets this 500. Retrying it with the same key returns the 202 replay. See Duplicates and retries.
500
Your account has no active owner rep to send as, so POST /v1/messages can’t send. Retrying won’t help until the account has one; email support@ibubbl.com.
422
A POST /v1/webhooks url that doesn’t start with https://. Webhook endpoints must use HTTPS.
403
An inbound event arrived with a missing or incorrect signature. For Recharge, the usual cause is that the source was created with your API token pasted where the API Client Secret belongs — they’re different values.
413
An inbound event body exceeded 256 KB.
429
Returned in four places, and nowhere else:
  • Conversation actions (Add and remove a tapback, Mark read, Start and stop typing): your account made more than 300 of these requests in 60 seconds (all API keys and all five endpoints together; a budget separate from lists). The response has a Retry-After header; wait that long and call again. See Rate limits.
  • List endpoints (List messages, List contacts): your account made more than 120 list requests in 60 seconds (all API keys and all lists together). The response has a Retry-After header with the seconds to wait; then send the same request again. See Rate limits.
  • Sends with attachments, rarely: iBubbl was already downloading as many attachment sends as it can, and no slot freed within 10 seconds. Retry-After is 5; then send the same request with the same idempotency_key. Nothing was created.
  • /v1/events: a secret-URL inbound event source received more than 60 events in 60 seconds. There is no Retry-After header here; send again after about a minute.
Text-only sends (POST /v1/messages without attachments) never return it.

When to retry

The general rule: don’t retry 4xx. Most 4xxes are payload-level problems that retrying won’t fix. The exception is 429 rate_limited: wait, then send the same request again (on a list, a conversation action or an attachment send, Retry-After says how long). The limit 422s (daily_cap_exhausted, cold_cap_exhausted) are retryable only after the limit resets at midnight ET; iBubbl does not queue them for you. The hourly new-contact limit and an offline line are different: those sends are accepted and wait (pending with held_reason: "hourly_limit", or queued), so resending just creates a duplicate. The numbers are on Limits and queues. A send refused with a 404 or 422 creates no message, so its idempotency_key stays unused and you can reuse it when you send again.

HTTP status mapping summary