> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lusor.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Phone numbers and email

> Read your workspace's phone numbers, the SMS they receive, and your Agent Mail inboxes.

Your workspace can have phone numbers and Agent Mail addresses. The API reads them and the messages they receive. It is read-only: it cannot send SMS or email, buy numbers, or change them.

| What | Endpoint |
| - | - |
| Workspace phone numbers | `GET /v1/workspaces/{workspaceId}/numbers` |
| One phone number | `GET /v1/workspaces/{workspaceId}/numbers/{phoneNumberId}` |
| SMS received by a number | `GET /v1/workspaces/{workspaceId}/numbers/{phoneNumberId}/messages` |
| Agent Mail addresses | `GET /v1/emails/addresses` |
| Mail received by an address | `GET /v1/emails/messages?addressId=…` |

Ids that do not exist or belong to another workspace return `404`, without saying which.

## Phone numbers

```bash theme={null}
curl https://api.lusor.ai/v1/workspaces/$WS/numbers \
  -H "X-Api-Key: $LUSOR_API_KEY"
```

| Field | Meaning |
| - | - |
| `id` | The number's id, used in the paths above. |
| `phoneNumber` | The number in international format, such as `+14155550100`. |
| `country` | The country it was bought in, such as `US` or `GB`. `null` for some older numbers. |
| `numberType` | `voip` or `real_sim`. |
| `status` | The number's status. |
| `autoRenew` | Whether it renews automatically. |
| `paidThrough` | The end of the paid period. `null` for some older numbers. |
| `expiresAt`, `createdAt`, `updatedAt`, `lastSyncedAt` | Timestamps. |

Numbers are shared across the workspace. They are not tied to a particular agent, phone or app.

## SMS messages

```bash cURL theme={null}
curl "https://api.lusor.ai/v1/workspaces/$WS/numbers/$NUMBER_ID/messages?limit=20" \
  -H "X-Api-Key: $LUSOR_API_KEY"
```

```python Python theme={null}
import os, requests

URL = f"https://api.lusor.ai/v1/workspaces/{os.environ['WS']}/numbers/{os.environ['NUMBER_ID']}/messages"
H = {"X-Api-Key": os.environ["LUSOR_API_KEY"]}

params = {"limit": 50}
while True:
    page = requests.get(URL, headers=H, params=params).json()
    for m in page["data"]:
        print(m["receivedAt"], m["sender"], m["body"])
    if page["nextCursor"] is None:
        break
    params["cursor"] = page["nextCursor"]
```

```javascript Node.js theme={null}
const URL = `https://api.lusor.ai/v1/workspaces/${process.env.WS}/numbers/${process.env.NUMBER_ID}/messages`;
const H = { "X-Api-Key": process.env.LUSOR_API_KEY };

let cursor = null;
do {
  const qs = new URLSearchParams({ limit: "50", ...(cursor ? { cursor } : {}) });
  const page = await (await fetch(`${URL}?${qs}`, { headers: H })).json();
  for (const m of page.data) console.log(m.receivedAt, m.sender, m.body);
  cursor = page.nextCursor;
} while (cursor);
```

Each message has `id`, `sender`, `body` and `receivedAt`. `body` is the raw text, including any codes. Lusor does not pick out one-time codes for you. `sender` is the sender as stored, or `null`. It is not a verified identity.

The API key must belong to the workspace in the path.

Query parameters:

| Parameter | Meaning |
| - | - |
| `limit` | 1 to 100. Default 50. |
| `cursor` | The `nextCursor` from the previous page. |
| `sender` | Only messages from this exact sender (case-sensitive). |

## Agent Mail

`GET /v1/emails/addresses` lists the workspace's Agent Mail addresses. Each has `id`, `address`, and `included`: `true` when the address comes free with your Lusor Phones, `false` when it is a paid address, `null` if that could not be read. An empty list is normal if your workspace has no addresses yet.

`GET /v1/emails/messages?addressId=…` lists mail received by one address:

```bash theme={null}
curl "https://api.lusor.ai/v1/emails/messages?addressId=$ADDRESS_ID" \
  -H "X-Api-Key: $LUSOR_API_KEY"
```

Each message has `id`, `addressId`, `senderName`, `senderAddress`, `subject`, `body` and `receivedAt`. `body` is the plain-text body. The sender fields are as stored and are not a verified identity. `limit` and `cursor` work as for SMS.

With an API key, `workspaceId` is optional on both mail endpoints, because the key already belongs to one workspace.

## Paging

Both message lists are newest first. Pass `nextCursor` back unchanged as `cursor` to get older messages. `nextCursor` is `null` when there are no older messages.

* A list is not a snapshot. To see newly received messages, load the first page again.
* Older messages are removed when their retention period ends.
* Start paging again from the first page when you change the number, address or sender.
* Unknown query parameters, and a repeated `limit` or `cursor`, return `400`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.