Buying a Number
Search inventory, purchase a number, and enable features on it
Buying a Number
Buying is two steps: search inventory to see what is in stock, then purchase. Search confirms stock, pricing, and capabilities in a country or prefix; you cannot buy a specific number from the results. Purchase draws from that same pool and auto-assigns one during provisioning.
1. Search available numbers
searchAvailablePhoneNumbers (GET /v1/phone-numbers/available) queries the carrier's live inventory in a country (default US). Voice capability is always included in the filter; pass sms=true to draw only from the SMS-capable pool. Each result carries its full capability set, so you can show users what kinds of numbers are in stock before they buy.
| Param | Purpose |
|---|---|
country | ISO-2 country (default US), must be offerable |
prefix | Area code / national dialing code (e.g. 415) |
locality | City name |
contains | Digit pattern the number must contain |
sms | true to only return SMS-capable numbers |
limit | Max results (default 20, max 100) |
const { data } = await zernio.phonenumbers.searchAvailablePhoneNumbers({
query: { country: 'US', prefix: '415', sms: true, limit: 10 }
});
data.numbers.forEach(n => console.log(n.phoneNumber, n.features)); // features = capability badgesresponse = client.phone_numbers.search_available_phone_numbers(
country='US', prefix='415', sms=True, limit=10
)
for n in response.numbers:
print(n.phone_number, n.features)curl "https://zernio.com/api/v1/phone-numbers/available?country=US&prefix=415&sms=true&limit=10" \
-H "Authorization: Bearer YOUR_API_KEY"2. Purchase
purchasePhoneNumber (POST /v1/phone-numbers/purchase) provisions a number. With usage-based billing active and a payment method on file, the number provisions in the same request and starts billing per month on your usage-based invoice. Two other responses to handle:
- No payment method on file →
402 PAYMENT_REQUIRED. Add a card, then retry the purchase. - Regulated country →
202withstatus: "kyc_required"and akycUrl(see KYC); the number is ordered once the identity check clears.
Request features at purchase time. wantsSms (draw an SMS-capable number and flag it for SMS) defaults off. connectWhatsapp (start the WhatsApp connect flow) defaults on, so for a Calls/SMS-only number you must send connectWhatsapp: false.
const { data } = await zernio.phonenumbers.purchasePhoneNumber({
body: {
profileId: 'YOUR_PROFILE_ID',
country: 'US',
wantsSms: true, // optional: get an SMS-capable number
connectWhatsapp: false, // false = Calls/SMS-only; omit or true starts the WhatsApp connect flow
}
});
if (data.status === 'kyc_required') {
console.log('Regulated country, collect KYC:', data.kycUrl);
} else {
console.log('Number provisioned:', data.phoneNumber.phoneNumber);
}response = client.phone_numbers.purchase_phone_number(
profile_id='YOUR_PROFILE_ID', country='US', wants_sms=True, connect_whatsapp=False
)
if getattr(response, 'status', None) == 'kyc_required':
print(f"Regulated country, collect KYC: {response.kyc_url}")
else:
print(f"Number provisioned: {response.phone_number.phone_number}")curl -X POST https://zernio.com/api/v1/phone-numbers/purchase \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"profileId": "YOUR_PROFILE_ID", "country": "US", "wantsSms": true, "connectWhatsapp": false}'How many you can buy. The cap is your plan's profile limit; the Unlimited plan is capped at 50 numbers. The active count includes numbers that are provisioning, verifying, active, or pending. A purchase past the cap returns a 400.
Purchasing is not idempotent by default, so protect retries. Send a purchaseIntentId (any string, one per intended purchase): a repeat with the same key returns the existing number instead of buying a second one, and it survives the add-payment-method round-trip. Independently, any second purchase within 10 minutes returns 409 PURCHASE_VELOCITY; pass allowMultiple: true to confirm bulk provisioning is intentional.
3. Enable features
A fresh number already has Calls on. Add the rest from the number's own routes:
- SMS: enable and register (
POST /v1/phone-numbers/{id}/sms). US numbers need an approved carrier registration before messages deliver. - WhatsApp: connect to a WABA.
- Voice routing: configure inbound handling (forwarding, IVR, voicemail).
Manage numbers
List every number with listPhoneNumbers (GET /v1/phone-numbers), fetch one with getPhoneNumber (GET /v1/phone-numbers/{id}), and give a number up with releasePhoneNumber (DELETE /v1/phone-numbers/{id}). Releasing stops the monthly charge and returns the number to the carrier pool; it cannot be undone.
const { data } = await zernio.phonenumbers.listPhoneNumbers();
data.numbers.forEach(n => console.log(n._id, n.phoneNumber, n.status));
await zernio.phonenumbers.releasePhoneNumber({ path: { id: 'PHONE_NUMBER_ID' } });curl "https://zernio.com/api/v1/phone-numbers" \
-H "Authorization: Bearer YOUR_API_KEY"
curl -X DELETE "https://zernio.com/api/v1/phone-numbers/PHONE_NUMBER_ID" \
-H "Authorization: Bearer YOUR_API_KEY"Next steps
- Port in a number you already own instead of buying
- Enable SMS or connect WhatsApp