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.