Skip to main content

Number rental and your wallet

A phone number in Orbit is not a one-time purchase. It is a monthly wallet debit with a lifecycle you control — and the two subjects most docs keep apart, billing and number states, meet on one arc: the wallet can’t cover a rental → warnings → suspend → reactivate. This page is the money side of the Number status map: what an idle number costs, what a failed renewal actually does, and the posture that keeps it from ever happening. The step-by-step operations (auto-renew toggle, reactivate, scheduled release, reclaim) are in Number lifecycle.

What an idle number costs

Every number you hold carries a monthly rental charged from your prepaid wallet, timed by the row’s next_billing_at. The rental runs whether the number routes thousands of calls or none — an idle active DID still debits. The charges show up as ledger rows you can reconcile through GET /api/v1/billing/transactions, alongside your usage debits. What happens when the balance can’t cover the charge:
  1. Before the renewal is attempted. When a number approaches next_billing_at and the wallet is already below the monthly charge, every owner and admin gets an email (“Action needed: add funds before your number renews”) plus an in-app Notification Center alert, both linking to the top-up screen. The email is throttled and the in-app alert fires at most once per billing cycle — a low balance produces one clear prompt, not a pile-up.
  2. When the charge fails. The renewal is attempted once at next_billing_at. Too little balance does not flip the number’s status — it stays active, you get the “Number renewal failed — add funds” notice, and Orbit re-attempts the charge once a day. A top-up that settles before the daily attempt renews the number automatically; there is no manual retry step.
  3. Notifications land with owners and admins only. Other team members are not emailed, so the people who can actually add funds are the ones warned.

The suspension arc

A renewal that stays unpaid for 7 days past its due date suspends the number:
While the number is suspended it sends and receives nothing, and the active-only list filter hides it from number pickers — which is why a suspended sender can look like “no numbers on file” surface-side. The row is still yours. Reactivating (POST /api/v1/numbers/:id/reactivate, or the Numbers page in the dashboard) returns it to active with its messaging profile, voice connection, routes, and labels unchanged. Reactivation is gated by the wallet being able to cover the renewal: top up first, then reactivate once. Suspension is also the only automatic state change an unpaid balance causes. Orbit never releases your number over a $0 wallet — the arc above ends in a reversible soft pause, not in the release pipeline.

Why suspension is not release

suspended and parked look similar — both stop traffic — and they are opposite in every way that matters: So a $0 wallet can put every number you own into suspended, and every single one comes back active on reactivation. Suspension never walks a number toward resale, and it never touches the per-region aging table that protects recipients from rapid DID churn. The only path to losing a number is the release path you initiate.

Scheduled release and reclaim — the separate arc a suspend never enters

When you decide a number should go, the flow is deliberate and one-directional after a final gate:
  1. Schedule a release (PUT /api/v1/numbers/:id/scheduled-release). The number moves to parked — the release-path grace state.
  2. The grace window stays open. While parked, the number is still assigned to you, and POST /api/v1/numbers/:id/reclaim moves it back to active without a re-purchase.
  3. The window closes. The parking-expiry scheduler issues the carrier release and the row flips to released. That is terminal — the only way back is a fresh purchase.
Billing interacts with this arc only in one place: the parking window extends at least to your paid-through date if you release right after a renewal, so you are never paid-past-a-release. The states themselves and the post-release aging posture are documented in Number status map and Number reuse, aging, and post-release posture.

Two controls: auto-renew per number, auto-top-up for the fleet

There are exactly two knobs, and they compose:
  • Auto-renew is the per-number prevent-default control. Toggle it via PATCH /api/v1/numbers/:id/auto-renew (auto_renew: true) and Orbit re-bills the rental at next_billing_at automatically; only a row explicitly opted in renews — an unset flag reads as off, and the number lapses at next_billing_at instead. Auto-renew decides whether a payment is due; it cannot guarantee the wallet can pay it.
  • Auto-top-up is the whole-fleet prevent-default control. It keeps the wallet funded: when the balance crosses your threshold_minor, Orbit charges your saved payment method off-session and credits the wallet. The evaluator runs every 15 minutes, consecutive auto-charges are separated by a 5-minute cooldown and capped at one per hour with a per-day cap (default 5), and a settled auto-charge is indistinguishable from a manual top-up in the ledger. Configure it via GET/PUT/DELETE /api/v1/billing/auto-topup or Dashboard → Billing → auto-replenish; full semantics on the Billing overview.
Auto-renew answers “should this number renew” and auto-top-up answers “can the wallet pay when it does.” Together they make suspension a choice, not an accident — the reason rental failures recover on their own instead of accumulating into a fleet-wide pause.

Worked scenario: a 50-DID campaign tenant that hits $0

One tenant holds 50 DIDs where each one was opted into auto-renew, staggered renewal dates across the month. The wallet slides to $0 mid-month:
  1. Renewals fail in staggered order, not as one event. Because next_billing_at differs per number, the ~2 renewals per day that arrive first are the first to fail. The failed renewals emit the retry-once-a-day warnings; numbers that haven’t reached their renewal date are untouched.
  2. Warning volume stays bounded. The pre-renewal low-balance email is throttled and the in-app alert fires at most once per billing cycle per number — 50 struggling numbers produce staggered single reminders, not an inbox flood. The tenant sees the wallet problem plainly instead of a pile-up that looks like a platform malfunction.
  3. First suspensions arrive 7 days after the first unpaid renewal. The number whose renewal failed on day 1 suspends on day 8; the rest follow their own 7-day clocks. Nothing suspends in bulk unless renewals were bulk-aligned all along.
  4. Auto-top-up intercepts the cascade before it binds. If auto-top-up is configured, its 15-minute evaluator sees the balance below threshold_minor and charges the saved card — usually within one evaluator cycle. The settled credit lands before the next daily renewal retry, the retry succeeds, and the number never leaves active. The hourly and daily auto-charge caps pace recovery instead of stampeding the card.
  5. The mass-suspend that never happens. With auto-top-up on, the arc stops at step 1 for every number whose renewal hasn’t retried yet. Without auto-top-up, every number still recovers on top-up: fund the wallet once, the next daily retry clears the overdue renewals, and the few suspended rows reactivate from the Numbers page with configuration intact. A 0walletsuspended50numbers?All50comeback.A0 wallet suspended 50 numbers? All 50 come back. A 0 wallet released none of them.

Posture checklist

Use suspend as the recovery state it is, not the accident it doesn’t have to be:
  • Keep auto-renew on for numbers you intend to keep; turn it off on teardown candidates and let them lapse deliberately.
  • Set auto-top-up with a threshold_minor above your largest daily rental+usage draw, so the evaluator fires before any renewal retry cycles.
  • Poll GET /api/v1/billing/balance from your integration and alert on outbound_block_reason — the same 402 pause machinery that gates sends tells you the wallet ran dry long before the 7-day suspend window closes.
  • Reactivate after top-up, once — the renewal retry and reactivate are idempotent, so racing them cannot double-charge you.

See also