Test keys
A test key lets you build and run an integration without emailing your customers.
It does everything a real key does — reads your data, renders the statement, works out who would receive it, records the run, fires your webhooks — and stops at the last step. The email is never handed to our mail provider.
Getting one
- Account → API → New key.
- Give it a label and the permissions it needs.
- Tick Test key.
Test tokens look different, so you can tell at a glance which one you are holding:
stky_test_kZq3n8VYc2sL5pR1tW7xJb4hD6gF9mA0eU ← test stky_Yb7mK2pQ9wR4tN6vX1zC8dF3gH5jL0aS ← live
A key is test or live for its whole life. There is no switch. To go live, create a second key without the box ticked and move your system across — which is what you would want anyway, so your staging and production systems hold different credentials.
You can confirm which one you have at any time:
curl https://app.statey.app/api/v1/organisation \
-H "Authorization: Bearer stky_test_your_key_here"
{
"api_key": { "label": "Staging", "scopes": ["read", "write", "send"], "sandbox": true }
}
What is different, and what is not
| Test key | |
|---|---|
| Reads your real data | Yes — same contacts, same balances |
| Renders the statement PDF | Yes |
| Works out who would receive one | Yes |
| Records the run and its recipients | Yes, marked as a test |
| Fires your webhooks | Yes |
| Uses your daily send allowance | Yes |
| Actually emails anyone | No |
Two of those surprise people, so they are worth saying plainly.
It reads your real data. A test key is not a separate sandbox account with invented customers. It sees your live contacts and their real balances, and renders the statement they would actually receive. That is deliberate — the failures worth catching are the ones involving your own data, like a customer whose statement comes back blank.
It uses your daily allowance. A test run of 300 contacts spends 300 of your 5,000. Testing is not a free send path. Keep rehearsals modest and check X-Quota-Remaining .
Seeing what happened
A test run appears in Sent items like any other, badged "Test run — not sent". Use the Exclude test runs filter for a clean view of real sends.
Through the API, campaigns carry a sandbox flag:
curl https://app.statey.app/api/v1/campaigns/7a6b5c4d-... \
-H "Authorization: Bearer stky_test_your_key_here"
{
"campaign": { "id": "7a6b5c4d-...", "sandbox": true, "subject": "August statements" },
"recipients": [
{ "contact_id": "9f8e...", "contact_name": "Acme Supplies",
"email_address": "accounts@acme.example", "status": "pending" }
]
}
The recipient list is the useful part: these are the people who would have been emailed, with the addresses that would have been used. Check it before you go live.
Their status stays pending , because nothing was delivered and so no delivery ever came back.
Webhooks from a test run
Test runs fire your webhooks, so you can build and verify a receiver end to end.
statement_run.sentfires as normal, with"sandbox": truein the payload.statement.delivery_updatedis simulated — onedeliveredevent per recipient, also marked"sandbox": true.
The second needs explaining. That event normally relays what our mail provider tells us, and a test run never reaches them, so no real event will ever arrive. Without simulation, the webhook most people want to test would be the one a test key could not exercise.
So a simulated delivered is emitted instead. Two things follow:
- You cannot rehearse a bounce. Simulated events are always
delivered. To test bounce handling, post a sample payload to your own endpoint directly. - Filter on
sandboxif it matters. If your integration writes back to a ledger or raises tasks, ignore events carrying"sandbox": true, or a rehearsal will show up in your real records.
Suggested way to use it
1. Create a test key with the permissions you need. 2. Build against it. Check the recipient list on each run, not just the 202. 3. Point your webhook receiver at it and confirm you handle duplicates and signatures. 4. Create a live key, move the credential across, and revoke nothing — keep the test key for your staging environment.
Step 4 is the point of separate keys: you keep a safe place to try changes after you have gone live.