Skip to main content
Every iBubbl line is a real phone number on a real Mac. Carriers and Apple flag numbers that message too many strangers too quickly, so iBubbl enforces a few limits per line. They protect your number. This page gives the exact numbers. Two kinds of limit apply:
  • Holds. The send is accepted (202) and waits as pending until it can go. You don’t need to do anything.
  • Refusals. The send is rejected with a 422 and 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.
Once one message to them goes out, they stop being new, and replies and follow-ups to them never count toward the new-contact limits. Only the 1,000-a-day limit counts those.
  • A new group counts as one new contact, whoever is in it. Sending into an existing group counts as none.
  • A message iMessage refused (failed with an imessage_* reason, such as imessage_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 202 with status: "queued". It goes out when the Mac is back. A message still queued 60–65 minutes after it was accepted becomes expired, and message.failed fires with status: "expired" and failed_reason: "queue_expired". Send it again if it still matters: its idempotency_key is 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.
A message that is already 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/messages has no HTTP rate limit. A text send never gets a 429. The one exception is rare: a send with attachments gets 429 rate_limited with Retry-After: 5 when 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 same idempotency_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 is 429 rate_limited with a Retry-After header: 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 handles 429. 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_limited with a Retry-After header. 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 answers 429 rate_limited while a workflow listens to that source. If no workflow listens, it answers 200 with runs_started: 0 and 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.
So a burst gains nothing. If you send 500 messages in one second, iBubbl accepts them all quickly, and then they wait as 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_exhausted or daily_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 through GET /v1/messages with created_after instead 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_key is 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 422 with 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