New: our AI Agent is live — 140+ live registry connections, KYB without an integration. Try it →
On this page

Sandbox fidelity and known limitations

The Know Your Customer sandbox is built to one bar: a developer can point an automated integration suite at the sandbox and get the same answers the production system gives, minus a small, documented set of deliberate differences. Everything not listed on this page is intended to match production exactly. If you see a difference that is not listed here, treat it as a defect and report it (see How to report a suspected defect).

This page has three parts:

  1. Intentional divergences: deliberate by design; never a defect.
  2. Known lower-fidelity behaviours: places where the sandbox approximates rather than fully reproduces production, with the exact observable difference.
  3. How to tell an intentional divergence from a defect, and how to report one.
Not covered here

Client-specific production extensions negotiated for individual customers (for example, encrypted webhook delivery or multi-endpoint webhook fan-out) are documented in your account’s integration annex, not on this public page. If your production integration uses a client-specific extension, the sandbox may not replicate it; check your annex first. See also Client-specific and environment-specific behaviour.

Part 1: Intentional divergences (by design, never a defect)

These three are the point of a sandbox. Your suite should assert them as expected differences, not failures.

1.1 No registry or document charges

Every cost field is zero or absent, and no sandbox call ever incurs a real company-registry lookup fee or document-purchase fee. Company data is served from a pre-loaded catalogue of real public-registry records, not fetched live per call.

  • What you observe: cost and charge fields on cases, documents, and purchases are 0 or omitted. A document-purchase or registry-backed call returns the data with no charge side effect.
  • Assert this positively: no path in your suite should ever produce a non-zero charge. If one does, that is a defect worth reporting.

1.2 Latency is a configured profile that approximates production, not a live measurement

Cases build asynchronously and transition to ready after a simulated per-jurisdiction delay, so your poll-until-ready logic is exercised. The delay comes from a configured profile, not a real registry round-trip. It approximates production timing bands; it does not reproduce a specific live measurement, and real production latency varies with registry conditions.

  • What you observe: a case create returns an id immediately, reports not-ready, then becomes ready after a delay that falls within the jurisdiction’s configured band. Bands differ by jurisdiction.
  • Do not size production polling timeouts or SLAs from sandbox timings. Use the sandbox to prove your polling logic loops and eventually succeeds; use production (or your account team’s stated bands) to size timeouts.
  • See 2.5 for the specific jurisdictions where the configured band is provisional.

1.3 Data is pre-loaded and resettable

The catalogue (around 980 real companies with genuine ownership trees, plus synthetic individuals) is fixed and shared read-only. Your tenant is an overlay on top of it. You reset by deleting the cases you created; the shared catalogue is untouched and your tenant stays provisioned.

  • What you observe: the same seeded company returns the same structure on every run. Cases you create are yours alone and can be cleared to return to a clean baseline.
  • Repeatability is a guarantee: the same scenario run before and after a reset yields the same result. That is the behaviour a CI suite should rely on.

Part 2: Known lower-fidelity behaviours (approximations, with the exact difference)

These are places where the sandbox deliberately approximates production. Each entry gives the exact observable difference so you can mask it in your suite instead of chasing a false failure.

2.1 IdFailure fires on any step set to FAILED, not on a real identity-verification verdict

In production, the IdFailure webhook rides the full identity-verification (Au10tix) journey and fires only for an identity-verification failure, carrying per-subject verdict detail. In the sandbox, IdFailure fires whenever any case step is set to FAILED, and the payload carries only a representative shape, with no per-subject verdict detail.

  • What you observe: setting an unrelated step to FAILED emits an IdFailure webhook; the payload is well-formed but does not contain a real Au10tix per-subject verdict.
  • How to handle: validate your IdFailure consumer (parsing, routing, signature handling) against the sandbox, but do not assert that IdFailure implies a genuine identity-verification failure. For the real verdict flow, note this is an approximation.

2.2 DocumentsRequested and CaseRequestSubmitted fire together; there is no real upload-portal round-trip

In production, requesting documents sends an upload-portal link to an end user, and CaseRequestSubmitted fires later, when that user actually completes the upload. The sandbox has no upload-portal flow: it fires DocumentsRequested and CaseRequestSubmitted together, immediately, with nothing dispatched to a real end user.

  • What you observe: a single document-request action produces both webhooks back-to-back; no email or SMS is sent; there is no waiting-on-user state to poll.
  • How to handle: test that your consumer handles both events; do not build assertions that depend on the delay between “requested” and “submitted”, and do not expect a real message to reach an end user (dispatch is stubbed).

2.3 The org-chart root role reads "Spose"; this is a deliberately mirrored production typo

The production API returns the subject or root node of an org chart with the role string "Spose" (a long-standing typo for the subject role). The sandbox mirrors this exactly for contract fidelity.

  • What you observe: the org-chart root node has "role": "Spose", effectivePercentage: null, and no shares key.
  • How to handle: this is intended. If your production code already tolerates "Spose", the sandbox matches it. Do not “fix” it in your test expectations; production returns the same string.

2.4 AML-only cases are refused with a documented error; they are not simulated

Production can build and return an AML-only (screening-only, no company-build) case. The sandbox does not simulate AML-only cases; an AML-only entity-create request returns a documented 400 error stating the sandbox does not simulate AML-only cases, and produces no case side effect (no caseCommonId is created).

  • What you observe: an AML-only create returns 400 with the documented message; no case is created.
  • How to handle: assert the documented 400 shape rather than expecting a built case. If you need to exercise AML behaviour, use a full entity case (which does run screening against the case). AML-only is rare via the API; the contract-correct refusal is the intended sandbox behaviour.

2.5 Per-jurisdiction latency bands: China is provisional; GB and SG were retuned

The latency profile (1.2) is believable per jurisdiction, but two caveats matter if you are timing-sensitive:

  • China (CN): the configured band is an explicit unvalidated assumption; it has not been confirmed against real production China timing. Treat CN latency as indicative only.
  • GB and SG: an earlier sandbox build ran these roughly 10x too fast versus real build wall-times; they have since been retuned to bracket observed real times. Current bands are corrected, but they remain configured approximations, not live measurements.
  • How to handle: for any latency-sensitive test, assert the shape (delay present, non-zero, in-band, jurisdiction-distinct, poll loop actually loops) rather than a specific wall-clock value. Do not derive production timeout budgets from sandbox CN, GB, or SG timings.

2.6 Screening surfaces no real hits on real people; identities and documents are synthetic

Screening runs against the case but does not surface real sanctions, PEP, or adverse-media matches on real individuals. Individuals and their documents are synthetic. Identity prevalidation is exercised (for example, an unrecognised or forged document filename returns IdentityDocumentNotRecognized in prevalidationMessages), but no real person is verified.

  • How to handle: test your handling of match sets, IsCaseAMLPositive, and prevalidation reason codes against the sandbox’s synthetic data; do not expect real-world match content.

2.7 Reports are for evaluation only

Sandbox reports demonstrate the real format and content structure and are genuinely openable PDFs, but are not for production compliance use. Volatile fields (timestamps, ids) differ per environment.

  • How to handle: assert on report structure and stable content, not byte-equality with a production report.

2.8 Uploaded document bytes are not stored; a downloaded document returns a sample placeholder

When you upload a document to a case, the sandbox records the upload (the document step, the file name, the prevalidation verdict, availability) and returns the real upload result, so your upload flow is fully exercised. It does not, however, retain the uploaded file bytes: the content is processed for prevalidation and then discarded rather than persisted. As a result, downloading a document you uploaded returns a valid, openable sample placeholder PDF, not the exact bytes you sent.

  • What you observe: an upload succeeds and the document step reports the file as available, but a subsequent document download returns a placeholder PDF rather than your original file. Pre-loaded catalogue documents download as their real seeded content.
  • How to handle: assert that your upload call succeeds and that the document step and verdict are updated; do not assert byte-equality between what you uploaded and what a later download returns. Test the round-trip mechanics, not the payload fidelity.

Part 3: Telling an intentional divergence from a defect, and reporting one

The rule: everything on this page is expected. Everything else is meant to match production. If a sandbox response differs from production in a way not listed above (a different HTTP status, a renamed or recased field, a changed enum value, a missing required field, a null where production sends a value or vice versa, a different error envelope), treat it as a defect.

Before reporting, quickly rule out the three “allowed to differ” classes, which are never defects:

  • Identifiers (caseCommonId, step ids, document ids, alert ids, tenant id) differ between environments by design. They must be present, well-formed, and internally consistent (the id a create returns is the id a read accepts), not equal to a production value.
  • Timestamps and relative dates (creation times, audit-trail times, “expires in N days”, TTLs) differ by design. Assert presence, format, and plausibility, not equality.
  • Charges and latency (Parts 1.1 and 1.2) differ by design.

If the difference is none of the above and is not in Parts 1 or 2, report it with:

  • the endpoint and method,
  • the exact request (headers, body, with secrets redacted),
  • the sandbox response you got and the production response you expected,
  • the field or fields that differ.
Report a suspected defect

Send well-scoped drift reports to help@knowyourcustomer.com. We take contract drift seriously: a response that works against the sandbox but breaks against production is the worst outcome a sandbox can produce, so a well-scoped drift report is genuinely valuable to us.

This page is versioned. Last reviewed against production: the parity check records the tracked production revision on each run; this page is stamped when that heartbeat first runs.