Bulk Reserve model
Bulk Reserve is one of three number-purchase surfaces in Orbit, and the only one with a reservation layer. You describe the shape of a block (country, number type, maybe an area code, a quantity up to 1000), Orbit scans both upstream inventory feeds and picks the cheapest matching numbers, and the block is held for 15 minutes without charging you. You then finalize it (purchase + bill + route) or cancel it (release). This page is the concept-level model behind those operations — the state machine, the hold/expiry friction, and where the wallet is touched. The step-by-step console walkthrough lives in Bulk Reserve in the console; the endpoint level field tables are in Phone Numbers — Bulk Reserve.The three purchase surfaces
All three DIDs-acquisition surfaces land on the same purchase machinery; they differ in how the numbers get chosen:
The distinction is filter-vs-exact-pick: single Buy and
buy-bulk are
exact-pick (you name the E.164 yourself), Bulk Reserve is filter-first (you
name the shape, Orbit supplies the numbers). Both feeds are treated as a
single pool by the reserve path unless you pin one provider.
The reservation state machine
A reservation is a row with a closed status vocabulary. The service-side values arereserving, ready, partial, failed, finalizing,
finalized, cancelled, and expired; reading them as a state machine,
they collapse into three behavioral clusters:
The transitions:
GET /numbers/bulk-reserve/:id.
Two moves you can never make: you cannot re-hold a settled reservation, and
you cannot cancel a finalized one. Release after finalize is per number via
DELETE /numbers/:id, because the items are now owned, billed DIDs.
Inventory scan semantics
Creating a reservation issues one search against the union of both upstream inventory feeds (DIDWW + Telnyx, joined by the same index the single-Buy page reads) and picks the cheapest matching N across that union. The picks are sorted by monthly cost ascending with E.164 as the tie-break, so two identical reserve requests select the same rows. Three properties to internalize:- Both feeds, or one. Pinning
provider: "didww"orprovider: "telnyx"restricts the scan to that feed; unpinned scans both. Pinning matters when you need a particular carrier’s regulatory posture (e.g. DIDWW-only regions) even at higher cost. - Partial fill is reported, not thrown. If the filter matched fewer
numbers than
quantity, the reservation reportsstatus: "partial"with the count it could hold. You finalize the smaller block or cancel and widen the filter. - Headroom in the search. The per-provider fan-out asks for up to 1.5× your requested quantity (capped at 500 rows) so the picks survive carriers turning stock between your search and your finalize.
The US area-code tile map
For US + local reservations the console filter grows an area-code picker backed by a geographic tile map. Every state (plus DC and the US territories PR, VI, GU, AS, MP) renders as a uniform-size tile; inventory density is encoded by color, so the map is not a choropleth and screen readers reach each tile separately. Clicking a tile writes the correspondingarea_code
into the filter; a multi-code state opens a popover. Tiles without current
stock are dimmed and not clickable — the map mirrors what the upstream
feeds actually group into each region.
The tile grid and the free-text NPA box both write the same area_code
field, so API callers who don’t render the console can send the raw 3-digit
code directly. Multi-area-code blocks run one reservation per area code;
the worked example in the guide does three.
When the wallet preflight fires
The wallet preflight runs only at finalize, never at reserve. Creating a reservation never debits — the picking-and-persisting step charges nothing, so a tenant that discards the hold costs nothing. At finalize the summed per-item cost is checked against the balance before any per-item purchase is attempted; insufficient balance stops the finalize with the required and available amounts named, before a single carrier call leaves. The reservation stays inready, so you can top up and retry
within the 15-minute window.
This is the only wallet touch point in the reservation lifecycle. Every
other state move is free.
Hold expiry and re-hold
The hold lasts 15 minutes from creation (expires_at stamped at
create). It is server-side — closing the tab does not release it — and it
releases read-time: any GET /numbers/bulk-reserve/:id after expires_at
flips the row to expired and its items to released, without waiting on
a sweep job. Once expired the row is settled; no finalize or cancel path
re-opens it.
Re-holding is not a first-class operation. If a hold lapses, create a new
reservation — inventory is re-picked at creation, so the new block may not
return the same numbers the old one held.
Finalize failure modes and their recoverability
Finalize can fail at three layers, and each recovers differently:- Wallet preflight reject. The summed per-item cost exceeds the
balance. No carrier call, no item moved, the reservation stays
ready. Recoverable: top up and re-finalize within the hold. - Per-item failures mid-purchase. Some items purchase and others are
rejected upstream (compliance gate, carrier-side race). Succeeded items
are purchased, billed, and given an inbound route; failed items carry
their error code and message on the row. The reservation closes as
partialwith the succeeded/failed counts. Recoverable: point the succeeded items and either re-create the failed slice as a new reservation or accept the partial block. No partial debit — failed items are never billed. - Every item failed. The finalize flips the reservation to
failed. Recoverable only by creating a new reservation; the failed row is settled.
compliance_profile_id on the
reservation’s filter is the way to pre-clear a block in a regulated
country.
See also
- Bulk Reserve in the console — the step-by-step walkthrough: filter panel, tile map, held page, finalize, cancel, and the worked 3-area-code example.
- Phone Numbers — Bulk Reserve — the endpoint level: request fields, response shapes, and the 1/minute rate limit on create.
- Number status map — the six-state vocabulary finalized numbers join once they are owned.
- Buy and provision numbers — the exact-pick surfaces, up to 50 per select-list order.