- Holds. The send is accepted (
202) and waits aspendinguntil it can go. You don’t need to do anything. - Refusals. The send is rejected with a
422and nothing is created. You need to wait for the limit to reset, or stop messaging that contact.
The four limits
These limits apply to every line, as of 2026-11-10.
A refused send creates no message, so its
idempotency_key stays unused. Codes and retry advice: Errors.
iBubbl can temporarily set a line’s limits lower than these, for example while a new line builds its reputation. These numbers are never exceeded. To discuss your limits, email support@ibubbl.com.
What counts as a new contact
A contact is new if your account has no history with them:- they have never texted, called or booked with you, on any of your lines, and
- no one-to-one message to them has gone out.
- A new group counts as one new contact, whoever is in it. Sending into an existing group counts as none.
- A message iMessage refused (
failedwith animessage_*reason, such asimessage_undeliverable) uses no new-contact slot, and the contact stays new. It still counts toward the 1,000 a day.
Holds, queues and refusals
held_reason and held_until appear on GET /v1/messages/{id} within about 10 seconds of acceptance. See Message lifecycle.
Offline lines
Your line sends from a Mac. If that Mac hasn’t checked in for 2 minutes, it counts as offline:- A contact your line has messaged before is accepted as
202withstatus: "queued". It goes out when the Mac is back. A message stillqueued60–65 minutes after it was accepted becomesexpired, andmessage.failedfires withstatus: "expired"andfailed_reason: "queue_expired". Send it again if it still matters: itsidempotency_keyis released. - A contact with no line yet (someone your account has never messaged) gets
422 no_eligible_line, because iBubbl only gives new contacts to a line whose Mac is online. Nothing is created. Send again once the line is back.
pending when the Mac goes offline waits for it. If the Mac stays offline for more than an hour, the message becomes failed with failed_reason: "agent_offline", and message.failed fires.
Rate limits
POST /v1/messageshas no HTTP rate limit. A text send never gets a429. The one exception is rare: a send withattachmentsgets429 rate_limitedwithRetry-After: 5when iBubbl is already downloading as many attachment sends as it can and no slot frees within 10 seconds. Wait, then send the same request with the sameidempotency_key.- Attachments: up to 10 files and 86 MB per message; images and GIFs 25 MiB each, video 50 MiB, PDF 10 MB, audio 25 MiB. See Send attachments.
- List endpoints (List messages,
GET /v1/messages, and List contacts,GET /v1/contacts) allow 120 requests per 60 seconds per account. The window slides: each request counts for 60 seconds after it’s made. All your API keys and all list endpoints share that one budget. Over it, the answer is429 rate_limitedwith aRetry-Afterheader: wait that many seconds, then send the same request again. A refused request doesn’t count. At 100 items a page, that’s up to 12,000 items a minute, so a loop that reads one page after another rarely reaches it; Pagination shows a loop that handles429. Other reads, such as retrieving one message, aren’t limited. - Conversation actions (Add and remove a tapback, Mark a conversation read, Start and stop typing) allow 300 requests per 60 seconds per account, shared by all your API keys and all five endpoints. It’s a budget of its own: it never uses up the list budget, nor the other way round. The window slides the same way, and over it the answer is
429 rate_limitedwith aRetry-Afterheader. A typing refresh every 5 seconds is 12 a minute per conversation, so about 20 conversations can show typing at once. See Tapbacks, read receipts and typing. POST /v1/events/{token}accepts up to 60 events per 60 seconds for each secret-URL inbound event source. Over that, it answers429 rate_limitedwhile a workflow listens to that source. If no workflow listens, it answers200withruns_started: 0and the event is dropped. Signed sources, such as Recharge, have no limit.
Throughput and pacing
No rate limit on text sends doesn’t mean unlimited speed. Each line is one Mac, and it sends one message at a time:- The Mac checks for new messages every 2 seconds, then sends them in order with a 1-second pause after each one. So one line sends at most about one message per second.
- Before the first text to a new US or Canadian number, the Mac asks Apple whether the number uses iMessage (see Lines and routing). These checks are spaced 5 to 10 seconds apart.
- The hourly and daily limits above apply on top.
pending in your line’s queue and go out one by one. New contacts past 30 wait an hour or more, and past 50 or 1,000 the sends are refused with 422.
How to pace your sends:
- Send one message at a time per line, or keep only a few requests in flight. Faster sending only builds a longer queue.
- For outreach to new contacts, plan for 30 an hour and 50 a day per line. One new contact every 2 minutes, spread over the contact’s sending hours, stays inside both limits.
- Stop on a cap. After
cold_cap_exhaustedordaily_cap_exhausted, stop that kind of send until midnight ET, instead of trying every remaining contact. - Follow webhooks rather than polling. If you must poll
GET /v1/messages/{id}, poll each message at most every 30 seconds. To check many messages at once, page throughGET /v1/messageswithcreated_afterinstead of polling each one.
Duplicates and retries
- Duplicates count against every limit. iBubbl doesn’t detect identical messages. A send repeated with a new
idempotency_keyis a second real message: it uses a slot in the 1,000 a day, and it counts as another unanswered message to that contact. Reuse the key on retries. See Message lifecycle. - A retry with the same key never counts twice. It returns the original message, so it uses no extra slot.
- Don’t retry a cap
422with a new key. The answer is the same until the limit resets, and nothing was sent. - Don’t resend a held or queued message. It is already waiting and will go out by itself. A second send creates a duplicate.
Next
- Message lifecycle: what each status means, and which webhook fires.
- Lines and routing: how a contact gets a line, and iMessage versus SMS.
- Errors: every error code and whether to retry it.

