Skip to main content

Sandbox Magic Numbers

Orbit’s sandbox simulator routes every send through a deterministic rule keyed by the trailing digit of the recipient number, so you can exercise your delivery-receipt (DLR), retry, and dead-letter handling without touching a real carrier. Every send is keyed by the trailing digit of the recipient number. Send to +15005550005 and you receive an expired delivery receipt; send to +15005550003 and you receive undelivered; send to +15005550001 and the carrier only ACKs the submit and never reports a final state — so you can exercise your DLR-timeout handling. Each scenario walks the same intermediate→terminal sequence a real carrier produces. The simulator only activates when:
  1. The API key is a sandbox key (prefix dv_test_sk_*), or
  2. The organisation has is_sandbox = true in the Orbit data plane, or
  3. The request carries the X-Test-Mode: true header from the dashboard.
Magic numbers in live mode are sent to the real carrier — there is no production-side magic behaviour. The trailing-digit convention is sandbox-only.

Message sends — the delivery-state table

The trailing digit of the recipient selects one of ten delivery scenarios. Each scenario emits its full delivery-receipt sequence as message.status webhooks — an intermediate sent acknowledgement (when the message reaches the carrier) followed by the terminal outcome: Each webhook carries a state_class (intermediate or terminal) and an is_terminal flag so your handler can tell an in-flight update from a final outcome — the same tags the production delivery-receipt path stamps. The trailing-0 (carrier rewrite) terminal receipt also carries body_rewritten_by_carrier: true, mimicking regulatory sender-ID rewrites. Delivery receipts do not change your stored message — a sandbox send never reaches a carrier, so the message keeps its honest test_sent status rather than being promoted to delivered/failed. The receipts appear only in the webhook payloads sent to your sandbox webhook URL, never on the message you retrieve through the API. Any E.164 number with the same trailing digit triggers the same scenario — +15005550009, +15555550009, and +908505550009 all resolve to the delayed-then-delivered sequence.

Example: simulate a failed delivery

Your sandbox webhook endpoint receives a single message.status event with data.status: "failed", state_class: "terminal" — no real carrier is touched, no balance is deducted.

Example: simulate a delivered message

Your webhook receives two message.status events in order: an intermediate data.status: "sent" (state_class: "intermediate"), then data.status: "delivered" (state_class: "terminal").

Voice calls

Sandbox voice calls always resolve completed today. The trailing-digit table below is a reference catalog of the outcomes simulateCall can compute — it is not yet wired into the live call path. The sandbox short-circuit pins the call record and the async lifecycle event to completed, and returns { "status": "completed" } synchronously, regardless of the recipient’s trailing digit. If you place a sandbox call to a number ending in 9 expecting no-answer, you will still receive completed. Treat the table below as the planned mapping, not behaviour you can trigger today.
simulateCall keys on the trailing digit too, but with three outcomes: The simulated lifecycle (call.initiatedcall.answeredcall.ended) fires through the same sandbox-events worker.

Reference catalog: GET /sandbox/numbers

Orbit also publishes a 10-state magic-number catalog for clients that want to render their own developer surface (e.g. an embedded “Test your integration” widget). This is a descriptive reference table returned by the read-only GET /sandbox/numbers endpoint and serialised from SANDBOX_MAGIC_NUMBERS in @devotel/messaging/sandbox/magic-numbers.
These ten states are the same scenarios the live send/DLR path fires (see the delivery-state table above). The catalog is a machine-readable copy of that mapping so you can render your own developer surface — e.g. an embedded “Test your integration” widget — without hard-coding the digits and latency bands yourself.
Response (one entry per trailing digit):
The full catalog covers the statuses submitted, delivered, undelivered, failed, expired, unknown, rejected, blocked, delayed, and carrier_rewrite, each keyed by trailing digit (10). See SANDBOX_MAGIC_NUMBERS for the canonical example numbers, latency bands, and descriptions.

Hard rules

  • No real carrier is ever reached. Every magic-number send short-circuits before the provider router resolves a backend.
  • No balance is deducted. Sandbox sends always have cost_usd_cents: 0 and never reach Stripe or your wallet.
  • DLRs fire to your sandbox webhook URL only. Configure this separately from your live URL under Settings → API Keys → Sandbox so production handlers never see test traffic.
  • Channels covered: SMS, MMS, WhatsApp, RCS, Viber, Telegram, Messenger, AMB, Email. Channel-specific status codes (e.g. WhatsApp 131047) are out of scope for the magic-number convention; the trailing-digit rule maps to the canonical generic status set.