KausateKausate Docs
Features

Sandbox (zz)

A synthetic jurisdiction for exercising every Kausate capability and testing webhook receivers against deterministic, free mock data

Overview

The Kausate Sandbox is a synthetic jurisdiction — code zz — that lets you build and test against Kausate during development without touching a real registry. It implements every Kausate capability against deterministic, in‑process mock data, and its monitoring fires a webhook on every check so you can test your webhook receiver on demand instead of waiting for a real‑world registry change.

  • No credentials, no setup — nothing to configure, no IP allow‑listing.
  • Free — every sandbox SKU is zero‑credit; sandbox calls never consume credits or money, regardless of your plan.
  • Deterministic — the same kausateId returns the same data every time, so your assertions are stable (the one exception is the living companies described below, which evolve on purpose).
  • Opt‑in — the sandbox is enabled per organization. Ask us to turn it on for your org; it won't appear in your capability listing until then.

The sandbox is not a real registry. The data is fabricated and carries no accuracy guarantees — use it only to develop and test your integration.

The dataset

All sandbox companies use a kausateId of the form co_zz_…. You can discover them with autocomplete or live search just like 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:

BandSandbox numberWhat it's for
Roster000001000005A handful of curated, rich edge cases (see below)
Bulk000006010005~10,000 deterministic companies for browsing, search, and pagination
Living700001700050Companies whose data evolves over time — use these to drive the change‑detection monitor
Error800001800005Companies that always return a specific error code instead of data
Shape810001810003Ordinary successes carrying the data shapes integrations break on

The five roster companies cover the shapes you'll want to test against:

CompanyEdge case
Sandbox Industries GmbHa simple company — two individual shareholders, financials, documents
Sandbox Holding AGa holding company
Sandbox Subsidiary Ltdowned 75% by the holding + 25% by an individual → a multi‑level shareholder graph and UBO chain
Jane Doe Tradinga sole proprietorship — no shareholder block
Sandbox Defunct GmbHan inactive / under‑external‑control company

Every company in these bands is generated deterministically and always returns the same data, so you can hard‑code the kausateIds you discover in your tests without pre‑creating anything. The bands are the whole dataset — a co_zz_… id from outside them isn't a sandbox company and won't resolve.

To turn a sandbox number from the tables below into the kausateId your calls need, look it up by number — the mapping is stable, so you only have to do this once per fixture:

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"}}'

Exercising the capabilities

Every capability works against a sandbox company exactly as it does for a real jurisdiction. Grab a kausateId from autocomplete, then call any endpoint — 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 search/live, finance, shareholder-graph, ubo, documents/list + documents, and prefill. Use the multi‑level subsidiary (Sandbox Subsidiary Ltd) to see a non‑trivial shareholder graph and UBO chain — then use the error band to exercise the branches your code takes when a call doesn't succeed.

Testing your error handling

A sandbox where everything succeeds lets you ship an integration that breaks the first time it meets a real registry. Kausate publishes a stable, dotted code on every error (see Errors), and the error band gives you one company per code so you can exercise each branch of your error handling on demand.

Sandbox numberCompanyAlways returnsHTTPOn which calls
800001Sandbox Vanished GmbHcompany.not_found404every company call
800002Sandbox Never Registered GmbHcompany.does_not_exist404every company call
800003Sandbox Confidential SAScompany.data_not_diffusable422every company call
800004Sandbox Unfiled GmbHdocument.not_found404document retrieval only
800005Sandbox Restricted GmbHdocument.type_unsupported400document retrieval only

"Every company call" means the report, financials, UBO, shareholder graph, document list, document retrieval and prefill — the company is discoverable in search and autocomplete, and then every capability you order on it returns that one code:

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"
}

The two document companies behave differently on purpose: their report and their document list are ordinary successes, so you reach the error the way you would in production — list the documents, take a kausateDocumentId from the list, request it, and the retrieval fails.

These are real production error types, not sandbox‑only ones — the code, the message and the HTTP status are exactly what the same failure produces against a live registry. They are all permanent errors, so the sandbox never spends minutes retrying before it answers: report, financials, UBO, documents and prefill return in well under a second, and shareholder-graph in a few seconds.

Testing awkward-but-valid data

These companies succeed. What they return is deliberately hostile to the assumptions integrations quietly make — every field present, Latin script, sensible lengths — and each one is a shape a real European register will hand you sooner or later.

Sandbox numberCompanyThe shape
810001Sandbox SparseNothing 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 GmbHNon‑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.
810003Sandbox Vereinigte Maschinenbau‑ … NachschusspflichtA 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 a name shared by many companies in the bulk band — Acme, Globex, Initech, Umbrella, Hooli and Cyberdyne all match hundreds of companies, so any of them fills whatever page size you ask for. This works on both search endpoints:

# 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"

# live 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 ships two monitoring sources so you can test your webhook receiver deterministically. Discover them for any sandbox company:

curl -H "X-API-Key: $API_KEY" \
  "$BASE_URL/v2/monitors/sources?kausateId=co_zz_…"
SourceBehavior
zz_sandbox.always_changingFires one generic change event every tick, for any sandbox company. Use it when you just want a steady webhook stream to test signing headers, retries, and payload shape.
zz_sandbox.simulatedFor a living company (700001700050), each tick changes one real field, so you receive a different, realistic event_code in turn — NAME_CHANGED, COMPANY_STATUS_CHANGED, REGISTERED_ADDRESS_CHANGED, LEGAL_FORM_CHANGED, ACTIVITIES_CHANGED, and director changes.

Then create a monitor and point it at your endpoint (or a webhook.site URL while developing). scheduleCron is optional and defaults to monthly; set it explicitly to control how fast the sandbox delivers:

curl -H "X-API-Key: $API_KEY" -H "Kausate-Version: 2026-05-01" \
  -X POST "$BASE_URL/v2/monitors" \
  -d '{
    "kausateId": "co_zz_…",            // a living company for varied events
    "sources": ["zz_sandbox.simulated"],
    "scheduleCron": "*/15 * * * *",    // every 15 min ≈ 96 events/day
    "webhookUrl": "https://your-server.com/webhooks/kausate"
  }'

The first tick records a baseline; every tick after that delivers a monitor.change_detected webhook with the changed field in before / after and the matching event_code. This lets you exercise your receiver's payload parsing, signature verification, and retry handling without waiting for a real registry change. See Monitoring & Webhooks for the full webhook payload shape and delivery semantics.

Sandbox sources fire on every tick, so the cron you choose is the event rate. A one‑minute cron (* * * * *) delivers roughly 1,440 events per day and keeps retrying against an unreachable endpoint — pick the slowest cadence that still exercises your receiver, and delete the monitor when you're done testing (DELETE /v2/monitors/{id}).

Last updated on

On this page