<!-- https://missblue.dev/docs/numbers -->

# Numbers

The lines your project holds. The Mac behind each line remains our implementation detail.

Base URL: `https://api.missblue.dev`

Every request carries `Authorization: Bearer $MISS_BLUE_KEY`.

### GET /v1/numbers

Your project's numbers, with the name each has been given.

The Mac behind a number is never named. Which machine holds a line is our problem, and telling you would make it yours. availability says whether a number can send right now: { "status": "available" }, or { "status": "unavailable", "message": … } with a sentence written to be shown to your own users as it is. It is unavailable exactly when a send made now would be queued rather than sent — sends are still accepted, and go out when it is back.

Example:

```bash
curl -X GET https://api.missblue.dev/v1/numbers \
  -H "Authorization: Bearer $MISS_BLUE_KEY"
```

Response:

```json
{
  "total": 1,
  "data": [{
    "id": "8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d",
    "handle": "+16465550142",
    "label": "Main support",
    "service": "imessage",
    "project_id": "e3b7c534-7e5d-4669-b90a-5b617bfe77f0",
    "disabled": false,
    "simulated": false,
    "availability": { "status": "available" },
    "shared": false,
    "created_at": "2026-08-23T09:12:04Z"
  }]
}
```

### GET /v1/numbers/{id}

Pull one number and its project and organization context.

Example:

```bash
curl -X GET https://api.missblue.dev/v1/numbers/8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d \
  -H "Authorization: Bearer $MISS_BLUE_KEY"
```

Response:

```json
{
  "number": {
    "id": "8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d",
    "handle": "+16465550142",
    "label": "Main support",
    "service": "imessage",
    "project_id": "e3b7c534-7e5d-4669-b90a-5b617bfe77f0",
    "disabled": false,
    "simulated": false,
    "availability": { "status": "available" },
    "shared": false,
    "created_at": "2026-08-23T09:12:04Z"
  },
  "project_name": "Client Support",
  "workspace_id": "3480fdd8-2ef3-4edd-9949-bf78b4cd3e35",
  "workspace_name": "Acme Agency"
}
```

### POST /v1/numbers/{id}/label

Give a number a name.

So a thread says it arrived on Main support rather than +1 646 555 0142. Coming back to a conversation days later, the digits do not tell you which line you used.

| Parameter | Type | Required | Notes |
| --- | --- | --- | --- |
| `label` | `string` | no | Empty or absent clears it back to the bare handle. |

Request body:

```json
{
  "label": "Main support"
}
```

Example:

```bash
curl -X POST https://api.missblue.dev/v1/numbers/8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d/label \
  -H "Authorization: Bearer $MISS_BLUE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Main support"
  }'
```

Response:

```json
{
  "id": "8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d",
  "handle": "+16465550142",
  "label": "Main support",
  "service": "imessage",
  "project_id": "e3b7c534-7e5d-4669-b90a-5b617bfe77f0",
  "disabled": false,
  "simulated": false,
  "availability": { "status": "available" },
  "shared": false,
  "created_at": "2026-08-23T09:12:04Z"
}
```

### GET /v1/numbers/{selector}/call-forwarding

Pull the currently confirmed call-forwarding destination and latest request.

forwarding_number changes only after staff confirms the carrier update. A pending destination appears under latest_request without pretending it is already active.

Example:

```bash
curl -X GET https://api.missblue.dev/v1/numbers/8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d/call-forwarding \
  -H "Authorization: Bearer $MISS_BLUE_KEY"
```

Response:

```json
{
  "number_id": "8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d",
  "number": "+16465550142",
  "forwarding_number": "+14155550100",
  "eligible": true,
  "eligibility_reason": null,
  "monthly_limit": 2,
  "requests_used_this_month": 1,
  "requests_remaining_this_month": 1,
  "latest_request": {
    "id": "927c4759-fb1a-43c4-9a39-acde90645fe0",
    "number_id": "8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d",
    "forward_to": "+14155550100",
    "status": "completed",
    "rejection_reason": null,
    "created_at": "2026-09-03T16:00:00Z",
    "updated_at": "2026-09-03T16:30:00Z",
    "completed_at": "2026-09-03T16:30:00Z"
  }
}
```

Errors:

- `400` — The path is neither a UUID nor a canonical E.164 number.
- `404` — The selected number is outside this project.

### POST /v1/numbers/{selector}/call-forwarding

Request a new call-forwarding destination.

The source in the path and forward_to must be canonical E.164 phone numbers. Staff complete the carrier change within 2–3 business days. Each number may request two changes per calendar month and have one open request at a time.

| Parameter | Type | Required | Notes |
| --- | --- | --- | --- |
| `forward_to` | `E.164 string` | yes | The destination: +, a non-zero country code, and 7–15 digits total. |

Request body:

```json
{
  "forward_to": "+14155550100"
}
```

Example:

```bash
curl -X POST https://api.missblue.dev/v1/numbers/8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d/call-forwarding \
  -H "Authorization: Bearer $MISS_BLUE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "forward_to": "+14155550100"
  }'
```

Response:

```json
{
  "id": "927c4759-fb1a-43c4-9a39-acde90645fe0",
  "number_id": "8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d",
  "forward_to": "+14155550100",
  "status": "pending",
  "rejection_reason": null,
  "created_at": "2026-09-03T16:00:00Z",
  "updated_at": "2026-09-03T16:00:00Z",
  "completed_at": null
}
```

Errors:

- `400` — The source or destination is not canonical E.164, or both are the same.
- `404` — The selected number is outside this project.
- `409` — This number already has a pending or processing request.
- `429` — This number already requested two changes in the current calendar month.

### GET /v1/numbers/{id}/name-photo

Pull this number's current Messages Name & Photo Sharing profile.

This is the Apple Account-wide outbound identity recipients may be offered, not a local Contacts card. photo_base64 is a bounded preview and has_photo remains authoritative. sharing_enabled says whether it is offered at all (to the number's contacts); Miss Blue keeps it on. Once a name and photo are saved here, saved is what was saved and in_sync whether the number still holds exactly that (photo_sha256 is the fingerprint of the exact image it holds). If it was changed outside Miss Blue, it is put back from what was saved, restored_at says when, and the project's people get an email. A new number starts with a name and photo Miss Blue chose (saved.is_default), and saved.verified_at says when a test message last proved the saved name and photo reach people.

Example:

```bash
curl -X GET https://api.missblue.dev/v1/numbers/8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d/name-photo \
  -H "Authorization: Bearer $MISS_BLUE_KEY"
```

Response:

```json
{
  "first_name": "Blue",
  "last_name": "Lover",
  "has_photo": true,
  "photo_mime_type": "image/jpeg",
  "photo_base64": "/9j/4AAQSkZJRg…",
  "photo_sha256": "53d37af3e156b59a0c7ed129912a7ff8c4b29de3acd0bca2b702b030d70bcd53",
  "sharing_enabled": true,
  "saved": {
    "first_name": "Blue",
    "last_name": "Lover",
    "has_photo": true,
    "photo_attachment_id": "88de9745-30e0-4b93-bfcb-dbb7f3325dde",
    "saved_at": "2026-10-01T17:10:55Z",
    "is_default": false
  },
  "in_sync": true
}
```

Errors:

- `403` — The number is shared or its Apple Account has more than one number.
- `404` — The number is outside this project.

### PUT /v1/numbers/{id}/name-photo

Update and verify the number's Messages name and photo.

Upload a JPEG or PNG first. To remove the photo, omit photo_attachment_id and set remove_photo to true. Success is returned only after an independent Messages readback matches the requested name and image. Saving also turns sharing on, for the number's contacts.

Request body:

```json
{
  "first_name": "Blue",
  "last_name": "Lover",
  "photo_attachment_id": "88de9745-30e0-4b93-bfcb-dbb7f3325dde",
  "remove_photo": false
}
```

Example:

```bash
curl -X PUT https://api.missblue.dev/v1/numbers/8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d/name-photo \
  -H "Authorization: Bearer $MISS_BLUE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Blue",
    "last_name": "Lover",
    "photo_attachment_id": "88de9745-30e0-4b93-bfcb-dbb7f3325dde",
    "remove_photo": false
  }'
```

Response:

```json
{
  "first_name": "Blue",
  "last_name": "Lover",
  "has_photo": true,
  "photo_mime_type": "image/jpeg",
  "photo_base64": "/9j/4AAQSkZJRg…",
  "photo_sha256": "53d37af3e156b59a0c7ed129912a7ff8c4b29de3acd0bca2b702b030d70bcd53",
  "sharing_enabled": true,
  "saved": {
    "first_name": "Blue",
    "last_name": "Lover",
    "has_photo": true,
    "photo_attachment_id": "88de9745-30e0-4b93-bfcb-dbb7f3325dde",
    "saved_at": "2026-10-01T17:10:55Z"
  },
  "in_sync": true
}
```

### GET /v1/numbers/{id}/service-status?handle={handle}

Pull live iMessage and FaceTime registration for a recipient.

Each service is registered, not_registered, or unknown. Unknown is an inconclusive Apple lookup and is never turned into a negative answer.

| Parameter | Type | Required | Notes |
| --- | --- | --- | --- |
| `handle` | `string` | yes | The E.164 phone number or Apple ID email to check. |

Example:

```bash
curl -X GET https://api.missblue.dev/v1/numbers/8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d/service-status?handle=%2B15163128403 \
  -H "Authorization: Bearer $MISS_BLUE_KEY"
```

Response:

```json
{
  "handle": "+15163128403",
  "imessage": "registered",
  "facetime": "registered",
  "checked_at": "2026-08-28T10:04:00Z"
}
```

### POST /v1/numbers/{id}/service-status

Run the same live service lookup with a JSON request.

Request body:

```json
{
  "handle": "+15163128403"
}
```

Example:

```bash
curl -X POST https://api.missblue.dev/v1/numbers/8f14e45f-ceea-467a-9a1b-1b1e5f9e2c3d/service-status \
  -H "Authorization: Bearer $MISS_BLUE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "handle": "+15163128403"
  }'
```

Response:

```json
{
  "handle": "+15163128403",
  "imessage": "registered",
  "facetime": "registered",
  "checked_at": "2026-08-28T10:04:00Z"
}
```
