Sandbox & test numbers

Test keys (ssms_sk_test_) run against a fully simulated environment: no carrier traffic, no charges, and nothing real ever sent. Every endpoint works, so you can build your whole integration, including webhooks, before going live.

Your sandbox number

Signup provisions a sandbox number in the reserved +1 500-555-XXXX range. It's the from for outbound tests and the to for simulated inbound. You can "purchase" more from GET /v1/numbers/available + POST /v1/numbers; the whole numbers API works in the sandbox.

Your own phone

The console asks for your cell once, right after signup, and texts you a code. Once it's verified, a test key delivers to that one number for real, so your first API call makes your phone buzz. Every other destination stays simulated. Real sandbox texts are capped at 10 a day and end with - via SimpleSMS sandbox. The response is a normal message with "test": true and an X-Sandbox-Real-Delivery: true header. Your phone also counts as your first verified recipient when you go live on the free tier.

Magic destination numbers

Send to these numbers to trigger fixed behaviors:

NumberBehavior
+15005550006Delivered: message.sent then message.delivered; the message is delivered by the time the send returns. Any other number behaves the same.
+15005550013Delayed delivery: status sent, then really delivered at least 5 seconds later. Poll GET /v1/messages/{id} (it settles as soon as the delay has passed) or wait for the message.delivered webhook (within about a minute). Use it to test code that waits on delivery.
+15005550001Stuck: status stays queued forever, no delivery event.
+15005550002Failed, no reason given: failure.code unknown.
+15005550007Failed: filtered as spam, failure.code carrier_filtered.
+15005550008Failed: refused by the carrier, failure.code carrier_rejected.
+15005550009Failed: number not in service, failure.code invalid_number.
+15005550010Failed: a landline, failure.code landline (and GET /v1/lookup says landline).
+15005550014Failed: phone unreachable, failure.code unreachable.
+15005550011Opted out: 403 forbidden, exactly as for a recipient who replied STOP. Nothing is written to your opt-out list.
+15005550012Rate limited: 429 rate_limited with a Retry-After header. Nothing is stored.

Failed numbers return 201 with status failed and emit message.sent then message.failed; the failure object and the event payload are the same ones a real carrier failure produces (see Errors). Every sandbox message has a full timeline, segments, encoding, a price of 0, and destination_carrier from the sandbox lookup.

Simulated inbound

POST /v1/test/inbound delivers a fake inbound SMS to one of your sandbox numbers through the real pipeline: it appears in GET /v1/messages and emits a message.received event. (Test keys only; live keys get a 403 test_mode_only.)

Sandbox limits

A ceiling of 1,000 messages/day per account keeps the sandbox healthy. It's not a product quota. If you legitimately hit it, tell us.