Provisioning Phone Numbers at Scale: Pools, Rotation & Automation
Buying one number is a click. Provisioning thousands across dozens of countries, for a contact center, a CPaaS product, or a fleet of AI voice agents, is an operations problem: search, order, route, monitor, rotate, and release, all programmatically. A dashboard doesn’t scale past a handful of numbers; an API and a provisioning loop do. Here’s how to architect number provisioning that holds up at volume.
2026-05-26 · 9 min read
By Daria Kesselman · DIDHub editorial
1. Why scale changes everything
At one or two numbers, provisioning is a human task: open a dashboard, search a country, pick a number, click order, paste the SIP details into your PBX. That workflow is fine until it isn’t, and the wall arrives faster than most teams expect. A contact center spinning up a new market needs fifty local numbers by Monday. A CPaaS product onboarding a customer needs to hand them a number the instant they sign up, not after someone gets to a ticket. A fleet of AI voice agents dialing outbound needs a constantly-churning set of caller IDs to stay out of spam filters.
The moment numbers become part of your product rather than your office phone system, provisioning stops being a task and becomes a system. That system has a shape, and it’s the same whether you run ten numbers or ten thousand:
- Search availability across countries, area codes, and capabilities (voice, SMS, fax), programmatically, because inventory moves.
- Order in bulk, handling the reality that some numbers provision instantly and some don’t.
- Route each number to the right trunk, agent, tenant, or AI assistant the moment it’s live.
- Monitor health, answer rates, spam-labeling, and cost per number.
- Rotate outbound caller IDs so no single number gets burned.
- Release what you’re not using, because idle numbers are a recurring line item.
Manual clicking can’t do any of this reliably at volume. The rest of this guide is about building each stage as code.
2. The provisioning lifecycle
Every number you operate moves through a predictable lifecycle. Modeling it explicitly, as states in your own database, mirrored against the carrier’s API, is the single highest-leverage thing you can do. It turns “do we have a number for this?” into a query instead of a scramble.
| Stage | What happens | What to automate |
|---|---|---|
| Search | Query availability by country, type, area code, and capability. Live inventory fluctuates; cached catalogs go stale. | API search with a fallback to a cached catalog so a single provider outage doesn’t stall onboarding. |
| Order | Reserve and purchase numbers. Some activate instantly; regulated countries enter a pending-documents state. | Bulk order with idempotency keys and per-item outcome handling (see §5). |
| Route | Attach the live number to a SIP trunk, routing profile, agent, or tenant. | Assign a routing profile in the same flow that orders, a number with no route is a dropped call. |
| Active | The number carries traffic. Inbound, outbound, or both. | Track utilization and per-number call success so idle or unhealthy numbers surface. |
| Monitor | Watch answer rates, spam labels, concurrency, and billing per DID. | Webhook events (call started / answered / ended) piped to your analytics; alert on answer-rate drops. |
| Suspend | Past-due, fraud-flagged, or tenant-paused numbers stop carrying traffic but aren’t released. | Tie suspension to billing state so a missed payment doesn’t silently keep burning spend. |
| Rotate / Release | Outbound DIDs cycle out of the active set; truly unused numbers are released to stop billing. | Scheduled job that releases below a utilization threshold and rotates outbound caller IDs (see §4). |
The two stages teams most often skip are monitor and release, and they’re where the money and the deliverability live. A number you ordered eight months ago for a campaign that ended is pure cost. A number quietly flagged “Spam Likely” is worse than no number at all.
3. Number pools, pre-provision vs order-on-demand
The naive model is order-on-demand: a customer signs up, an agent gets assigned, a campaign launches, and only then do you order a number. It’s simple, and for instant-activation markets like the US it’s perfectly fine. The problem is latency and failure: ordering takes time, and in regulated countries it can take days while documents are reviewed. Your customer doesn’t want to hear “your German number will be live next Tuesday.”
The answer is a number pool: a buffer of already-provisioned numbers, sitting in an available state in your inventory, ready to assign the instant they’re needed. Assignment becomes a database update, pull a number from the pool, mark it assigned, attach routing, with zero carrier round-trip on the critical path.
How to size a pool:
- Per-market depth. Keep more headroom in markets with long lead times (regulated countries needing KYC docs) and less in instant-activation markets where on-demand ordering is genuinely instant.
- Burn rate plus headroom. Track how fast you assign numbers per market and keep enough to cover the carrier lead time plus a spike buffer. A low-watermark alert that triggers a top-up order keeps the pool from draining.
- Capacity planning beyond the number. Numbers are only one axis. Plan numbers-per-agent, concurrent channels per number, and headroom for traffic spikes, a pool of numbers with no channel capacity behind them still drops calls.
The cost trade-off is real: pooled numbers bill while they sit idle. The discipline is to pool where lead time hurts and order-on-demand where it doesn’t, then let the release stage (§2) reclaim numbers that never got assigned.
4. DID rotation for outbound
Inbound numbers are stable, a customer’s support line shouldn’t change. Outbound is the opposite. If you blast thousands of calls a day from a single DID, two things happen, both bad: answer rates collapse, and carrier analytics flag the number as “Spam Likely” or “Scam Likely.” Once a number is labeled, it’s effectively dead for outbound, recipients’ phones suppress or warn on every call.
The fix is rotation: spread outbound volume across a pool of numbers so no single DID exceeds the call velocity that trips spam heuristics. Combine it with two more practices:
- Local-presence dialing. Match the caller-ID region to the recipient’s region. A US recipient is far likelier to answer a +1 415 number than a +44 or +972 one. At scale this means maintaining rotation pools per region, not one global pool.
- Velocity caps per DID. Cap calls-per-number-per-day and cool a number down once it hits the ceiling. Rotate the cooled number out and a fresh one in.
- Attestation hygiene. Rotation buys you nothing if the underlying calls are signed with weak STIR/SHAKEN attestation, carriers flag on attestation as well as velocity. Outbound needs full A-attestation to survive. We cover the mechanics in STIR/SHAKEN and the spam-labeling problem.
Rotation and pools are the same machinery viewed from two angles: a pool is numbers waiting to be assigned; a rotation set is numbers waiting to be used as caller ID. Both need health monitoring, a number that starts getting flagged should be pulled from rotation automatically, the same way a drained pool triggers a top-up.
5. Bulk ordering done right
Ordering one number is a request that succeeds or fails. Ordering five hundred is a distributed operation where the only guarantee is that some of them will behave differently from the rest. A few will be snapped up by another buyer between search and order. A handful in regulated countries will land in a pending-documents state. The network will time out on one and leave you unsure whether it went through. Bulk ordering that ignores this loses numbers, double-orders, or wedges.
Two principles make bulk ordering safe:
Idempotency keys
Every bulk order should carry a client-generated idempotency key, a checkout ID you mint and attach to the request. If the connection drops and you retry, the server recognizes the key and returns the original result instead of ordering a second batch. This is the single most important safeguard: it makes retries safe, and at scale you will retry. Without it, a flaky network turns into double-billed, double-provisioned numbers.
Partial-failure handling
A bulk order must return per-item outcomes, not a single success/fail for the whole batch. The right shape is a result row per requested number: provisioned, pending_documents, or failed, each with a reason. Your provisioning loop then:
- Moves
provisionednumbers into the active/pool state and attaches routing. - Parks
pending_documentsnumbers in a waiting state and kicks off the compliance flow (§6). - Leaves
faileditems eligible for retry, ideally without re-ordering the ones that already succeeded under the same checkout ID.
6. Compliance at scale
Most countries don’t let a number go live until you’ve proven who’s using it, identity documents, a local address, sometimes a business registration. At one number this is a minor speed bump. At scale, across dozens of countries, it’s the thing that gates your whole provisioning pipeline, and the reason a number pool (§3) matters so much for regulated markets.
The pattern that scales is to prepare compliance documentation ahead of demand, not in reaction to each order:
- Pre-stage document bundles per country. Assemble and validate the required identity and address documents before you need numbers in that market, so an order can attach an already-approved bundle and skip the wait.
- Reuse bundles across orders. A validated bundle for a given end user or entity should attach to many numbers, not get re-uploaded per number.
- Model the pending state explicitly. When an order returns
pending_documents, your system should know exactly which bundle is missing or under review, and surface it, not silently stall.
For a country-by-country breakdown of what’s required and how bundles work, see why international numbers need KYC: compliance bundles explained. The operational takeaway: compliance is a prerequisite you stage in advance, not a step you discover mid-order.
7. How DIDHub does it
DIDHub is built API-first precisely because of everything above, the dashboard is a convenience, not the interface you provision at scale through. The provisioning surface maps directly onto the lifecycle:
- Catalog search fans out across providers and falls back to a cached catalog, so search keeps working even when a single upstream is unavailable.
- Cart + atomic bulk checkout handles the partial-failure reality: you stage items, then submit one checkout that returns per-item outcomes and is idempotent on a client checkout ID you supply.
- Number management, list, assign routing profiles, suspend, and release, is all programmatic, so pools, rotation, and reclamation are jobs you run, not tickets you file.
A search-to-checkout flow looks like this:
# 1. Search the catalog, country + type + area code, with capabilities curl https://api.didhub.io/v1/catalog/search?country=US&type=geographic&area_code=415&limit=25 \ -H "Authorization: Bearer $DIDHUB_TOKEN" # → each row carries a select_token + a price/display snapshot # 2. Stage the numbers you want, add each select_token (pass its snapshot) curl -X POST https://api.didhub.io/v1/cart/items \ -H "Authorization: Bearer $DIDHUB_TOKEN" \ -H "Content-Type: application/json" \ -d '{"select_token":"sel_415_...","snapshot":{"...":"from the catalog row"}}' # 3. Atomic-ish bulk checkout, idempotent on your client_checkout_id curl -X POST https://api.didhub.io/v1/cart/checkout \ -H "Authorization: Bearer $DIDHUB_TOKEN" \ -H "Content-Type: application/json" \ -d '{"client_checkout_id":"co_2026_05_26_batch_01"}' # → per-item outcomes: provisioned | pending_documents | failed # failed items stay in the cart; retry the same client_checkout_id safely
Provisioned numbers come back with a number record and a billing transaction; items in a regulated market return pending_documents so you can attach a pre-staged compliance bundle; anything that failed stays in the cart for a safe retry under the same checkout ID. From there, attach a routing profile to point each number at the right trunk, agent, or tenant, see routing profiles and SIP-trunk failover for the routing model, and try every request and response shape live in the API explorer.
If you’re provisioning at the scale this guide is about, multi-tenant resale, large outbound rotation pools, or many regulated markets, [email protected] can walk through per-tenant isolation, capacity planning, and bulk pricing.
8. Bottom line
Provisioning at scale is a lifecycle, and the teams that do it well automate every stage of it rather than clicking through a dashboard:
- Automate the lifecycle, search, order, route, monitor, rotate, release, as code, with each number’s state modeled explicitly in your own inventory.
- Keep pools for regulated markets so carrier lead time never becomes your customer’s wait time; order-on-demand only where activation is genuinely instant.
- Rotate outbound DIDs across region-matched pools with velocity caps and A-attestation, so no number gets burned and answer rates hold.
- Make bulk ordering safe with idempotency keys and per-item outcome handling, assume partial failure and reconcile.
- Prep compliance ahead of demand so a pending-documents state is a known, pre-staged step, not a mid-order surprise.
Get those five right and the number layer stops being the thing that slows your product down, and starts being infrastructure you barely have to think about.
More from the blog
A2P 10DLC Registration: Getting Your US SMS Actually Delivered
US carriers require A2P traffic on 10-digit long codes to be registered through The Campaign Registry. We explain brand + campaign registrat
AI Voice Agents Need Real Phone Numbers
Vapi, Retell AI, ElevenLabs, Bland, Synthflow, LiveKit Agents, Pipecat, AI voice platforms need real DIDs with STIR/SHAKEN A-attestation, re
Branded Calling Explained: Logo & Verified Name on Caller ID
Complete guide to branded calling: the four major programs (Hiya, First Orion, TNS, Google Verified Calls), how Rich Call Data fits, what sh
CNAM & Caller ID: Why Your Business Name Doesn’t Show
In North America the receiving carrier looks up your caller ID name via a CNAM dip, you don't send it. We explain why your business name doe
Ready to get a number?
Pick a DID in 130+ countries from $1.99/month. Activates instantly on most numbers.