Overview
POST /check-imessage tells you whether a single address can receive an iMessage, before you spend a send on it. You pass one phone number or email address. You get back two booleans: imessage and rcs.
POST /check-imessage-bulk does the same thing for up to 100 addresses in one call and returns a result for each one.
Both endpoints are read only. Nothing is sent to the address, and the person on the other end sees nothing. They use POST instead of GET so contact data stays in the request body and never lands in a URL, a proxy log, or a browser history.
Base URL for every BlueReacher endpoint:
Why check before you send
Checking first is the difference between a clean campaign and a broken one.- You stop burning sends. An iMessage aimed at an Android number cannot be delivered as an iMessage. Check first, and you route that contact to RCS or SMS instead of watching the send fail.
- Your reply rate stays honest. Undeliverable addresses sit in your denominator and drag every campaign metric down. Filter them out before launch and your numbers describe real conversations.
- Your line stays healthy. Repeatedly pushing traffic at addresses that cannot receive it is a bad pattern. BlueReacher gives you dedicated iMessage lines, managed for you, with no A2P registration required, and the fastest way to protect that line is to only message people who can actually receive the message.
- Your list stays current. People switch phones. A number that was on iMessage in March can be on Android in July. A bulk check the morning of a send catches that.
- Checks are free. Availability checks are not billed as messages and do not count against your message volume. Only rate limits apply.
check-imessage-bulk over your list right before a campaign, split the results into iMessage, RCS, and SMS groups, then send each group on the channel it can receive.
Authentication
Every request needs your API key in theAuthorization header and a JSON content type:
Check one address
POST https://api.bluereacher.com/functions/v1/check-imessage
Looks up a single address and returns its channel availability.
Request fields
No other fields are accepted. Unknown fields in the body are ignored.
Example request
Response fields
Successful lookups return
200 OK.
Example response
Error notes
400 with invalid_address is the one you will hit most. It almost always means the number was not in E.164. Normalize before you call: strip spaces, parentheses, and dashes, then add the country code. Full list in Errors.
Check up to 100 addresses
POST https://api.bluereacher.com/functions/v1/check-imessage-bulk
Checks a batch of addresses in one call. Use this for list hygiene and pre-campaign segmentation. It is roughly ten times more throughput per minute than looping the single endpoint.
Request fields
Duplicates are collapsed and checked once. Results come back in the order each address first appears in your array, so you can zip them against your input after deduping.
Example request
Response fields
A well formed request returns
200 OK even when some addresses fail. Per-address problems live inside results, not in the HTTP status. Check results[].error on every item.
Per-address error codes:
Example response
Error notes
The whole call fails with a4xx only when the request itself is wrong: bad JSON, missing addresses, an empty array, or more than 100 entries. Anything address-specific comes back inside results with a 200.
Splitting a larger list
Lists longer than 100 have to be chunked. Both examples below also handle a429 by waiting the number of seconds in the Retry-After header, then retrying the same chunk.
Picking a channel from the result
Thechannel field on a send accepts "imessage", "rcs", or "sms". Map the check straight onto it:
Skip any result where
error is not null. You do not know that contact’s availability, so do not guess a channel for it.
Freshness and caching
Results are cached for 24 hours per address. A repeat check inside that window returns the stored result, andchecked_at shows the original lookup time rather than the time of your call. Compare checked_at to now if you need to know how fresh a result is.
Cached responses still count against your rate limit.
Two habits that keep this accurate:
- Check within 24 hours of sending, not weeks ahead. Availability changes when people change phones.
- Store
imessage,rcs, andchecked_aton your contact record. Re-check anything older than 24 hours instead of trusting a stale flag.
Rate limits
Limits are per API key, counted across your whole workspace, over a rolling 60 second window.
Batching is the cheaper path by a wide margin. Use
check-imessage-bulk for anything over a handful of addresses and save the single endpoint for real time lookups, like a form submission or a CRM record opening.
Every response carries the current state of your limit:
Going over returns
429 Too Many Requests:
Retry-After, then retry the same request. Both endpoints are read only and have no side effects, so retrying is always safe. If you are running a large list check on a schedule, watch X-RateLimit-Remaining and slow down before you hit zero rather than driving into 429s.
Errors
Errors use one shape across the whole API:
One rule worth writing into your code: never read an error as a negative result.
imessage: false means the address cannot receive iMessage. An error means you do not know yet. Retry or hold the contact back instead of downgrading them to SMS on bad information.