What a test key does
Create one in the dashboard under Developers, API keys, with the mode set to Test. It starts cc_test_. Requests made with it go through the same checks as live ones: the body is validated, numbers are checked and de-duplicated, opted-out numbers are refused, and you get the same response shapes back. The difference is that every message has test set to true, uses no credit, and never reaches a phone.
{
"data": {
"batch_id": "bat_01J9Z8X7W6V5T4S3R2Q1P0N9M7",
"messages": [{ "id": "msg_01J9Z8X7W6V5T4S3R2Q1P0N9M8", "status": "queued", "credits": 0, "test": true }],
"rejected": []
},
"meta": { "credits": 0, "replayed": false, "test": true }
}Test keys work while your account is still waiting to be checked, so you don't have to wait for approval to start building.
The simulated timeline
About a second after you send, each test text moves to sent, and about two seconds after that to delivered. Each step records a timeline entry and fires message.sent and then message.delivered to your webhooks, signed exactly as live events are, so your signature check gets a proper workout.
Test texts show in the dashboard's message history with a test label, which keeps them easy to tell apart from real ones.
Limits
Test texts are free, so they're capped: up to 50 numbers in one request and 300 texts an hour per account. Go over the hourly figure and you get a 429 with a Retry-After header, the same as the live rate limit.
| Test key | Live key | |
|---|---|---|
| Key prefix | cc_test_ | cc_live_ |
| Texts actually sent | No | Yes |
| Credits used | None | One per SMS part |
| Works before your account is approved | Yes | No (403 account_pending) |
| Number checks, opt-outs and rejections | Same as live | Yes |
| Webhooks | Fired and signed, like live | Yes |
| Recipients per request | Up to 50 | Up to 1,000 typed numbers, plus contacts and lists |
| Numbers per hour | Up to 300 | Set by your rate limit and balance |
| Campaigns | Drafts only, cannot be sent | Yes |
What test mode skips
- Nothing reaches a phone, so you won't see
message.receivedoropt_out.createdfrom a test send. Use the webhook test button (orPOST /webhooks/{id}/test) to check your handler for those. - Every test text ends up delivered. There's no way to simulate a failed or undelivered text yet, so write those paths against the payloads in the webhooks guide.
- Campaigns can't be sent or cancelled with a test key; that returns
403 test_mode_not_supported. Test the text itself withPOST /messagesinstead. - A test key can't cancel a live scheduled text.
Switching to live
Once your account is approved and has credit, create a live key and swap it in. Test and live Idempotency-Key values are kept apart, so a key you used in testing can't make a live request return an old test answer. The quickstart walks through the whole thing.