> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prodbreak.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Values you control

> What's faithful and unfakeable vs what you set yourself — the line that decides what you can control.

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

| Kind                                                                                                                              | Can you set it?                                                | Examples                                                          |
| --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ----------------------------------------------------------------- |
| **Faithful data** — ids, `status`, amounts, timestamps, counters, anything the API derives from your inputs and its own lifecycle | **No** — faking it would break fidelity, and you never need to | `id`, `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 either     | **Yes** — this is the legitimate surface you control           | a 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.

```ts theme={null}
// 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 →](/guides/test-a-webhook))

## How much you'll set depends on the API

<CardGroup cols={3}>
  <Card title="Owns its state" icon="vault">
    Stripe, GitHub. Mostly faithful data; you barely touch the out-of-control surface.
  </Card>

  <Card title="Read-only window" icon="window">
    Weather, market data. Out-of-control but easy — sensible defaults usually suffice.
  </Card>

  <Card title="Passthrough" icon="shuffle">
    **Deck.** Acts on reality it doesn't own. Out-of-control-heavy — you set the values that matter.
  </Card>
</CardGroup>

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](/concepts/pins-and-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.
