Foreshock

Get started

Environments and testing

Two deployment forms in the contract, and where the degradation drill actually has to happen — on a surface where you can produce failures on demand.

Updated
2026-08-24

The two environments in the contract

The contract defines two servers.

ServerFormNotes
https://api.foreshock.orgManaged endpoint.Shared control plane, per-customer data isolation.
https://{host}Self-hosted deployment.host defaults to foreshock.internal. The customer address book never leaves the customer environment.

Nothing else about the request or response shape changes between them. If your client behaves differently against one, that is a bug in your client.

Sandbox

Whether a hosted sandbox is available, and on what terms, is settled during onboarding rather than stated here. Do not build an integration plan around one existing. The failure-mode testing described below does not need it, and is more thorough without it.

The sandbox is where you exercise the happy path and the shapes: pagination, idempotent replay, webhook signature verification, evidence retrieval.

Where degradation testing has to happen

The sandbox is not where you test failure. A live service — any live service, ours included — cannot be made to fail on demand in the exact shape you need, at the moment your test suite needs it. If your only failure test is “the sandbox happened to return a 503 once”, you have not tested anything.

Point your client at a local stub you control and drive it through the matrix:

  • every degraded 200 — a HOLD verdict with each degradation reason code in turn
  • every non-2xx in the contract — 400, 401, 403, 409, 429, 500, 503, 504
  • a response that never arrives — hold the connection past your own timeout
  • a connection that is refused, a TLS handshake that fails, a name that does not resolve
  • a malformed body on an otherwise 200 response

Then assert the same thing for every row: your code path did not credit.

Because the contract is machine-readable, the stub does not have to be hand-written. Request and response contract tests are generated from api/openapi.yaml, the same file this documentation is rendered from. A stub built from the contract stays correct when the contract changes; a hand-written one silently does not.

The full matrix and the assertions to write against it are on the fail-closed client contract page.