+ + +
[ Sandbox as a Service — the other SaaS ]

Break prod
before prod
breaks.

Stateful, controllable sandboxes for the APIs you build on — so your end-to-end tests run against something as loyal to production as it gets, without a live key, a side effect, or a flaky call.

setup is one line · your real vendor SDK · zero live calls

payments.failure.test.ts vitest
test("a declined run surfaces the vendor's error", async ({ sandbox }) => {

  // arm the failure your app must survive — fires once, then clears
  await sandbox.faults.arm("task_runs", "create", {
    status: 402, code: "insufficient_funds", count: 1,
  });

  const deck = sandbox.client();  // your real vendor SDK, repointed

  await expect(deck.taskRuns.create({ taskId: "task_rent" }))
    .rejects.toMatchObject({ code: "insufficient_funds" });
});
we offer production-faithful sandboxes for every API below
+ +
the point

As loyal to production as it gets.

Same wire shapes, same object lifecycles, same webhooks, same clock-driven behavior — verified against the live API with contract tests. Your end-to-end suite runs against a stand-in it can't tell apart from the real thing, plus the one thing production will never give you: control.

+
[ The Sandbox ]

A rehearsal stage for every failure.

One command boots a faithful, stateful stand-in for the real API. It's a real server — not a pile of canned responses.

~ zsh
$ prodbreak up deck --port 8801
prodbreak · pack=deck · world ready
key minted: pbw_k3y_d3m0

$ curl -XPOST :8801/v2/task-runs -d '{"task_id":"task_rent"}'
{ "id": "trun_8f3k2", "status": "pending", ... }

$ curl :8801/v2/task-runs/trun_8f3k2
{ "id": "trun_8f3k2", "status": "completed", ... }  # it remembers

$ curl -XPOST :8801/__admin__/clock/advance -d '{"days":30}'
{ "ok": true }  # 30 days of renewals & retries — instantly
3.1 / state

Stateful round-trip

Create it, list it, update it — the sandbox remembers. Multi-step flows, server-derived fields, and full object lifecycles behave like the real thing.

3.2 / control

Force any outcome — outputs, not just errors

Script the values your code needs to see — run results, balances, webhook payloads — and arm the faults it must survive (402, 429, timeout). No more hand-written fixtures rotting in your repo: a fixture is a snapshot in time; this is a live world you direct.

3.3 / seed

Seed any starting state

Start every test from "customer with three failed payments" — not from an empty database and forty lines of setup calls.

+
[ The Gate ]

Stability, enforced on every deploy.

Failure handling rots silently — a refactor breaks your retry logic and nothing notices, because no test ever exercises it. Put prodbreak in CI and every PR is checked against every failure you've rehearsed.

Get early access
4.1 / coverage

Every PR, every failure mode

One job step boots the sandbox. Your whole integration suite runs against it — including the paths that only break at 3am.

4.2 / determinism

Deterministic by design

Same seed + same script = same result, every run. No flaky live calls, no shared-sandbox state bleeding between PRs — every run gets its own isolated world.

4.3 / safety

No keys, no costs, no risk

No live credentials in CI, no rate limits, no per-call charges. The most dangerous thing a test can do is fail.

.github/workflows/integration.yml
- name: Boot sandbox
  run: prodbreak up deck --port 8801 &

- name: Integration tests
  run: npm test
  env:
    DECK_BASE_URL: http://localhost:8801  # no live keys in CI
All checks have passed
4 successful checks
Hide all checks
pb integration / declined payment recovery (pull_request) Successful in 2sDetails
pb integration / rate-limit backoff & retry (pull_request) Successful in 1sDetails
pb integration / webhook replay after downtime (pull_request) Successful in 3sDetails
pb integration / 30-day dunning cycle (pull_request) Successful in 1sDetails
This branch has no conflicts with the base branch
Merging can be performed automatically.
Merge pull request
"Resilience becomes a regression suite."
[ The Field ]

Schema mocks echo. Sandboxes remember.

prod break stripe-mock Prism / WireMock live API
Stateful round-tripYESYES
Force vendor-shaped errorsYES~ magic values
Seed a starting stateYES~ by hand
Webhooks you controlYES~ wait & pray
Virtual clockYES
Works when the vendor has no sandboxYES~ schema only
Safe for CI — no keys, no costYESYESYES

[ no shade — stripe-mock and Prism are great at what they do. They're just not built for this. ]

+
[ The Packs ]

One engine. A pack per API.

Each pack is built against the live API and verified with contract tests — fidelity is measured, not assumed.

deck in build

Banking-data tasks & runs. No native sandbox exists — every real call is live. The reason prodbreak exists.

stripe in build

Payments, subscriptions, dunning. Test mode exists — but it can't force most failures. We can.

sendgrid next up

Email delivery, bounces, suppression lists — and the events you can't trigger on demand.

twilio next up

SMS & voice status callbacks, delivery failures, carrier filtering.

slack next up

Bots, events, rate-limit tiers, and workspace state your tests can own.

shopify next up

Orders, inventory, webhooks — a full store as test fixture.

echo shipped

The open template pack. Runs today — boot it and curl the whole control surface.

+ request an API

Tell us which API keeps breaking your prod. That's our roadmap.

[ Adoption ]

Setup is one line. Your app doesn't change.

~ zsh
$ npx prodbreak up deck
prodbreak · pack=deck · sandbox live → https://deck.prodbreak.dev
.env.test
- DECK_BASE_URL=https://api.deck.co/v2
+ DECK_BASE_URL=https://deck.prodbreak.dev

the entire migration

step / 01

Pick a pack

One command boots a sandbox for the API you integrate. It mints its own key and owns its own world.

step / 02

Repoint your SDK

Change one env var — the base URL. Your real vendor SDK, your real app code, untouched.

step / 03

Test like you own the vendor

Seed state, arm faults, advance the clock, fire webhooks. The API does what your test says it does.