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

# Phone Numbers

> Provision, assign agents to, transfer, and verify phone numbers.

A **phone number** belongs to an organization and carries two agent
assignments — one for the inbound direction (who answers) and one for
the outbound direction (who is placed on the caller side). Numbers can
be provisioned by ThunderPhone ("demo") or brought in through your own
VoIP provider and verified via a [VoIP connection](/api-reference/voip-connections).

## Endpoints

| Method          | Path                                              | Description                   |
| --------------- | ------------------------------------------------- | ----------------------------- |
| `GET`           | `/v1/phone-numbers`                               | List phone numbers            |
| `POST`          | `/v1/phone-numbers`                               | Provision a new number        |
| `GET`           | `/v1/phone-numbers/{phone_number_id}`             | Retrieve a single number      |
| `PUT` / `PATCH` | `/v1/phone-numbers/{phone_number_id}`             | Assign agents / update status |
| `DELETE`        | `/v1/phone-numbers/{phone_number_id}`             | Release the number            |
| `POST`          | `/v1/phone-numbers/{phone_number_id}/transfer`    | Move a number to another org  |
| `GET`           | `/v1/phone-numbers/{phone_number_id}/versions`    | List prior assignments        |
| `POST`          | `/v1/phone-numbers/{phone_number_id}/verify-voip` | Verify a VoIP-sourced number  |

## Phone number object

```json theme={null}
{
  "id": 201,
  "number": "+15551234567",
  "label": "Support line",
  "source": "voip",
  "status": "active",
  "inbound_agent_id": 12,
  "outbound_agent_id": null,
  "voip_connection_id": 5,
  "voip_verification_status": "verified",
  "voip_last_verified_at": "2026-04-20T18:24:10.113Z"
}
```

| Field                      | Type              | Description                                                                                                             |
| -------------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `id`                       | integer           | Server-assigned number id                                                                                               |
| `number`                   | string            | E.164-formatted phone number (e.g. `+15551234567`)                                                                      |
| `label`                    | string            | Your display label for the number (also settable via `PATCH`)                                                           |
| `source`                   | string            | `demo` (provisioned by ThunderPhone) or `voip` (brought via a [VoIP connection](/api-reference/voip-connections))       |
| `status`                   | string            | `provisioning`, `active`, `failed`, or `released`                                                                       |
| `inbound_agent_id`         | integer \| null   | Agent that answers inbound calls to this number                                                                         |
| `outbound_agent_id`        | integer \| null   | Agent used when placing outbound calls from this number. Always `null` for demo numbers (demo numbers are inbound-only) |
| `voip_connection_id`       | integer \| null   | Linked VoIP connection (only when `source="voip"`)                                                                      |
| `voip_verification_status` | string            | `unverified`, `verified`, or `failed`                                                                                   |
| `voip_last_verified_at`    | timestamp \| null | Last successful verify                                                                                                  |

***

## List phone numbers

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.thunderphone.com/v1/phone-numbers \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY"
  ```

  ```python Python theme={null}
  numbers = requests.get(
      "https://api.thunderphone.com/v1/phone-numbers",
      headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
  ).json()
  ```
</CodeGroup>

Returns an array of [Phone number objects](#phone-number-object), sorted by `created_at` descending.

***

## Provision a number

Requests a new demo number from ThunderPhone's pool. To bring your own
number through a VoIP provider, see [Import VoIP numbers](/api-reference/voip-connections#import-numbers).

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.thunderphone.com/v1/phone-numbers \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"area_code": "415"}'
  ```

  ```python Python theme={null}
  number = requests.post(
      "https://api.thunderphone.com/v1/phone-numbers",
      headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
      json={"area_code": "415"},
  ).json()
  ```
</CodeGroup>

| Field       | Type   | Required | Description                 |
| ----------- | ------ | -------- | --------------------------- |
| `area_code` | string | no       | 3-digit area code to prefer |
| `city`      | string | no       | US city name                |
| `state`     | string | no       | 2-letter US state code      |

Returns `201 Created` with the new [Phone number object](#phone-number-object) in
`status="provisioning"`. The upstream provider usually transitions to
`active` within seconds; poll the detail endpoint to observe the change.

***

## Retrieve a phone number

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.thunderphone.com/v1/phone-numbers/201 \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY"
  ```
</CodeGroup>

Returns `200 OK` with a [Phone number object](#phone-number-object), or `404` if not found.

***

## Assign agents / update status

`PATCH` clears or changes inbound/outbound agent assignments. The new
agents must belong to the same org.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PATCH https://api.thunderphone.com/v1/phone-numbers/201 \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "inbound_agent_id": 12,
      "outbound_agent_id": 13
    }'
  ```

  ```python Python theme={null}
  number = requests.patch(
      f"https://api.thunderphone.com/v1/phone-numbers/{phone_number_id}",
      headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
      json={"inbound_agent_id": 12, "outbound_agent_id": 13},
  ).json()
  ```
</CodeGroup>

| Field               | Type            | Description                                                                                                                                           |
| ------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `inbound_agent_id`  | integer \| null | Pass `null` to clear                                                                                                                                  |
| `outbound_agent_id` | integer \| null | Pass `null` to clear. Rejected with `400` on demo numbers (inbound-only)                                                                              |
| `label`             | string          | Display label                                                                                                                                         |
| `status`            | string          | Usually set by the server; write access is limited to toggling between `active` and `released`. Setting `released` also clears both agent assignments |

Returns `200 OK` with the updated [Phone number object](#phone-number-object).

***

## Release a phone number

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE https://api.thunderphone.com/v1/phone-numbers/201 \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY"
  ```
</CodeGroup>

Returns `204 No Content`. Demo numbers are returned to the pool; VoIP
numbers are detached from the phone record but remain in your VoIP
provider.

***

## Transfer a number to another org

Atomically move a number between orgs. Requires `admin+` in both orgs.
On transfer, the number's inbound/outbound agent assignments are
cleared (agents don't cross org boundaries).

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.thunderphone.com/v1/phone-numbers/201/transfer \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"target_org_id": 77}'
  ```

  ```python Python theme={null}
  result = requests.post(
      f"https://api.thunderphone.com/v1/phone-numbers/{phone_number_id}/transfer",
      headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
      json={"target_org_id": 77},
  ).json()
  ```
</CodeGroup>

```json Response theme={null}
{
  "source_org_id": 42,
  "target_org_id": 77,
  "cleared_agent_assignments": true,
  "phone_number": { /* Phone number object in the target org */ }
}
```

***

## Version history

Every assignment change records a snapshot so you can audit who
changed what.

<CodeGroup>
  ```bash cURL theme={null}
  curl 'https://api.thunderphone.com/v1/phone-numbers/201/versions?limit=20' \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY"
  ```
</CodeGroup>

```json Response theme={null}
{
  "count": 2,
  "results": [
    {
      "id": 88,
      "revision": 2,
      "created_by_id": 7,
      "created_at": "2026-04-20T18:24:10.113Z",
      "snapshot": { /* Phone number object at this revision */ },
      "changed_fields": ["inbound_agent_id"]
    }
  ]
}
```

`created_by_id` is the integer user id that made the change (`null`
for system-initiated changes).

***

## Verify a VoIP-sourced number

For numbers imported through a VoIP connection, run (or re-run) the
end-to-end verification flow that confirms inbound routing works and
outbound trunking is authorized.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.thunderphone.com/v1/phone-numbers/201/verify-voip \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY"
  ```
</CodeGroup>

```json Response theme={null}
{
  "phone_number_id": 201,
  "status": "active",
  "voip_verification_status": "verified",
  "provider_charge_estimate_cents": 0,
  "provider_charge_currency": "usd",
  "provider_charge_note": ""
}
```

Verification may take several seconds; the response reflects the final
state. If verification fails, `voip_verification_status` becomes
`failed` and the phone status returns to `provisioning` — fix the VoIP
connection (credentials, trunk, SIP allowlist) and call this endpoint
again.

***

## Related

<CardGroup cols={2}>
  <Card title="Agents" icon="robot" href="/api-reference/agents">
    Configure the voice agents you assign to these numbers.
  </Card>

  <Card title="VoIP Connections" icon="phone-volume" href="/api-reference/voip-connections">
    Bring your own phone numbers via Twilio, Telnyx, and more.
  </Card>

  <Card title="Phone Number Labels" icon="tag" href="/api-reference/phone-number-labels">
    Tag caller phone numbers that show up in call history.
  </Card>

  <Card title="Calls" icon="phone" href="/api-reference/calls">
    See call history filtered by phone number.
  </Card>
</CardGroup>
