Skip to the page

Sending and receiving

Lookups

Ask whether a person uses iMessage. The answer is a best guess from your own Messages history and says what it’s based on. This page also covers when a lookup helps and when it doesn’t.

GET/v1/lookup answers “is this person on iMessage?” as well as anyone outside Apple can: by reading what the newest chat with them in your own Messages used. Apple offers no way to ask about somebody you’ve never texted, so for them the answer is unknown, and the answer always says what it rests on.

curl "https://usebluebot.com/api/v1/lookup?number=%2B15555550123" \
  -H "Authorization: Bearer $BLUEBOT_API_KEY"
Response200Somebody you’ve texted over iMessage
{
  "object": "lookup",
  "handle": "+15555550123",
  "service": "imessage",
  "basis": "history",
  "last_seen_at": "2026-11-12T16:20:00.000Z",
  "checked_at": "2026-11-13T19:41:00.000Z"
}

number takes a phone number or an email address, written any way to takes one on a send. Write the + as %2B in a URL you build by hand; the SDKs and the request examples here do it for you. A value BlueBot can’t read as either is 400 invalid_request.

What the answer means

service is the guess and basis is what it rests on:

servicebasisIt means
imessagehistoryThe newest chat with this person in your Messages is an iMessage chat. They used iMessage as of last_seen_at.
smshistoryThe newest chat is a regular text (SMS, MMS or RCS) chat. They may have no iPhone, or they may have turned iMessage off.
unknownnoneYou’ve never had a chat with this person, so there’s nothing to go on.
unknowndevice_offlineYour Mac wasn’t online to ask.
unknowntimeoutYour Mac didn’t answer within 15 seconds.

history is good evidence and nothing more. People switch phones, and somebody whose newest chat with you was over iMessage a year ago may be on Android now. Look at last_seen_at: an answer from last week is worth more than one from last year.

You gotIt meansDo next
"service": "imessage"They used iMessage in your newest chat.Send with auto, or imessage if the text only makes sense as an iMessage.
"service": "sms"Your newest chat with them is regular texts.Send with auto. Keep files small; regular texts carry less.
"basis": "none"Nothing to go on.Send with auto. It tries iMessage first and falls back to a regular text once.
"basis": "device_offline"The Mac is away.Wake the Mac, or send anyway: a text waits for it.
"basis": "timeout"The Mac didn’t answer in time.Try again in a minute. If it keeps happening, check the Mac’s Full Disk Access in BlueBot’s window.

How a lookup works

Your Mac answers it. BlueBot asks at the Mac’s next check-in, the Mac reads your Messages history for the newest chat with that person, and BlueBot holds your request open for up to 15 seconds to hear back. Most lookups take one or two check-ins, a few seconds. If no answer comes in time, the API answers unknown with timeout rather than making you wait longer.

The Mac needs Full Disk Access to read Messages’ history. Without it the Mac can’t answer any lookup, and every lookup times out. BlueBot’s window on the Mac shows the check and how to fix it, and GET /v1/device shows it as the full_disk_access check.

An answer is reused for 10 minutes. Asking about the same person twice in a row costs one trip to the Mac, and the second answer’s checked_at is the first one’s.

When to use it

  • Showing it to a person. A blue or green badge next to a contact in your CRM tells your team how a text will arrive.
  • Before an iMessage-only send. If a text only works as an iMessage (a long video, a group plan), look up first and send service: "imessage" only to people whose answer is imessage. Everyone else gets a different text, or none.
  • Sorting a list once. Before a campaign, look up each person once and keep the answers, rather than asking again for every send.

When not to

  • Before every send. service: "auto" already uses the newest chat’s service at the moment the Mac sends, and falls back from iMessage to a regular text once on its own. A lookup first adds up to 15 seconds and a request for no better result.
  • To find out about a stranger. For anybody you’ve never texted, the answer is unknown. Nothing in BlueBot, or anywhere outside Apple, can say whether a number you’ve never texted is on iMessage.
  • In a tight loop. Each lookup can hold a request for 15 seconds and counts against your 120 requests a minute. Look up a few at a time, not hundreds at once. Rate limits

In the SDKs

lookup.ts
const lookup = await client.lookup('+15555550123');
if (lookup.service === 'imessage') {
    // Safe to send the iMessage-only version.
}
lookup.py
lookup = client.lookup("+15555550123")
if lookup.service == "imessage":
    ...  # Safe to send the iMessage-only version.

The Zapier app has the same check as its Check iMessage search, and the MCP server as its lookup_service tool, so an assistant can ask before it sends. Services and SMS fallback explains how BlueBot chooses between iMessage and a regular text on every send.