Sandbox (zz)
A synthetic jurisdiction for testing every operation and your webhook receiver against deterministic mock data
Overview
The Kausate Sandbox is a synthetic jurisdiction, code zz, for building
and testing without calling a real register. It supports every operation
against deterministic mock data, and its monitoring sources fire a webhook on
every check.
- No setup — no credentials, no IP allow‑listing.
- Free — sandbox search and data calls never consume credits. Monitors on sandbox companies are billed like any monitor.
- Deterministic — the same
kausateIdreturns the same data every time, except the living companies described below, which change on purpose. - Opt‑in — enabled per organization. Ask us to turn it on; it does not appear in your jurisdiction list until then.
Sandbox data is fabricated. Use it only to develop and test your integration.
The dataset
Sandbox companies have a kausateId of the form co_zz_…. Find them with
autocomplete or search, as in any other jurisdiction:
curl -H "X-API-Key: $API_KEY" \
"$BASE_URL/v2/companies/search/autocomplete?query=Sandbox&jurisdictionCode=zz"The sandbox is pre‑indexed with ~10,000 companies across five bands:
| Band | Sandbox number | What it's for |
|---|---|---|
| Roster | 000001–000005 | Five curated edge cases (see below) |
| Bulk | 000006–010005 | ~10,000 deterministic companies for browsing, search, and pagination |
| Living | 700001–700050 | Companies whose data evolves over time — use these to drive the change‑detection monitor |
| Error | 800001–800005 | Companies that always return a specific error code instead of data |
| Shape | 810001–810003 | Ordinary successes carrying the data shapes integrations break on |
The five roster companies:
| Company | Edge case |
|---|---|
| Sandbox Industries GmbH | a simple company — two individual shareholders, financials, documents |
| Sandbox Holding AG | a holding company |
| Sandbox Subsidiary Ltd | owned 75% by the holding + 25% by an individual → a multi‑level shareholder graph and UBO chain |
| Jane Doe Trading | a sole proprietorship — no shareholder block |
| Sandbox Defunct GmbH | an inactive / under‑external‑control company |
The kausateId of a sandbox company never changes, so tests can hard‑code it.
To get the kausateId for a sandbox number, search by number:
curl -H "X-API-Key: $API_KEY" -H "Kausate-Version: 2026-05-01" \
-X POST "$BASE_URL/v2/companies/search/sync" \
-d '{"jurisdictionCode": "zz", "advancedQuery": {"sandboxId": "800001"}}'Calling the operations
Every operation works for a sandbox company as it does for a real one. For example, a synchronous company report:
curl -H "X-API-Key: $API_KEY" -H "Kausate-Version: 2026-05-01" \
-X POST "$BASE_URL/v2/companies/report/sync" \
-d '{"kausateId": "co_zz_…"}'The same id works for finance, shareholder-graph, ubo, documents/list,
documents and prefill. Sandbox Subsidiary Ltd returns a multi‑level
shareholder graph and UBO chain.
Testing your error handling
Every error carries a stable, dotted code (see Errors).
Each company in the error band always returns one of them:
| Sandbox number | Company | Always returns | HTTP | On which calls |
|---|---|---|---|---|
800001 | Sandbox Vanished GmbH | company.not_found | 404 | every company call |
800002 | Sandbox Never Registered GmbH | company.does_not_exist | 404 | every company call |
800003 | Sandbox Confidential SAS | company.data_not_diffusable | 422 | every company call |
800004 | Sandbox Unfiled GmbH | document.not_found | 404 | document retrieval only |
800005 | Sandbox Restricted GmbH | document.type_unsupported | 400 | document retrieval only |
"Every company call" means report, financials, UBO, shareholder graph, document list, document retrieval and prefill. The company still appears in search and autocomplete:
curl -H "X-API-Key: $API_KEY" -H "Kausate-Version: 2026-05-01" \
-X POST "$BASE_URL/v2/companies/report/sync" \
-d '{"kausateId": "co_zz_…"}' # the 800001 company// → HTTP 404
{
"detail": "Company not found",
"code": "company.not_found",
"request_id": "req_e14506d86e0e452080d5de23ae5418b5"
}For the two document companies, the report and the document list succeed. The
error comes when you request a kausateDocumentId from that list.
The code, message and HTTP status are the same ones a live register failure
produces. All of these are permanent errors, so they return without retrying.
Testing awkward-but-valid data
These companies succeed, with data shapes that real registers produce and integrations often mishandle:
| Sandbox number | Company | The shape |
|---|---|---|
810001 | Sandbox Sparse | Nothing but a name. No status, legal form, address, activity, director, shareholder, document or financial statement. Every optional field your client dereferences is genuinely absent. |
810002 | Пример Ωμέγα 株式会社 مثال Ünïcøde GmbH | Non‑Latin script in the company name, the address and a director's name — Cyrillic, Greek, CJK, Arabic (right‑to‑left) and Latin diacritics. Catches encoding, collation and name‑splitting bugs. |
810003 | Sandbox Vereinigte Maschinenbau‑ … Nachschusspflicht | A legal name over 300 characters, with a matching address and a director's name. Catches column truncation, fixed‑width layouts and single‑line log formats. |
For a large result set, search for Acme, Globex, Initech, Umbrella,
Hooli or Cyberdyne. Each matches hundreds of companies in the bulk band:
# autocomplete — returns a full page of 50
curl -H "X-API-Key: $API_KEY" \
"$BASE_URL/v2/companies/search/autocomplete?query=Acme&jurisdictionCode=zz&limit=50"
# search — returns a full page of 20 distinct companies
curl -H "X-API-Key: $API_KEY" -H "Kausate-Version: 2026-05-01" \
-X POST "$BASE_URL/v2/companies/search/sync" \
-d '{"jurisdictionCode": "zz", "companyName": "Acme"}'Monitoring → a webhook on every check
The sandbox has two monitoring sources of its own, alongside the standard
company_report and shareholder_graph. List them for any sandbox company:
curl -H "X-API-Key: $API_KEY" \
"$BASE_URL/v2/monitors/sources?kausateId=co_zz_…"| Source | Behavior |
|---|---|
zz_sandbox.always_changing | Fires one generic change event on every check, for any sandbox company. Use it for a steady webhook stream to test retries and payload shape. |
zz_sandbox.simulated | A living company (700001–700050) changes one field per minute, in turn: NAME_CHANGED, COMPANY_STATUS_CHANGED, REGISTERED_ADDRESS_CHANGED, LEGAL_FORM_CHANGED, ACTIVITIES_CHANGED, and director changes. Each changed field fires its own event. |
Create a monitor pointing at your endpoint. scheduleCron defaults to monthly;
set it to control how often the sandbox delivers. Use a living company
(700001–700050) for varied events:
curl -H "X-API-Key: $API_KEY" -H "Kausate-Version: 2026-05-01" \
-X POST "$BASE_URL/v2/monitors" \
-d '{
"kausateId": "co_zz_…",
"sources": ["zz_sandbox.simulated"],
"scheduleCron": "*/15 * * * *",
"webhookUrl": "https://your-server.com/webhooks/kausate"
}'The first check records a baseline. Every check after that delivers a
monitor.change_detected webhook with the changed field in before / after
and the matching event_code. With zz_sandbox.simulated, a one‑minute cron
gives one event per check; at 15 minutes several fields have changed between
checks, about 430 events per day. zz_sandbox.always_changing gives exactly one
event per check. See Monitoring & Webhooks for the
payload and delivery rules.
Sandbox sources fire on every check: a one‑minute cron delivers about 1,440
events per day and keeps retrying against an unreachable endpoint. Delete the
monitor when you are done testing (DELETE /v2/monitors/{id}).
Last updated on