Skip to main content
The SDK is a thin, typed wrapper over the HTTP API. In tests you get a Sandbox handle from your plugin; you can also connect to one directly. Examples are TypeScript; the Python SDK mirrors them one-for-one in snake_case.
import { prodbreak } from "@prod-break/sdk";

const sandbox = await prodbreak.connect({
  url: process.env.PRODBREAK_URL!,
  key: process.env.PRODBREAK_KEY!,
});

The Sandbox handle

MemberSignatureWhat it does
seedseed(resource, objects)Silent insert of history. Guide
resetreset({ t0? })Empty state, rewind clock to t0.
statestate(resource?)Introspect the world (debug aid).
clientclient<T>()The vendor SDK, base-URL repointed at this world.
lastResolutionTracelastResolutionTrace()Why the last call’s fields resolved as they did.
faultsForce outcomes. ↓
worldTrigger external causes. ↓
clockAdvance time. ↓
webhooksRegister endpoints, run a sink. ↓
exogenousPin out-of-control values. ↓

sandbox.faults

sandbox.faults.arm(resource, operation, {
  status: number, code: string, message?: string,
  count?: number,                                  // omit = until cleared
  match?: { input?: object, credential_id?: string },
});
sandbox.faults.clear(id?);                          // one by id, or all
Guide: Force an error →

sandbox.world

sandbox.world.trigger(event, data?);   // fire an external cause; 409 if its precondition fails
sandbox.world.next();                  // the live "what can happen next" set
Concept: Causes, not effects →

sandbox.clock

sandbox.clock.advance("5s");                       // due events fire in order, before this resolves
sandbox.clock.setDurations({ run_settle: "0s" });  // collapse named durations for deterministic CI
Concept: The virtual clock →

sandbox.webhooks

const inbox = await sandbox.webhooks.sink();        // local HTTP receiver: { url, secret, waitFor, all }
sandbox.webhooks.register(url, { subscribe: [...] }); // → { id, secret }
sandbox.webhooks.unregister(id);
Guide: Test a webhook →

sandbox.exogenous

sandbox.exogenous.pin(match, field_path, value);   // result-keyed override
sandbox.exogenous.on(event, field_path, value);    // event-name sugar → same pin
sandbox.exogenous.clear(id);
match is { operation, resource?, credential_id?, source_id?, input? }. Most-specific match wins; setting a faithful field is rejected. The same surface selects a forceable branch. Concept: Setting values & the trace →
Surface omitted from the MVP, by design: sequenced values (“tapes”), freeze/step clock verbs, replay seeding. They’re reserved in the HTTP contract so the SDK grows into them without breaking v1.