# Is this number on iMessage?

> A best guess from your own Messages history: what the newest chat with the person used.

`GET /v1/lookup`

A best guess from your own Messages history: what the newest chat with the person used. BlueBot asks the Mac and waits up to 15 seconds; `basis` says what the answer rests on. Apple offers no way to ask about a number you have never texted, so that answer is `unknown`.

Needs a key with the `messages:read` scope. [Keys and scopes](https://usebluebot.com/docs/concepts/api-keys)

## Query parameters

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `number` | string | Yes | The phone number or email address to look up. 3 to 320 characters |

## Example

```bash
curl "https://usebluebot.com/api/v1/lookup?number=%2B15555550123" \
  -H "Authorization: Bearer $BLUEBOT_API_KEY"
```

```ts
import BlueBot from '@usebluebot/sdk';

const client = new BlueBot({ apiKey: process.env.BLUEBOT_API_KEY });

const lookup = await client.lookup('+15555550123');
console.log(lookup);
```

```python
import os
from bluebot import BlueBot

client = BlueBot(api_key=os.environ["BLUEBOT_API_KEY"])

lookup = client.lookup("+15555550123")
print(lookup)
```

## Response

`200`: The answer and its basis.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `object` | "lookup" | Yes |   |
| `handle` | string | Yes | A phone number in E.164 (`+15555550123`) or an email address an Apple ID uses (iMessage only). |
| `service` | string | Yes | What the newest chat with the person used, or `unknown`. One of `imessage`, `sms`, `unknown` |
| `basis` | string | Yes | `history`: a chat with the person was found. `none`: there is no chat with them. `device_offline`: the Mac wasn’t there to ask. `timeout`: the Mac didn’t answer within 15 seconds. One of `history`, `none`, `device_offline`, `timeout` |
| `last_seen_at` | timestamp or null | Yes | The newest text in that chat. |
| `checked_at` | timestamp | Yes | When this answer was found. |

The answer, `200`:

```json
{
  "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"
}
```

## Errors

Every refusal has the same envelope and a page of its own. These are the ones this operation can give.

| Code                                                    | Status | What it means                                                                                                                                    |
| ------------------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| [`unauthorized`](https://usebluebot.com/docs/errors/unauthorized)             | 401    | The request carried no key, or a key BlueBot doesn’t know: mistyped, revoked, or a test key sent to the live API.                                |
| [`insufficient_scope`](https://usebluebot.com/docs/errors/insufficient_scope) | 403    | The key doesn’t carry the scope the endpoint needs. Each endpoint’s reference names its scope.                                                   |
| [`rate_limited`](https://usebluebot.com/docs/errors/rate_limited)             | 429    | Too many requests. A key may make 120 requests a minute. The `RateLimit` header says how many are left, and `Retry-After` how long to wait.      |
| [`internal`](https://usebluebot.com/docs/errors/internal)                     | 500    | Something went wrong on BlueBot’s side. It was reported. Send the request again; with an Idempotency-Key that is always safe.                    |
| [`invalid_request`](https://usebluebot.com/docs/errors/invalid_request)       | 400    | Something in the request doesn’t fit: a missing or malformed field, a bad id, or a combination the endpoint refuses. `details` names each field. |

## Try it
