Phone, SMS & voice

Buy a number

Search live inventory, buy a number in one request, watch sold-out countries and release numbers you no longer need.

Buying a number takes two calls: search the inventory, then purchase. In countries that do not regulate numbers (the US among them) the number is active when the purchase returns. Regulated countries answer with a KYC step instead.

#Before you start

  • A payment method on file. Telephony is billed on your monthly invoice.
  • A profile id. Each number belongs to one profile. See Profiles.

#Search available numbers

GET /v1/phone-numbers/available queries the carrier's live inventory for a country (default US). Every result lists its features, and voice is always included.

curl "https://api.pozy.ai/v1/phone-numbers/available?country=US&areaCode=415&sms=true&limit=10" \
  -H "Authorization: Bearer $POZY_API_KEY"
Response
{
  "country": "US",
  "numberType": "local",
  "requireSms": true,
  "numbers": [
    { "phoneNumber": "+14155550142", "features": ["voice", "sms", "mms"], "locality": "San Francisco" },
    { "phoneNumber": "+14155550143", "features": ["voice", "sms", "mms"], "locality": "San Francisco", "bestEffort": true }
  ]
}
Query parameter What it does
country ISO 3166 alpha-2 code. Must be a country from GET /v1/phone-numbers/countries.
numberType local, mobile, national or toll_free. Defaults to the country's default type.
areaCode An area code (415) or a city name. A city covers every area code it has.
locality A city name, matched against the national numbering plan. Accents and common aliases work.
contains Digits the number must contain.
sms true returns SMS-capable numbers only.
limit Results to return. Default 20, maximum 100.

When too few numbers match, nearby numbers fill the list and carry bestEffort: true. Drop them if the exact area matters. An unknown query parameter is a 400 that lists the accepted ones.

#Purchase

POST /v1/phone-numbers/purchase takes a profileId and a country. Leave out phoneNumber and Pozy assigns one. Pass a phoneNumber from your search to buy that exact number.

curl -X POST https://api.pozy.ai/v1/phone-numbers/purchase \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "profileId": "6650c1f0a2b3c4d5e6f70812",
    "country": "US",
    "phoneNumber": "+14155550142",
    "wantsSms": true,
    "connectWhatsapp": false,
    "purchaseIntentId": "order-8841-line-1"
  }'
Response 200
{
  "message": "Phone number provisioned",
  "phoneNumber": {
    "id": "6650d2e1b3c4d5e6f7081923",
    "phoneNumber": "+14155550142",
    "status": "active",
    "country": "US",
    "provisionedAt": "2026-10-30T10:12:00Z",
    "profileId": "6650c1f0a2b3c4d5e6f70812"
  }
}

Keep phoneNumber.id. It is the {id} for every feature endpoint (/voice, /sms, /sip-trunk).

Body field Default What it does
profileId required The profile that owns the number
country US Country to buy in
numberType country default local, mobile, national or toll_free
phoneNumber none Buy this exact E.164 number. Only works where numbers activate instantly.
areaCode none Hold an auto-assigned number to this area. The purchase fails rather than give you another area.
wantsSms false Draw from SMS-capable stock and flag the number for SMS
connectWhatsapp true Start the WhatsApp connection on the new number. Send false for a calls or SMS line.
wantsWhatsapp false With connectWhatsapp: false, still pick a number WhatsApp will accept
purchaseIntentId none Your own key for this purchase, up to 100 characters. A retry with the same key returns already_purchased instead of buying twice.
allowMultiple false Confirm that a second purchase within 10 minutes is intentional
Purchases are not idempotent by default

Always send a purchaseIntentId, one per number you mean to buy. A retry with the same value returns { "status": "already_purchased", "numberId", "phoneNumber", "profileId" } and does not charge again. The key survives the round trip through adding a payment method.

#When the profile already has a number

A profile holds one number. If the profile you pass already has one, Pozy puts the new number on the next free profile (creating one if needed) and returns it in profileId. Read profileId from the response rather than assuming.

#Regulated countries

A country with needsKyc: true answers 202 instead of provisioning:

Response 202
{
  "status": "kyc_required",
  "country": "GB",
  "numberType": "local",
  "kycUrl": "https://pozy.ai/kyc/..."
}

Send your customer to kycUrl, or collect the details yourself with the KYC endpoints. Passing phoneNumber for a regulated country or type is a 400: the number is assigned after review.

#Check one country

GET /v1/phone-numbers/availability?country=BR&numberType=local answers for a single country: whether stock exists, which area codes are in stock (areaOptions), and the address rule for KYC (addressConstraint).

addressConstraint What the registrant needs
geo An address inside the area of the number
country Any address in the country
none No address

areaAvailability sorts every area of the country into inStock, preOrder and outOfStock. Pass an ndc from inStock as areaCode on the purchase to hold the order to that area.

#Watch a sold-out country

When a country or area has no stock, you have two options:

  • Pre-order it. If the type is preOrderable, submit the KYC form with preOrder: true. The number is sourced for you, usually within 2 to 4 weeks, and nothing is billed until it is active.
  • Watch it. POST /v1/phone-numbers/stock-watches with a country (and optionally numberType and areaCode) puts you on the list.
Create a stock watch
curl -X POST https://api.pozy.ai/v1/phone-numbers/stock-watches \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "country": "IE", "numberType": "local" }'

Stock is checked every few hours. When numbers come back, Pozy sends the phone_number.stock_available webhook, so subscribe to it to hear about it. A watch fires once and is then used up, so create it again if you miss the stock.

Rule Value
Watches per workspace 20
Watches per country and type 1 (a repeat request returns the existing watch)
Watch on a country that is in stock 409: buy instead

#Manage numbers

  • GET /v1/phone-numbers lists your numbers. Filter by status or profileId. Released numbers are left out unless you ask for status=released.
  • GET /v1/phone-numbers/{id} returns one number with its features and voice settings.
  • DELETE /v1/phone-numbers/{id} releases a number.
Releasing is permanent

A released number goes back to the carrier pool and stops billing. You cannot get it back. A number attached to a SIP trunk must be detached first, or the release returns 409 invalid_resource_state.

#Limits

Limit Value
Numbers per profile 1
Numbers per workspace Your profile limit (no cap where profiles are unlimited)
Purchase velocity A second purchase within 10 minutes needs allowMultiple: true
Search results 20 by default, 100 at most

#Errors

Status Code Cause Fix
400 The country is not offered, or phoneNumber was sent for a regulated country Pick a country from the countries list, or drop phoneNumber and run KYC
400 numberType: "toll_free" with connectWhatsapp: true Send connectWhatsapp: false
402 payment_required No payment method on file Add a card, then retry with the same purchaseIntentId
409 PHONE_NUMBER_UNAVAILABLE The exact number you picked is gone Search again
409 AREA_CODE_UNAVAILABLE No deliverable stock in that areaCode Pick another area, or leave it out
409 NO_WHATSAPP_ELIGIBLE_NUMBER Every number offered is one WhatsApp refuses Pass an areaCode, or retry
409 PURCHASE_VELOCITY A second purchase within 10 minutes Send allowMultiple: true

All errors use the standard error shape.

#Endpoints

Endpoint What it does
GET /v1/phone-numbers/countries List offerable number countries
GET /v1/phone-numbers/availability Check country availability
GET /v1/phone-numbers/available Search available numbers
POST /v1/phone-numbers/purchase Purchase phone number
GET /v1/phone-numbers/claims/{claimId} Resolve a number claim
GET /v1/phone-numbers List phone numbers
GET /v1/phone-numbers/{id} Get phone number
DELETE /v1/phone-numbers/{id} Release phone number
GET /v1/phone-numbers/stock-watches List stock watches
POST /v1/phone-numbers/stock-watches Watch an out-of-stock country
DELETE /v1/phone-numbers/stock-watches/{id} Stop watching a country

#Webhook events

Event When it fires
whatsapp.number.activated WhatsApp number activated.
whatsapp.number.suspended WhatsApp number suspended.
whatsapp.number.reactivated WhatsApp number reactivated.
whatsapp.number.released WhatsApp number released.
phone_number.stock_available Phone-number stock available.