Phone Numbers

Purchase phone number

Changed on

Payment-first: the system provisions a number and auto-assigns it, unless you pass phoneNumber to buy one exact number from GET /v1/phone-numbers/available. With usage-based billing active and a payment method on file, the number provisions inline and bills per month on your usage-based invoice (there is no checkout redirect). No payment method on file returns 402 PAYMENT_REQUIRED; a regulated country returns 202 with status: "kyc_required" and a kycUrl.

The monthly price is the one GET /v1/phone-numbers/countries quotes for that country and numberType at the time of purchase, and it is stamped on the number: later rate-card changes never move a number you already own.

Requires usage-based billing (the Usage plan). The maximum number of phone numbers is determined by the user's plan.

post/v1/phone-numbers/purchase

Request

  • Base URL: https://zernio.com/api
  • URL: https://zernio.com/api/v1/phone-numbers/purchase
  • Auth: HTTP bearer

Request body

profileIdstring required

Profile for the number, which may already hold other numbers. Without it the number goes to the default profile. The response's profileId carries the assignment.

countrystring

ISO 3166-1 alpha-2 country for the number (default US). International numbers require usage-based billing. Tier 3/4 countries return 202 { status: "kyc_required", kycUrl }. The customer must complete KYC at that URL before the number is ordered. See GET /v1/phone-numbers/countries.

numberType'local' | 'mobile' | 'national' | 'toll_free'

Which of the country's offered number types to order (see types[] on GET /v1/phone-numbers/countries). Omitted = the country's default type, which is always the WhatsApp-safe choice. Capabilities, price, and KYC requirements are per (country, type): toll_free can never connect WhatsApp (400 when combined with connectWhatsapp:true), and wantsSms:true requires an SMS-capable type.

areaCodestring

Area code (national destination code, e.g. 11 for Sao Paulo) the number must be in. Hard constraint: when the area has no deliverable inventory the purchase fails with 409 code AREA_CODE_UNAVAILABLE instead of assigning a number from another area, and later replacements stay in this area too. Omit for any area. Get live options from GET /v1/phone-numbers/availability (areaOptions).

claimIdstring

Keyless calls only: a claimId from a keyless GET /v1/phone-numbers/available. The 401 then carries a claimUrl for that exact number. Ignored when an API key is sent.

phoneNumberstring

One exact number to buy, in E.164, taken from GET /v1/phone-numbers/available. Hard constraint: when it is no longer available (bought by someone else, or WhatsApp's buy-time check rejects it) the purchase fails with 409 code PHONE_NUMBER_UNAVAILABLE instead of assigning another number; search again and pick another. Only for countries and types that activate instantly: a regulated one (202 kyc_required) returns 400 when phoneNumber is set.

connectWhatsappboolean

A phone number is the unit; WhatsApp is one optional feature. Pass false to buy a STANDALONE number (Calls/SMS only): provisioning skips the Meta pre-verify/OTP steps and the number activates immediately. Omitted defaults to the WhatsApp provisioning path. WhatsApp can be connected to a standalone number later from the connect flow.

wantsSmsboolean

SMS capability is per-number, not per-country. Pass true to provision from the SMS-capable inventory pool so the number can actually text (see also GET /v1/phone-numbers/available with sms=true, and smsAvailable on GET /v1/phone-numbers/countries).

wantsWhatsappboolean

Declare WhatsApp intent on a STANDALONE purchase (connectWhatsapp:false). The number still activates and bills immediately, but if WhatsApp's buy-time check rejects the assigned number, it is automatically swapped for a WhatsApp-eligible one during the purchase instead of being delivered with WhatsApp unavailable. Ignored on the WhatsApp provisioning path (connectWhatsapp omitted or true), which always delivers a WhatsApp-verified number.

purchaseIntentIdstring

Optional idempotency key. Send the same value when retrying a purchase: if a number was already bought under this key, the API returns { status: "already_purchased", numberId, phoneNumber, profileId } instead of provisioning a second number. Generate a fresh key for each genuinely new purchase.

allowMultipleboolean

Any second purchase within 10 minutes of a previous one is rejected with 409 code PURCHASE_VELOCITY as duplicate protection. Pass true to confirm the additional purchase is intentional (e.g. bulk provisioning).

Response

Either a checkout URL (first number) or the provisioned phone number (subsequent numbers).

OR
OR

Changes

    • info

      added the new optional request property

    • info

      added the optional property to the response with the status

    • info

      added the optional property to the response with the status

    • warning

      added the new NO_WHATSAPP_ELIGIBLE_NUMBER enum value to the response property for the response status