Tonedocs
API referencePhone numbers

Assign a sandbox number — 140/160 require an approved DLT PE ID

Allocates a free number from the sandbox pool. No carrier is contacted and nothing is charged — this is the number you build against before any paperwork exists.

Requires the write scope. A key with less gets 403 insufficient_scope.

POST
/v1/numbers
AuthorizationBearer <token>

Authorization: Bearer tone_live_… or tone_test_…. The prefix IS the environment: a test key reaches only the sandbox, and no request field bridges the two.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/numbers" \  -H "Content-Type: application/json" \  -d '{    "agentId": "9f1c2d84-4e3a-4f6c-b902-7d1e8a33c451",    "series": "regular"  }'
{  "data": {    "agentId": "9f1c2d84-4e3a-4f6c-b902-7d1e8a33c451",    "capabilities": {      "sms": false,      "voice": true    },    "createdAt": "2026-08-25T09:14:22Z",    "currency": "INR",    "e164": "+918045678901",    "environment": "live",    "id": "4b7c1a02-9de5-4f31-bb07-2c1a5e9f0d43",    "inbound": "ready",    "label": "Support line — Bengaluru",    "mediaEndpoint": {      "authSecretId": "3f1a7f6e-2b4c-4d1e-9a8b-5c6d7e8f9a0b",      "customParameters": {        "tenant": "acme"      },      "format": "linear16",      "sampleRate": 16000,      "type": "static",      "url": "wss://media.acme.example/tone"    },    "nextRentalAt": "2026-09-01T06:30:00Z",    "numberType": "landline",    "provider": "exotel",    "purchasedAt": "2026-08-01T06:30:00Z",    "recordCalls": true,    "region": "KA",    "releaseAt": null,    "releasedAt": null,    "renewalCycle": "anniversary",    "rentalPaise": 50000,    "routed": true,    "routingMode": "tone_agent",    "series": "regular",    "setupPaise": 0,    "sipTrunk": {      "credentialId": "cred_5a1b",      "inboundTrunkId": "tin_2c7d",      "originationSipUri": "sip:acme@sip.livekit.cloud",      "originationUriId": "ouri_9f2c",      "outboundTrunkId": "tout_8e3f",      "provider": "vobiz",      "terminationDomain": "acme.sip.vobiz.example",      "terminationRealm": "vobiz.example",      "terminationUsername": "acme-out",      "transport": "tls"    },    "sipTrunkId": null,    "status": "pending"  }}
Was this page helpful?

Update a knowledge base or its attached agents

agentIds is the COMPLETE attachment set, not a delta: send the full list every time, omit the key to leave attachments untouched, send an empty array to detach it from everything.

Search every carrier for numbers available to buy (cursor-paginated)

Asks every carrier Tone sells from and lists their numbers together, cheapest first. Each result names its provider — pass it back when you buy, and the number is bought from and operated by that carrier. Pass provider here to list one carrier’s numbers only (GET /v1/numbers/carriers names them). If one carrier is unreachable the others still list; if nothing lists and a carrier failed, that failure is returned rather than an empty list. Page with meta.pagination.cursor, sending the same filters with it. Every page is sorted cheapest first; carriers are read a page at a time, so a later page can occasionally hold a cheaper number than an earlier one, and a page can hold fewer than limit results while hasMore is still true. The first page carries meta.pagination.total, how many numbers the whole search lists, when every carrier searched can count it; it is the carriers’ own count where they page, so a walk can end a little short of it, and it is left out when a carrier cannot count a circle (VoiceLink) or failed. Live inventory, so results go stale — a number can be taken between this call and your purchase, which is a 409 number_unavailable, and a number sold between two pages can shift a carrier's listing by one. Only regular numbers are offered: the 140 and 160 series are not purchasable through any carrier API.