Regulated numbers

Validate carrier requirements before funding a number purchase, then track carrier review and activation.

Some countries let a carrier hand out a phone number immediately. Others require the carrier to register an end user against the number first. Which one you are in decides what you have to supply and when the number is ordered, so read the requirement before you build a checkout around it.

For an overview before choosing a country or integration, see Phone numbers for AI agents.

Read the requirement first

GET /v1/numbers/requirements (numbers:read) resolves one country, number type and profile type:

curl -H "Authorization: Bearer $SKYSAY_API_KEY" \
  "$SKYSAY_API_URL/v1/numbers/requirements?country=EE&number_type=national&profile_type=business"

Two fields drive everything else:

FieldMeaning
registration_requiredtrue when the carrier registers an end user against the number, false when it does not, null when the carrier's data does not settle it and a Skysay operator has to decide.
carrier_proof_requirementWhat the carrier lists for that market: none, required, or unknown.

A market reads false only when every number group the carrier currently sells there is marked as needing no registration. One group that needs it makes the market true, and a group the carrier has not marked either way makes it null. The carrier publishing requirement text for a country does not, on its own, make registration required: US, Canadian and UK local numbers, for example, need none.

carrier_proof_requirement reports the carrier's published list and nothing else. It is not a statement that anything has been approved, and it never reflects your own profile's status.

  • none — the carrier publishes an explicit zero for every proof type and names no document template. There is nothing for you to upload.
  • required — the carrier asks for at least one proof document or a template it wants signed. personal_identity_fields, business_identity_fields, address_fields and document_names on the same response say what to collect.
  • unknown — the carrier published nothing for this market. Treat it exactly like required: Skysay does, and the number waits.

Carrier forms

Some markets need a form the carrier publishes: a letter of authorization, a letter of intent, a registration form or an agreement. France local, Hong Kong national, India local, Thailand and most Caribbean numbers are examples. carrier_forms lists the forms for the profile type you asked about, and is an empty list everywhere else:

FieldMeaning
idThe carrier's template id.
nameThe form's name, also listed in document_names.
urlWhere to download the form.
formatThe file type, such as pdf or docx.
notesConditions the carrier adds, in its own words, such as less than 1 month old.

To complete one, download it, fill in your details and sign where it asks for you or your company. Use letterhead or a stamp if the form asks for them, and leave any part for Skysay or the carrier empty. Upload the signed form as a PDF, JPG or PNG; save a Word file as PDF first. In the workspace, Verification shows each form with its download link above its upload field.

Some markets cannot be ordered at all

Registration decides when a number is ordered. A separate field decides whether the market can be ordered, and it is worth reading before you show a country and number type as buyable.

The carrier sells every market under one or more products. Most are sold with no call channels bundled into the number, and Skysay prices their inbound calls per minute. Some markets are sold only with call channels bundled in. Skysay has no per-minute inbound rate for a bundled-channel number, so it does not sell one, and an order naming that product is refused before anything reaches the carrier.

GET /v1/numbers/requirements and GET /v1/number-catalog both answer this with the same pair of fields:

FieldMeaning
orderabletrue when Skysay sells this market, false when it does not, null when nothing was checked.
not_orderable_reasonThe named reason when orderable is false. Empty otherwise.

Three reasons exist. Two describe a market, and the third describes a single product within one:

  • number_type_not_priced — Skysay prices incoming calls per minute and has no per-minute rate for this number type at all. Toll-free and shared-cost markets are in this group. Nothing about the carrier's stock changes it.
  • carrier_bundles_channels — every number product the carrier currently has available for this country and number type bundles call channels into the number. It describes available stock, not the carrier's whole price list: a zero-channel product the carrier lists but has none of reads the same way.
  • sku_bundles_channels — the same fact about ONE product rather than the market. It appears only on catalogue rows, where another product in the same country and number type may still be orderable. A market summary never carries it.

Where both apply, number_type_not_priced is reported, because it is the one that stays true regardless of how bundled-channel numbers come to be priced.

On GET /v1/number-catalog the pair appears on each catalogue row, describing that one product, and on each market summary, describing the country and number type as a whole. A market is orderable when at least one available row is the zero-channel product.

Treat null as "not answered", never as a refusal. It means the catalogue held no rows for that market, or held rows that recorded no channel count, so nothing was established either way. A client should leave such a market exactly as it would have before these fields existed. An unknown refusal reason still blocks ordering, but should use neutral copy such as "Cannot order now" rather than asserting the market is permanently unavailable.

89 of the 186 markets in the current catalogue are not orderable: 62 toll-free, 13 national, 8 local and 6 shared cost. Where orderable is false, offer another number type or another country. No amount of verification changes it, because it is about the carrier's product for that market and Skysay's inbound pricing, not about your profile.

Every affected national and local market also has exact_number_browsing_enabled false, so exact-number selection never reached them; only a category order did.

If a request somehow reaches ordering, it stops before anything is sent to the carrier and says that Skysay could not confirm the number is on a product it can price. That refusal is about the selected product, not the market: it also fires when the product's channel count was never recorded, so it does not tell you to abandon the country.

Choose an exact number

You can let Skysay pick any available number in a country and type, or choose the exact number yourself.

POST /v1/available-numbers/search (numbers:write) loads the numbers the carrier can sell right now for one country and number_type. It is a read: nothing is reserved, ordered or charged. GET /v1/available-numbers (numbers:read) lists what is loaded. Both take two optional narrowings:

  • area_code: digits only, for example 212.
  • region: a state or region, by name or code: Texas, TX and US-TX all name the same one, in any case.

Each row says where the number is, as the carrier states it: area_code, area_name, city, region and region_code. A field the carrier does not state is empty.

The search answers with a refresh_status:

refresh_statusMeaning
succeededThe carrier answered. rows holds the numbers it offered, and is empty when nothing matched.
fresh_cacheThe same search ran moments ago and its numbers are still current, so they are returned without asking the carrier again.
cooldownThe same search found nothing moments ago. Try again in a couple of minutes, or order without choosing a number.
failed, blockedThe carrier could not be read. Order without choosing a number, or try again later.

A narrowed search is its own search: an area code with no numbers does not hold back a search for another one.

Every row is a snapshot, not a reservation. expires_at says when it stops being current, and the list stops showing it then; search again for a fresh list. A number you already chose stays valid after that: pass its id as provider_available_number_cache_id on POST /v1/number-requests, and Skysay checks it with the carrier again before ordering, as described below.

In the workspace, Phone numbers → Get a number opens a checkout dialog with area code and state fields. Each number shows where it is, and once the list is a few minutes old the dialog offers Refresh list; buying the number you picked still works.

Numbers Skysay cannot carry yet

A confirmed purchase (POST /v1/number-requests with customer_purchase_confirmed) is checked before it is saved: Skysay must be able to carry incoming calls for that market. When no capacity plan or inbound rate covers it, the request is refused with 409 and nothing is created or charged:

{
  "error": "inbound_coverage_missing",
  "message": "Skysay cannot carry incoming calls for this number type yet, so it cannot be bought. Nothing was charged.",
  "blocker": "carrier_rate_missing"
}

blocker uses the same words the Numbers page shows after activation (capacity_plan_unavailable, carrier_rate_missing). Choose another market, or contact support.

Numbers offered on request

Some numbers are not in the carrier catalogue Skysay orders from automatically. Skysay orders them by hand and enables them in your workspace when they are ready. Today that is United Arab Emirates mobile.

United Arab Emirates mobile
One-time setup$180.00
Monthly$180.00
Calls in$0.20/min, plus AI agent usage
Calls out$0.30/min to UAE numbers, plus AI agent usage
Usually ready inabout 15 business days
Who can orderbusinesses only
What Skysay asks fora local business address in the UAE and your business registration certificate

Per-minute prices are billed in whole minutes (60/60).

To order one, open Phone numbers → Get a number, choose United Arab Emirates, and choose Request on the Mobile row, which is marked On request. The coverage list on the skysay.ai home page links to the same request.

  • Nothing is charged when you request it. The request shows Requested with three steps: requested, Skysay orders it from the carrier, number active. Skysay contacts you for the documents.
  • When Skysay enables the number, the setup fee and the first month, $360.00 in total, are charged from your purchased wallet funds at once, and the number appears as Active. Choose who answers it, as with any number. If your wallet cannot cover it, the number is not enabled and nothing is charged.
  • Calls are placed and answered by a Skysay AI agent. Outbound calls go to UAE numbers only; a call to another country is refused before it starts. Outbound calls routed through your own app or phone server are not available on these numbers yet.
  • These numbers are voice only.

Through the API, request it like any other number with POST /v1/number-requests, country: "AE", number_type: "mobile". The saved request's provider_flow.fulfillment is manual_offer; its price_snapshot carries the fixed setup and monthly prices, and prices sent in the request body are ignored. The offer itself is published in GET /v1/pricing/catalog under public_price_book.numbers.on_request.

Where a number request waits

A saved request is not yet an active phone number. Phone numbers shows its current status, recorded details, and the next action you can take.

StatusWhat you see and do
payment_requiredPayment required → Add funds. Purchased wallet funds are needed. Browser-testing credit cannot pay for a number.
awaiting_verificationVerification required → Complete verification. Supply the person or business details required for this request's country and number type.
requestedRequest saved → View details. Check the recorded details; this state alone does not establish what is blocking the request.
carrier_verificationVerification checks → View details. Read the recorded next step. This state alone does not prove that documents have been submitted to, or approved by, the carrier.
fulfillment_queuedFinding an available number → View details. The request is queued, which does not prove that the number has been purchased.
active, assignedThe request is complete. Open its assigned number when it is available in the list.
failedCould not activate → View details. Read the recorded reason; the request remains visible.
closedThe request is closed and normally leaves the pending list. A return link to that request still shows its current outcome.

Payment and verification are separate checks. Follow the current next action; completing one check can reveal another. A requirement recorded as not_required says registration is not required for that request. A missing requirement is shown as unknown, not as a request for documents. This is based on the request's recorded requirement, not a fixed country rule.

Add funds opens Billing with the same request selected. It shows the recorded quote only when its currency and charge components are known; otherwise it says the quote is pending. The top-up amount you choose buys wallet credit and is not a charge for that exact quote. Checkout returns to the same request, even if its status changed while you were away. The wallet is credited only after a confirmed payment, not because a return URL says success. Availability, number limits and verification checks still apply.

Complete verification opens the exact request's country, number type and person or business context. It does not substitute another request or the first profile in your workspace. Errors and identity-verification returns keep that context. Submitting verification links that request to the profile you verified and returns you to the same request; it does not itself claim the number is purchased, carrier-approved or active. The remaining provisioning checks must also be ready.

A request you saved before verifying is linked to that verification as well. When you submit verification, Skysay links your workspace's open requests for the same country, number type and business or personal type. If more than one of your verification profiles could apply, Skysay does not choose for you: the request that Complete verification started from is linked, and Skysay support links any other. When Skysay approves the verification, the linked requests move to their next check in the same step, usually carrier_verification, instead of staying at awaiting_verification. A request saved after you submitted verification is linked at that approval.

When the number is ordered, Skysay checks the exact number you chose with the carrier again, however long the request has waited:

  • If the number is still available at the price you confirmed, it is ordered.
  • If its price changed, nothing is charged and the request returns to requested so you can confirm the new price.
  • If the carrier now requires registration for that number, nothing is charged and the request returns to awaiting_verification.
  • If someone else took the number meanwhile, nothing is charged and you are asked to choose another number.

Who a new number answers with

A number starts with a number rule as soon as it is active, so it never answers by accident and never sits half-configured:

  • the AI agent you named in agent_id when you requested it, if it is still active;
  • otherwise your workspace's only active AI agent;
  • otherwise nobody: the rule is set to do not answer until you choose.

A named AI agent that has since been deleted or switched off is not replaced by a guess. A rule you set yourself before activation is kept. Change it any time with PATCH /v1/phone-numbers/{number_id}/number-rules.

Inbound activation and outbound calling are separate

A managed number becomes active for inbound routing once the carrier confirms its registration, routing and inbound capacity. Outbound caller-ID setup does not keep a carrier-ready number in provisioning. Routing, an AI agent and call-time funding still need to be ready before an inbound call can connect.

The selected number panel shows Outbound calling is being set up while Skysay registers its caller ID. Inbound calls can continue; outbound attempts from that number are refused until registration succeeds. Skysay retries setup every five minutes for up to seven days, without ordering the number again. If setup still fails, the panel says Outbound calling needs support.

The Numbers aggregate exposes this distinction in calling_readiness.outbound.registration_status: pending, failed, registered, not_required, or legacy for numbers activated under the earlier combined readiness contract. An outbound destination and the usual admission checks are still required after caller-ID registration succeeds.

How the carrier learns who the end user is

From your approved verification profile Skysay creates two records at the carrier: an identity — the person or company — and an address, which belongs to that identity. Neither is bound to a phone number on its own.

When a registered market number is ready, Skysay opens a single verification task naming that number and that address. The carrier establishes the number's end user by approving the task; there is no separate step that attaches an identity to a number, and no state in which a number is waiting for one.

That makes the task the only thing standing between an ordered number and an approved one, which is what GET /v1/numbers/{number_id}/activation reports: submit_address_verification while the task has still to be opened, and wait_for_carrier_approval once the carrier has it.

Validate requirements before funding the purchase

For a number requiring registration, the Phone numbers page shows five steps:

  1. Verification details — provide the required person or business details and documents.
  2. Skysay approval — Skysay reviews the submitted information and documents.
  3. Carrier requirements — Skysay validates the prepared identity, address and proofs against the applicable requirements. Once both checks pass, add funds for the confirmed number purchase.
  4. Carrier review — after purchasing the number, Skysay submits its registration for the carrier's compliance review.
  5. Number active — the number becomes available after carrier approval and activation checks.

Skysay approval and successful carrier requirement validation must both be complete before the request asks for funding. Requirement validation checks whether the prepared information satisfies the selected rules. It does not mean the carrier has approved the company or the number.

The same sequence applies when the carrier lists no documents: required identity and address information must still be validated. Unknown requirements remain blocked. If information or requirements change, an old validation result cannot authorize the purchase. A carrier validation refusal requires correction; a temporary provider outage leaves the check pending.

Actual carrier review requires a purchased number. The number is therefore paid for before the final carrier decision and remains inactive while review is pending. A rejection can leave a purchased number that cannot be activated; requirement validation cannot guarantee final approval.

The carrier-review email is sent only after the carrier accepts the actual number-specific review request. Uploading documents, approving a profile, validating requirements, or adding funds does not start that review or its estimated duration. The email's review estimate is measured from the actual submission time and is an estimate, not an activation guarantee.

The inbound rate the quote is based on

Before any money moves, a number request carries a quote covering setup, monthly rental, and the per-minute price of the calls the number will carry. Read it on the request in the workspace, or on GET /v1/number-requests/{request_id} under quote_summary.source_breakdown.traffic_rates: each covered category appears in matched_rate_groups with a customer_price — the amount in micro-USD, the same figure as a decimal string, the unit it is charged per, the billing increment, and a confidence saying how firm the figure is.

In most regulated markets the carrier does not price inbound minutes against the number itself. It prices them against a shared inbound-capacity plan the number is attached to — and before purchase there is no number yet, so nothing on the number says which plan that will be.

Every managed Skysay number is provisioned onto one standard metered capacity plan, so the plan is known before the number is ordered. The quote prices the inbound leg from that plan, so matched_rate_groups names inbound voice with its customer_price instead of waiting for someone to supply a rate. A request in a metered market therefore reaches a final quote on the same path as any other market.

What that rate is, and is not

customer_price is your price per minute for inbound calls on this number — what Skysay charges you, on our standard metered capacity plan. It is not a carrier quotation for your specific number, and not a guarantee from the carrier. What you are billed is derived when a call is admitted, from the activated number's own carrier record.

Two consequences worth designing for:

  • A number provisioned onto that plan is billed from the same published rate the quote was based on. The quote and the charge read one plan, not two.
  • A number that ends up outside it — one the carrier delivers with its own included or dedicated channels, for example — has no metered rate to apply. Skysay refuses the inbound call rather than billing it at the assumed rate. GET /v1/numbers/{number_id}/activation reports that outcome.

Where a deployment has no standard capacity plan configured — a self-hosted install, for example — traffic_rates.status stays traffic_rates_pending_rate_card_or_invoice, inbound voice stays in missing_rate_groups, and no customer_price is returned for it. It never falls back to a default rate.

What Skysay still checks

In every registration-required market, regardless of carrier_proof_requirement, a number request waits for all of these:

  • your verification profile approved by Skysay (identity check for a personal profile, company review or identity check for a business one);
  • every requirement item Skysay tracks for the market satisfied and reviewed;
  • a successful carrier requirement validation for the current evidence;
  • the first payment funded and the displayed purchase confirmed.

Capacity pricing for an owned number

For managed DIDWW numbers, inbound pricing uses the number's verified capacity plan. The Numbers page explains why an individual number cannot be priced:

  • capacity_hybrid_unsupported: the number includes fixed-price channels, so a per-minute capacity rate does not apply.
  • capacity_separate_metering_unsupported: the carrier uses separate metering for this number group, outside the supported capacity-plan contract.
  • capacity_plan_unavailable: the capacity facts or supported plan are missing.

Contact support for any of these reasons. A blocked number does not disable pricing for other numbers. Capacity facts are refreshed by provisioning or an explicit operator action; opening the Numbers page does not contact the carrier. A price change applies to new call reservations. A call already reserved keeps its original price through settlement.