GET returns realistic, fixed dummy data; every write validates your input exactly like production but never touches a real account; and a one-shot webhook test-send lets you prove your receiving endpoint works before you register a real subscription.
The sandbox key
Every sandbox request uses the same shared key — there’s nothing to create and nothing to keep secret.The sandbox is currently in limited rollout.
kn_sandbox_example below is illustrative, not a working key — contact us for the current value while general access is being rolled out.Authorization header:
/v1/sandbox/ prefix instead of /v1/ — nothing else about the request shape changes. A request to /v1/sandbox/* with a real kn_live_... key (or vice versa) is rejected with 401 Unauthorized; the two are never interchangeable.
Because the key is public, the sandbox has its own coarse, shared rate limit — separate from the per-key limits described in Authentication. If you’re testing high request volume, do it against a real key instead.
What’s covered
Each one accepts the same parameters and returns the same response shape as its production counterpart in the API Reference — code you write against the sandbox should work unmodified against a real key.
Reseller/child-tenant provisioning (
POST /v1/tenants, credit limits, usage, scoring config, script config) isn’t in the sandbox — those actions create real state for a real tenant, which doesn’t fit a shared, no-signup key. Try those with a real key instead.Dummy data
EveryGET returns the same small, fixed dataset every time — two example accounts (“Acme Robotics”, “Rocket Logistics”) and their contacts. List endpoints paginate for real (cursor/next_cursor/has_more behave exactly like production), so you can test your pagination code end to end:
POST /v1/sandbox/enrich, POST /v1/sandbox/prospect, and the filter-sets endpoints) validate your request body exactly like production — send a malformed body and you’ll get the same 400 you’d get for real — but nothing is saved. A valid request gets back a realistic canned response instead.
Multi-tenant preview
If you manage tenants on behalf of your own customers, the sandbox includes one fixture child tenant so you can see the parent → child delegation pattern (X-Knock-Tenant header or ?product_slug=) without provisioning anything real:
sandbox-child-eu is shown above for a concrete example — call GET /v1/sandbox/tenants if you’d rather look up the fixture child’s product_slug programmatically instead of hardcoding it.
Testing your webhook receiver
The one thing you can’t fully dry-run against fixture data alone is your own webhook endpoint.POST /v1/sandbox/webhooks/test sends a single, real, signed event to a URL you provide — immediately, synchronously — so you can confirm your receiver validates signatures correctly before you register a real subscription:
event_type accepts the same values as a real webhook subscription (account.identified, contact.identified, score.changed, play.triggered, signal.detected, tenant.limit_reached, tenant.limit_approaching). The response tells you whether delivery succeeded:
GET /v1/webhooks/{id}/secret. The signature field above is returned directly in this response so you can compare it byte-for-byte against the X-Knock-Signature header your receiver actually saw. For how signature verification works end to end against a real, persisted subscription, see Receive Real-Time Visitor Event Alerts via Webhooks. Nothing is stored either way: there’s no subscription to list or delete afterward, just the one test delivery.
Next steps
Quickstart
Ready to go live? Get your own API key and install the tracking script.
API Reference
See the full parameter and response reference for every endpoint the sandbox mirrors.