Test & live modes
Every API key is bound to exactly one project and one mode — test or live.
The mode is baked into the key prefix:
sk_test_…— a test-mode keysk_live_…— a live-mode key
You pass the key as a bearer token, and the mode comes along with it. There is no
mode parameter on any request — the key decides.
# A test-mode request: builds, schedules, and delivers against test data only.curl https://api.schedstack.com/v1/schedules \ -H "Authorization: Bearer sk_test_…" \ -H "Content-Type: application/json" \ -d '{ "endpoint": "https://example.com/hooks/orders", "method": "POST", "body": "{\"order_id\":\"ord_123\"}", "delay": "30s" }'The resources you create echo their mode back so you always know which side you’re on:
{ "id": "sch_…", "object": "schedule", "mode": "test", "endpoint": "https://example.com/hooks/orders", "method": "POST", "state": "active"}Data is fully isolated per mode
Section titled “Data is fully isolated per mode”Test and live are separate datasets within the same project. A sk_test_… key
cannot read, list, or mutate live data, and a sk_live_… key cannot touch test data.
Isolation is enforced at the query layer — every read and write is scoped by
(project, mode).
This applies to everything keyed off a request:
- Schedules, endpoints, and deliveries are mode-scoped.
GET /v1/schedules,GET /v1/deliveries/{id}, and attempt history return only rows for the calling key’s mode. - Idempotency keys are mode-scoped too. The same
idempotency_keyused by ask_test_…request and ask_live_…request will not collide — they resolve to independent schedules. A test request never replays a live response, or vice versa.
Only live first attempts count toward the SLO
Section titled “Only live first attempts count toward the SLO”SchedStack publishes a 100–300 ms dispatch SLO (fired_at − scheduled_for, p99,
where fired_at is the first byte out). The SLO measures dispatch initiation — when
we start the send — not your receiver’s response time.
The published number is computed over a deliberately narrow population:
livemode only — test-mode dispatches are excluded entirely.- First attempts only (the initial fire). Retries, reclaim/recovery fires, rate-limit or breaker deferrals, catch-up/coalesced fires, and DST-shifted fires are all excluded.
Test mode is for correctness, not timing. Use it to verify that your endpoint receives, verifies the signature on, and idempotently handles a delivery — but don’t read anything into test-mode dispatch latency.
Develop safely in test mode
Section titled “Develop safely in test mode”-
Build against a
sk_test_…key. Point your integration at the same base URL and paths — only the key changes. Schedule short delays, watch deliveries land, and inspect retries and the dead-letter view without touching live data. -
Verify the full contract. Confirm your endpoint verifies the
Sched-Signatureand dedupes on the delivery ID — at-least-once delivery means you own deduplication. Test mode is the place to prove this before real traffic. -
Swap to
sk_live_…to go live. Same code, live key. Because data is isolated, nothing you created in test leaks into live — you start clean. Keep the test key wired into CI and local dev.
Where to go next
Section titled “Where to go next”- Idempotency — how idempotency keys are scoped and how to dedupe at-least-once delivery.
- Retries & dead-letter — what happens when a delivery doesn’t land on the first attempt.
- Quickstart — schedule your first durable delivery and watch it land.