Phone numbers API
Search, buy, assign, and manage phone numbers, plus the regulatory compliance flow. See Phone numbers for concepts.
These endpoints are organization-scoped. With a dashboard JWT pass X-Org-Id; with an API key the org is carried by the key. Every response uses the standard { "success": true, "data": { … } } envelope (conventions). With an API key, mutations (purchase, assign, release, compliance) need a key whose role is developer, admin, or owner; a viewer or member key can only read. For what a signed-in member can do with compliance applications, see Compliance.
Numbers
| Method | Path | Purpose |
|---|---|---|
GET | /api/voice/numbers/providers | Configured carriers + their capabilities, and the default provider |
GET | /api/voice/numbers/integration | A provider's default integration (?provider=) |
GET | /api/voice/numbers/search | Search available numbers to buy |
POST | /api/voice/numbers/purchase | Purchase + persist a number |
GET | /api/voice/numbers | List your numbers ({ numbers, total }) |
GET | /api/voice/numbers/{id} | Number details |
GET | /api/voice/numbers/connection-status | Live carrier-side routing check for every number |
DELETE | /api/voice/numbers/{id} | Release a number |
POST | /api/voice/numbers/{id}/assign-agent | Attach an agent (answers inbound, used as caller ID) |
DELETE | /api/voice/numbers/{id}/agent | Detach the agent |
POST | /api/voice/numbers/{id}/pool | Mark or unmark a pool number, one many people forward to. See Pool numbers & inbound routing |
POST | /api/voice/numbers/{id}/relink-integration | Re-point the number's routing at the platform |
DELETE | /api/voice/numbers/{id}/integration | Detach the integration (carrier routing) |
POST | /api/voice/numbers/{id}/compliance | Link a compliance application to a number |
GET | /api/voice/numbers/renewal-risk | Per-number renewal state and whether the wallet covers what is coming due |
GET | /api/voice/numbers/reclaimable | Recently released numbers the carrier may still be holding |
POST | /api/voice/numbers/{id}/reclaim | Ask for a released number back |
Search
curl "https://api.telenow.ai/api/voice/numbers/search?country=US&type=local&limit=20" \
-H "x-api-key: vai_live_…"
Query parameters: country (required, ISO 3166-1 alpha-2), provider (omit for the default), pattern, type (local / mobile / tollfree / national), region, services, limit, offset. The response carries the resolved provider and a numbers array with region, number_type, monthly_rent, setup_price, price_currency, monthly_rent_usd, setup_price_usd, and capabilities.
Prices. monthly_rent and setup_price are the carrier's list price in the carrier's own currency, which is named by price_currency and is not always USD. monthly_rent_usd and setup_price_usd are the same prices in USD at the exchange rate your wallet is charged at (null when there is no price or no rate). A purchase charges the setup price and the first month's rent in USD; a postpaid account's first month is prorated. GET /api/voice/numbers and GET /api/voice/numbers/{id} return the same three fields on each number, and /reclaimable rows carry priceCurrency, lastMonthlyRentUsd, and lastSetupPriceUsd.
Purchase
curl -X POST https://api.telenow.ai/api/voice/numbers/purchase \
-H "x-api-key: vai_live_…" -H "Content-Type: application/json" \
-d '{
"provider": "plivo",
"number": "+14155550142",
"complianceApplicationId": "…",
"extras": { "numberType": "local", "country": "US" }
}'
| Field | Required | Notes |
|---|---|---|
number | Yes | The E.164 number returned by /search. |
provider | — | Omit to use the default provider. |
complianceApplicationId | For regulated buys | A local accepted application's id; the carrier rejects regulated purchases without it. |
integrationId | — | Override the default provider integration bound on purchase. |
extras | — | Provider-specific extras forwarded to the carrier (e.g. Twilio needs numberType + country to price/regulate correctly). |
Returns 201 Created with { number, integrationExternalId, providerStatus, complianceLinked }. Purchasing spends from your wallet, so a suspended or empty prepaid account returns an error (see Billing & usage).
Assign / unassign an agent
curl -X POST https://api.telenow.ai/api/voice/numbers/{id}/assign-agent \
-H "x-api-key: vai_live_…" -H "Content-Type: application/json" \
-d '{ "agentId": "agent-uuid" }'
The body field is agentId (camelCase). The agent must belong to the same org (403 otherwise; 404 if the agent doesn't exist).
assign-agent returns 409 Conflict when a team member already receives inbound calls on the number — inbound is exclusive (see Phone numbers and Team & workplace). The mirror case (allocating the number to a member for inbound while an agent is bound) is rejected the same way from the member-update endpoint. Detach with DELETE …/{id}/agent.
Connection status
curl "https://api.telenow.ai/api/voice/numbers/connection-status" -H "x-api-key: vai_live_…"
Makes live calls to the carrier API to check whether each owned number is actually routed to the platform's application. Returns { numbers: [{ id, e164, ourAppId, liveAppId, matches }], answerUrl }, where matches is true (routed to us), false (routed elsewhere / nowhere), or null (unknown). For a BYOC number that isn't routed yet, set its carrier Answer URL to the returned answerUrl. Because it hits the carrier, call this on demand, not in a tight loop.
Released numbers
A purchased number that goes unpaid is released back to the carrier (see Phone numbers → Getting a released number back). Both carriers hold a released number for the original account for a short time — Plivo about 5 days, Twilio about 10 — and GET …/reclaimable lists the ones still inside that window with their reclaimDeadlineAt. Numbers you released yourself are not listed: if one is still free, /search sells it again.
curl -X POST https://api.telenow.ai/api/voice/numbers/{id}/reclaim -H "x-api-key: vai_live_…"
{id} is the released row's id from /reclaimable. The call does everything the platform can do by itself and answers 200 with one of two status values:
status | Meaning |
|---|---|
restored | The carrier sold the number back. It is a fresh purchase — charged to credits at today's price — and number is the new active row (a new id). restore says how much of its old wiring came back: agentRestored, defaultOutboundRestored, campaignsRelinked, and notes for anything that could not be put back (for example, an agent deleted since). |
requested | The carrier would not sell it back automatically (a reserved number is not in either carrier's searchable inventory), so the request has been filed with Telenow support, who repurchase it from the carrier console before deadline and restore it to your account. alreadyRequested: true means an earlier call had already filed it. |
Refusals happen before the carrier is asked: 403 when the wallet does not cover the last known price (the message states the shortfall — the number was released for non-payment, so it is not recovered into a wallet that cannot keep it), and 400 when there is nothing to recover — the hold has ended, you released the number yourself, or it lives on your own carrier account (BYOC) or trunk.
Compliance
Some destinations require documentation before a number can carry traffic. See Compliance for the end-to-end walkthrough, and Telephony providers for per-provider details.
Roles. With an API key, submitting, withdrawing and linking need a key whose role is developer, admin or owner, like every mutation on this page; any key can read. With a user JWT, workspace membership is enough to view, submit and withdraw applications — the dashboard's Compliance page is open to every member.
| Method | Path | Purpose |
|---|---|---|
GET | /api/voice/numbers/compliance/requirements | Required documents for a provider/country/type/end-user |
POST | /api/voice/numbers/compliance | Submit a compliance application — returns 201 with the created application |
GET | /api/voice/numbers/compliance | List your applications ({ applications, total }) |
GET | /api/voice/numbers/compliance/{id} | Application detail (refreshes from the carrier) |
DELETE | /api/voice/numbers/compliance/{id} | Withdraw an application |
POST | /api/voice/numbers/{id}/compliance | Link an accepted application to a number |
…/compliance/requirements requires country, type, and endUserType query params (and an optional provider). Query it first to learn exactly which documents the carrier needs, submit them with POST …/compliance, wait for the application to reach accepted, then link it to your number.
Submitting an application
{
"provider": "plivo",
"countryIso": "IN",
"numberType": "local",
"alias": "Acme India — local numbers",
"endUser": {
"type": "business",
"name": "Acme Pvt Ltd",
"email": "[email protected]",
"registration_number": "22AAAAA0000A1Z5",
"address_line1": "1 MG Road",
"city": "Bengaluru",
"state": "KA",
"postal_code": "560001",
"country": "IN"
},
"documents": [
{
"documentTypeId": "gst_certificate",
"file": {
"filename": "gst.pdf",
"mime": "application/pdf",
"contentBase64": "JVBERi0xLjQ..."
}
}
]
}
Top-level keys are camelCase; the fields inside endUser are snake_case, exactly as shown.
Linking an application to a number
curl -X POST https://api.telenow.ai/api/voice/numbers/{id}/compliance \
-H "x-api-key: vai_live_…" -H "Content-Type: application/json" \
-d '{ "complianceApplicationId": "application-uuid" }'
The link body field is complianceApplicationId (camelCase). Only an accepted application on the same provider as the number can be linked. To attach one at purchase time instead, pass complianceApplicationId to POST /api/voice/numbers/purchase.
Carriers (BYOC) & SIP trunks
To use your own carrier account, manage credentials under /api/orgs/{orgId}/carriers; for your own SIP infrastructure, manage trunks and DIDs under /api/orgs/{orgId}/trunks. Both are documented in the Carriers & trunks API. The dashboard equivalents live under Developers → Carriers and Developers → SIP trunks (Telephony providers, SIP trunking).