Skip to main content

Number backorder waitlist

When the number you want is out of stock at the provider, the synchronous buy flow cannot help — there is nothing to search, select, or purchase. The backorder waitlist lets you register a standing request for a specific (country, area code, number type) pool and poll the same live provider inventory the buy flow uses, so the moment matching stock reappears you can place the order instead of manually re-running the search page. This guide covers what the waitlist is, the entry lifecycle, the dashboard walkthrough, an automation pattern, the limits and behaviour, and when to reach for the waitlist instead of the replenishment policy or a low-stock alert.

What the waitlist is

A waitlist entry is a standing backorder for a pool of numbers that is currently exhausted at the provider — GET /api/v1/numbers/available returns no rows for the (country, area code, number type) combination you want. You tell Orbit what you are waiting for and how many you want, and the availability check re-runs the live, cross-provider inventory search (Telnyx + DIDWW + Devotel) on demand until the pool reports enough depth to satisfy your request. The waitlist is distinct from two supply-side surfaces that both presume availability and therefore cannot help when a pool is empty: The buy flow answers “the number is in stock — take it now”. Replenishment answers “I own a pool and it is running low — top it up from orderable stock”. The low-stock alert answers “warn me before my owned bucket empties”. The waitlist answers “the number is out of stock — tell me when it comes back”.

The lifecycle

The waitlist is a four-endpoint surface. All routes are tenant-scoped and require the numbers:write scope (reads work with numbers:read).

1. Create an entry

Subscribe to a backorder with POST /api/v1/numbers/waitlist:
The server assigns id, created_at, and created_by and returns the stored entry:
An exact duplicate — the same (country, area_code, number_type) already on your waitlist — returns 409 WAITLIST_DUPLICATE with the existing_entry_id, so the waitlist cannot fill with repeated subscriptions to the same pool. The hard ceiling is 50 entries per organization; exceeding it returns 422 WAITLIST_LIMIT_REACHED.

2. Poll availability

GET /api/v1/numbers/waitlist/availability runs a live provider inventory search for every enabled entry and reports whether each pool has restocked enough to satisfy the request:
An entry is fulfillable when the live available count is at least the entry’s quantity. The availability check fans out to up to 15 enabled entries per request (one cross-provider search each, concurrency bounded to 3). When your enabled set exceeds that cap, summary.truncated is true and the response flags it — narrow the check with ?entry_id=<id> to poll a specific entry. To check a single entry, pass its id:

3. Place the purchase

The waitlist never buys on your behalf. When an entry returns fulfillable: true, place the order through the normal buy flow — the inventory is now present:
Use GET /numbers/available?country=US&type=local with the entry’s filters to select the concrete E.164 numbers, then pass them to POST /numbers/buy-bulk (up to 50 per call) or POST /numbers/purchase one at a time. The buy flow wallet preflight, per-number mutex, and per-line error handling all apply unchanged — the waitlist only tells you stock exists; it does not reserve it. Stock can turn over between your availability poll and your purchase, so treat fulfillable: true as “re-check and buy now”, not as a hold.

4. Unsubscribe

Remove an entry with DELETE /api/v1/numbers/waitlist/:entryId:
Returns 200 with { removed: true, entry_id }. An unknown id returns 404 WAITLIST_ENTRY_NOT_FOUND.

Persistence

The waitlist lives on organizations.settings.numbers.waitlist as JSONB — the same per-organization store the replenishment policy and low-stock threshold already use, so no migration is required. Adding or removing an entry is a read-modify-write of that blob, org-scoped by tenant id. A malformed entry in the blob is dropped individually rather than discarding the whole list, and any lookup or parse failure yields the empty waitlist.

Dashboard walkthrough

Standing entries appear on the Numbers page under a Waitlist tab. Each row shows the country, area code, number type, requested quantity, and the last availability result. The Recheck availability action on a row runs the same live provider search as GET /numbers/waitlist/availability for that entry interactively, so you can poll a single pool without waiting on a scheduled sweep. When an entry returns fulfillable: true, the row surfaces a Buy now action that drops you into the buy flow pre-filtered to that entry’s (country, area code, number type) — the same search you would run manually, with the filters filled in. The waitlist does not hold the stock; the action re-searches live inventory at click time, so act on a match promptly.

Automation pattern

A typical integration subscribes a backorder entry, polls availability on a schedule, and fires a purchase when an entry returns fulfillable: true. The waitlist does not push a notification — it is a poll-driven surface — so the integration supplies the cadence.

1. Subscribe once

2. Poll on a schedule

Run GET /numbers/waitlist/availability on a cadence appropriate to how quickly stock turns in the target market. Each entry costs one cross-provider live search, and the sweep is bounded to 15 entries per call, so a 15–30 minute interval is a reasonable default for a handful of entries:
When summary.truncated is true, your enabled set exceeds the per-request cap — poll the remaining entries with ?entry_id= in subsequent calls, or disable entries you no longer need.

3. Buy when an entry is fulfillable

For every result where fulfillable is true, re-search the concrete inventory and place the purchase:
Handle NUMBER_NO_LONGER_AVAILABLE per-line failures the same way the buy flow does — failed rows are never charged, so re-search the remaining quantity and retry only the replacements. After the purchase lands, remove the entry with DELETE /numbers/waitlist/:entryId if it is fully satisfied, or leave it in place if you want to keep waiting for more depth. A minimal Node.js loop:

Limits and behaviour

The waitlist is poll-driven: there is no pushed notification when stock reappears. The number.inventory.low webhook event covers your owned low-stock buckets; it does not fire for a backorder entry. Your integration supplies the poll cadence via GET /numbers/waitlist/availability. The availability check is a pure provider inventory read — it runs the same cross-provider search the buy flow uses and reports depth. It does not reserve, hold, or purchase anything, and it never touches an outbound voice/SMS path. Stock can turn over between a poll and a purchase, so a fulfillable: true result means “re-check and buy now”, not a held reservation.

When to use the waitlist vs replenishment vs a low-stock alert

The three supply-side surfaces answer different questions. Pick by the state of the pool you care about: A useful shorthand: the buy flow is for stock that is present, the replenishment policy is for stock you own that is running low, the low-stock alert warns you before an owned bucket empties, and the waitlist is for stock that does not exist yet. If GET /numbers/available returns rows for your target, you do not need the waitlist — buy directly. Reach for the waitlist only when the search is empty for the pool you want.

See Also