Phone numbers

Phone numbers are carrier-grade, SMS- and voice-enabled numbers. You can provision new numbers, attach them to agents, list existing numbers, retrieve messages for a number, and release numbers when no longer needed.

SMS compliance: Receiving inbound SMS works out of the box. To send outbound SMS, US carriers require 10DLC (10-Digit Long Code) registration. Fill out the registration form, it takes about 5 minutes and we submit everything to the carriers for you. If you can’t figure it out, schedule a call and we’ll handle the registration for you. Voice calls (inbound and outbound) are not affected and work immediately.

Search available numbers

Preview purchasable numbers before buying one.

GET /v1/numbers/available

Query parameters

ParameterDescription
areaCode3-digit area code, e.g. 415. The most broadly supported filter.
cityCity name. Pair with state. Support varies by account.
state2-letter state code, e.g. CA. Pair with city for consistent results; standalone support varies by account.
zip5-digit ZIP. Support varies by account.
countryUS or CA. Defaults to US.
limitMax results, 1 to 30. Defaults to 10.

Searching with no criteria returns a page of whatever is in stock. Giving a Canadian area code searches Canada even though country defaults to US.

Criteria support varies by account and there is no single rule that holds everywhere:

  • areaCode is the most broadly supported filter.
  • city, state and zip work on some accounts and not others. Where they aren’t supported they are ignored rather than rejected, so check what comes back instead of assuming the filter applied.
  • state on its own is honored on some accounts and rejected with 400 on others. Pair it with city for consistent behavior.

Number search isn’t available on every account. When it isn’t, this endpoint returns 404 (or 422 if it’s enabled but not yet configured).

That doesn’t block you from buying a number. POST /v1/numbers accepts an areaCode and picks one for you on any account, so search is a convenience rather than a requirement. Contact support if you want search enabled.

Example

curl "https://api.agentphone.ai/v1/numbers/available?areaCode=415&limit=5" \
-H "Authorization: Bearer $AGENTPHONE_API_KEY"
{
"data": [
{
"phoneNumber": "+14155550123",
"city": "San Francisco",
"state": "CA",
"rateCenter": "SNFC CNTRL",
"areaCode": "415"
}
],
"widened": false
}

phoneNumber is the only guaranteed field. city, state and rateCenter are null when the inventory source returns no per-number detail, so key off phoneNumber and treat the rest as best-effort labels.

widened: true means your exact criteria were out of stock and these are nearby alternatives instead. Check it before assuming you got what you asked for.

Buying a number you found

Pass the same phoneNumber to POST /v1/numbers:

curl -X POST "https://api.agentphone.ai/v1/numbers" \
-H "Authorization: Bearer $AGENTPHONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "+14155550123"}'

Search results are not reserved. This is live inventory, so a number can be bought by someone else between your search and your purchase. When that happens the purchase returns 409 with fresh alternatives in the same shape as the search response. Pick another and retry rather than treating it as fatal.

import httpx
H = {"Authorization": f"Bearer {API_KEY}"}
def buy_in_area_code(area_code: str) -> dict:
r = httpx.get(
"https://api.agentphone.ai/v1/numbers/available",
params={"areaCode": area_code, "limit": 5},
headers=H,
)
r.raise_for_status()
for entry in r.json()["data"]:
resp = httpx.post(
"https://api.agentphone.ai/v1/numbers",
json={"phoneNumber": entry["phoneNumber"]},
headers=H,
)
if resp.status_code == 409:
continue # taken between search and purchase, try the next one
resp.raise_for_status()
return resp.json()
raise RuntimeError(f"every candidate in {area_code} was taken")

Search is rate limited to 30 requests per minute per account, and purchase to 20.

Create number

Provision a new SMS-enabled phone number.

POST /v1/numbers

Request body

FieldTypeRequiredDefaultDescription
countrystringNo"US"Two-letter country code for the number (e.g., "US", "CA")
areaCodestring or nullNonullPreferred area code (US/CA only, e.g., "415"). If none are available in that area code, you’ll get another number in the same country.
agentIdstring or nullNonullOptionally attach the number to an agent immediately

Example

curl -X POST "https://api.agentphone.ai/v1/numbers" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"country": "US",
"areaCode": "415",
"agentId": "agt_abc123"
}'
{
"id": "num_xyz789",
"phoneNumber": "+15551234567",
"country": "US",
"status": "active",
"agentId": "agt_abc123",
"createdAt": "2025-01-15T10:45:00Z"
}

List numbers

List all phone numbers for this project.

GET /v1/numbers

Query parameters

ParameterTypeRequiredDefaultDescription
limitintegerNo20Number of results to return (max 100)
offsetintegerNo0Number of results to skip (min 0)

Example

curl -X GET "https://api.agentphone.ai/v1/numbers?limit=10&offset=0" \
-H "Authorization: Bearer YOUR_API_KEY"

Look up a number

Check line-type intelligence for any phone number before you message it: whether it is a mobile, landline, or VoIP line, its country, and whether the handset supports RCS. Useful for keeping agents from spending messages on numbers that can never receive them.

GET /v1/numbers/lookup

Billed at $0.009 per number looked up.

Query parameters

ParameterTypeRequiredDescription
phoneNumbersstringYesComma-separated E.164 numbers to look up, up to 25 per request

Example

curl -X GET "https://api.agentphone.ai/v1/numbers/lookup?phoneNumbers=%2B14155551234,%2B15551230000" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"data": [
{
"phoneNumber": "+14155551234",
"lineType": "mobile",
"country": "US",
"rcsEnabled": true
},
{
"phoneNumber": "+15551230000",
"lineType": "landline",
"country": "US",
"rcsEnabled": false
}
]
}

lineType is "mobile", "landline", or "voip"; fields are null when a number cannot be resolved. Accounts with a negative balance receive a 402 before any lookup runs.

Delete number (release)

Release (delete) a phone number.

This action:

  1. Releases the number back to the carrier pool
  2. Marks the number as "released" in the database
  3. Keeps all messages and conversation history for audit purposes

This action is irreversible. The number cannot be recovered once released.

DELETE /v1/numbers/{number_id}

Example

curl -X DELETE "https://api.agentphone.ai/v1/numbers/num_xyz789" \
-H "Authorization: Bearer YOUR_API_KEY"

Get messages for number

Get messages for a specific phone number. Supports cursor-based pagination via before/after timestamps.

GET /v1/numbers/{number_id}/messages

Query parameters

ParameterTypeRequiredDefaultDescription
limitintegerNo50Number of messages to return (max 200)
beforestring (datetime) or nullNonullReturn messages before this timestamp (ISO 8601)
afterstring (datetime) or nullNonullReturn messages after this timestamp (ISO 8601)

Example

curl -X GET "https://api.agentphone.ai/v1/numbers/num_xyz789/messages?limit=10" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"data": [
{
"id": "msg_001",
"from_": "+15559876543",
"to": "+15551234567",
"body": "Hi, I need help with my order",
"receivedAt": "2025-01-15T12:00:00Z"
}
],
"hasMore": false
}