Skip to main content
Every message goes out from one of your Blujay phone numbers. GET /v1/phone-numbers tells you which numbers you have, whether each one can send right now, how full its queue is, and how much of its sending limits it has used. This page also explains the limits themselves: how many new contacts a number can message a day, how big its queue is, and the guard against messaging one person too often. Request limits on the API itself (reads and writes per minute) are on Rate limits. The rules about what a message can contain before a contact replies are on Sending rules.

List your numbers

GET /v1/phone-numbers returns the active numbers in your workspace, oldest first.
curl
Response (200)
The limits and queue values above are illustrative. They differ between numbers and change over time, so read them from your own responses. To read one number, use GET /v1/phone-numbers/{phone_number_id}. It also returns numbers that are no longer active, with status: "unavailable", so you can still look up a number that older chats used. An unavailable number doesn’t report current health, limits, queue or label.

Understand the fields

Free Plan numbers leave out health_status, limits, queue and capabilities.voice. A missing field there doesn’t mean the number can’t send; use send_status.
Common mistake: from in POST /v1/chats is the display_number string ("+15555550100"), not the phone_number_id. Every other endpoint that names a number takes from_phone_number_id ("phone_abc123").

Sending limits

Sending limits protect each number’s reputation, so its messages keep arriving. They apply to each phone number, not to your API key. The values below are today’s typical values; the live limits and queue fields on your number are the source of truth, and sending limits can change at any time. There is no hourly limit on texts.

New contacts per day

A new contact is someone this number has never texted before. Each Dedicated number can message up to 50 new contacts a day once it is established. A new number, or one that was recently reassigned, may start lower and reaches the full limit over about its first month. A number’s age is counted from the day it was created in Blujay; moving it to another workspace doesn’t reset it.
  • People who texted you first never count, and neither do follow-ups in a chat you already have.
  • In a new group chat, each participant the number hasn’t texted before counts.
  • Over the limit, a send returns 429 RATE_LIMIT_EXCEEDED with limit_type: new_contact_daily. Nothing is queued.

Queue

Each number’s send queue has room for 1,500 pending messages. When it is full, a send returns 429 QUEUE_FULL with limit_type: phone_number_queue. Wait for Retry-After while queued messages go out, then retry with the same Idempotency-Key.

Texts to the same person

Each number can send at most 30 messages a minute to the same person (limit_type: recipient_loop). It’s there to stop a runaway loop in your code from flooding someone, and failed attempts count toward it too. Normal conversations never come close.

Free Plan numbers

A Free Plan number can message only verified contacts: people who texted it first and were verified in the app, up to 10 of them. The new-contact limit never applies to it, and GET /v1/phone-numbers doesn’t report limits or queue for it. Sending to anyone else returns 403 CONTACT_NOT_VERIFIED. The sending rules and the same-person guard still apply.

When limits reset

The new-contact count resets at midnight in your workspace’s time zone. The API doesn’t expose that time zone, so don’t compute the reset yourself: read limits.new_contacts.reset_at on the number, or error.details[0].reset_at on a 429, and wait until then. The same-person guard and the queue clear on their own within minutes; their reset_at says when.

Texts in a row without a response

A separate rule limits how many texts go to a contact without a response, and what a message can contain before they reply. Those return 400 errors, not 429, and aren’t retryable. See Sending rules.

Number health

Your own numbers report health_status: a score from 0 to 100 and a status band. The score reflects how your conversations go: how often people reply, how long conversations last, how quickly you answer, how many conversations people start with you, how close you run to the recommended daily volume, and whether your messages look templated. See Sending best practices. Read health_status as part of your preflight check and before a large batch.

Check a number before you send

Before you start a batch, read the number and stop when it has no room. Treat any of these as a stop signal:
  • send_status.allowed is false.
  • queue.remaining is 0.
  • limits.new_contacts.remaining_today is 0 and you’re about to message someone for the first time.
The check is a guide, not a reservation. Other sends can use up room between your check and your send, so still handle the errors below.

Handle limit errors on sends

When a send would go over a number’s limit, POST /v1/chats and POST /v1/chats/{chat_id}/messages return 429 before anything is queued. Wait for the Retry-After header (also error.retry_after), then retry with the same Idempotency-Key, or send from another number. Each entry in details also has scope: "phone_number", the phone_number_id, limit, used, remaining and reset_at:
RATE_LIMIT_EXCEEDED can also mean you’re making API requests too quickly. In that case details[0].limit_type is public_api_read, public_api_write or public_api_media, and scope is api_key. See Rate limits.

Common questions

No. Numbers have a daily limit on new contacts, a limit on texts in a row without a response, and a per-minute guard on texts to the same person.
Spread new conversations over the day and across your numbers. A new number’s new-contact limit grows over about its first month, and people who text you first don’t use it up. For more volume, add numbers.
No. Only texts you send count. A reply from the contact restarts the count of texts in a row.
A 429 or 400 queues nothing and doesn’t use up the new-contact limit. Failed attempts do count toward the same-person guard.
For a large send, spread messages over the day and across your numbers, and stop when remaining_today or queue.remaining reaches zero. Steady batches deliver better than bursts.

Limitations

  • A Free Plan number reports no health_status, limits, queue or capabilities.voice, and can message only verified contacts (CONTACT_NOT_VERIFIED).
  • An AI Agent number only replies to people who text it first (CONTACT_MUST_TEXT_FIRST), and it can’t create group chats or send to them. The phone number object doesn’t say which plan a number is on. See Plans.
  • A number that was replaced reports send_status.reason_code: sender_retired; a send from it returns SENDER_RETIRED. Switch to the new number’s phone_number_id.
  • There is no webhook when a number’s health changes or it is suspended (SENDER_SUSPENDED). phone_number.status_updated fires only when a number is replaced.
  • The workspace time zone behind reset_at isn’t exposed.

Next steps

Send messages

Start a chat from one of your numbers.

Sending rules

What a message can contain before and after a reply.

Rate limits

API request limits and how to back off.

iMessage, RCS or SMS

Check whether a number reaches someone over iMessage, RCS or SMS.