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.
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
{
"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) |
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
curl https://api.thunderphone.com/v1/phone-numbers \
-H "Authorization: Bearer sk_live_YOUR_API_KEY"numbers = requests.get(
"https://api.thunderphone.com/v1/phone-numbers",
headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
).json()Returns an array of Phone number objects, 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.
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"}'number = requests.post(
"https://api.thunderphone.com/v1/phone-numbers",
headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
json={"area_code": "415"},
).json()| 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 in
status="provisioning". The upstream provider usually transitions to
active within seconds; poll the detail endpoint to observe the change.
Retrieve a phone number
curl https://api.thunderphone.com/v1/phone-numbers/201 \
-H "Authorization: Bearer sk_live_YOUR_API_KEY"Returns 200 OK with a 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.
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
}'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()| 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.
Release a phone number
curl -X DELETE https://api.thunderphone.com/v1/phone-numbers/201 \
-H "Authorization: Bearer sk_live_YOUR_API_KEY"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).
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}'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(){
"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.
curl 'https://api.thunderphone.com/v1/phone-numbers/201/versions?limit=20' \
-H "Authorization: Bearer sk_live_YOUR_API_KEY"{
"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.
curl -X POST https://api.thunderphone.com/v1/phone-numbers/201/verify-voip \
-H "Authorization: Bearer sk_live_YOUR_API_KEY"{
"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.