Some of the data an API returns, it computes from what you gave it. Some of it comes from outside its own logic — values even the real API can’t predict. ProdBreak treats these differently, and the line between them is the most important idea in the product.

Two kinds of data

KindCan you set it?Examples
Faithful data — ids, status, amounts, timestamps, counters, anything the API derives from your inputs and its own lifecycleNo — faking it would break fidelity, and you never need toid, status: succeeded, amount, created_at
Out-of-control values — what the API reads or receives from outside itself; the real service can’t predict these eitherYes — this is the legitimate surface you controla bank balance an agent reads, a transcript, a model’s risk score
The whole override surface exists for the second row. We call these exogenous values — “from outside” — and the SDK names them that way (sandbox.exogenous.*).

Why the line matters

Faithful data is non-negotiable. Create a charge for $20, and the GET returns $20. The status really advances pending → succeeded. You can’t fake these because the value of the sandbox is that they’re real — that’s what your green test is asserting against. Out-of-control values are genuinely nobody’s to predict. When an agent reads a rent balance off a portal, that number originates outside the API’s logic — real prod can’t predict it either. So you pre-define it. That’s not cheating; it’s the only honest option.
// you set the out-of-control value...
await sandbox.exogenous.pin({ operation: "runTask" }, "output.balance", 1432.18);

// ...but you cannot set status — it's faithful, and the attempt is rejected
await sandbox.exogenous.pin({ operation: "runTask" }, "status", "completed");
// ✗ illegal_override: "status" is faithful data, not yours to set

The line runs between fields, not between endpoints

A single response is assembled per field. One object can carry faithful fields (status, created_at) and an out-of-control one (output) side by side — each resolved from its own source, then frozen together into one object.

Set once, then frozen

An out-of-control value is resolved once, at the moment it’s produced (a run’s output binds when it reaches completed), then frozen into the object and replayed verbatim on every later read. This one rule gives you a powerful guarantee:
The webhook payload, a later GET, and a list view are all views of one frozen value — so they always agree.
That consistency holds by construction, not by reconciliation. (Test it →)

How much you’ll set depends on the API

Owns its state

Stripe, GitHub. Mostly faithful data; you barely touch the out-of-control surface.

Read-only window

Weather, market data. Out-of-control but easy — sensible defaults usually suffice.

Passthrough

Deck. Acts on reality it doesn’t own. Out-of-control-heavy — you set the values that matter.
You don’t have to set all of them: any out-of-control value you leave alone falls back to a deterministic synthesized default (shape-correct and stable across runs), so a suite is green with zero setup and you only set the values a test actually depends on. Continue to Setting values & the resolution trace for how you set out-of-control values — the resolution order (pin → tape → synth) — and how the sandbox tells you which fields are yours to set.