---
title: Sandbox vs live
description: What test mode does, what live mode requires, and exactly which requests are refused until your account is approved for production.
canonical_url: "https://cascades.crscreditapi.com/docs/concepts/sandbox-vs-live"
doc_version: "1.0.0"
last_updated: "2026-10-09T18:04:24Z"
source: docs/concepts/sandbox-vs-live.md
---

# Sandbox vs live

Every run has an `execution_mode`: `test` or `live`. The mode is chosen per request, not per key, so the same integration moves from sandbox to production by changing one field.

## What does test mode do?

- **Synthetic data.** Nothing calls a billable bureau or vendor and nothing is billed. For most applicants every product node returns its schema mock: `happy_path` (clean file, no records) by default.
- **Pick the outcome with `scenario`.** Add `"scenario": "fail_path"` to `payload` to make every product node return its decline mock (for example the eviction node reports two filings and `recommendation: FAIL`), so `fail_steps` and adverse-action branches run. A node's `mock_scenario` config overrides it.
- **Registered test subjects replay.** When a trigger's applicant is a [registered test subject](/docs/sandbox/test-identities) and that subject is registered for every product node in the cascade, the run replays the subject's authored bureau responses instead of the mocks, still at no charge. The execution's `input_context.sandbox_replay` is `true`, and `scenario` has no effect on that run. Any other applicant, and every batch row, gets the mocks.
- **Drafts run.** A cascade with `active: false` accepts a single `execution_mode: test` trigger, so you can exercise it before activating. Batches and re-evaluations still need an active cascade (`409 workflow_inactive`), so a sandbox account cannot run batches. See [Batches](/docs/concepts/batches).
- **Human review resumes inline.** `POST /executions/{id}/review_decisions` on a test-mode execution runs the chosen branch synchronously and answers `200` with the final state; live-mode decisions enqueue the resume and answer `202`.
- **Webhooks still fire.** `execution.*` and `adverse_action.*` events are delivered for test runs too, so you can build your handler end to end. `execution.*` payloads carry `"execution_mode": "test"`; `adverse_action.*` payloads do not carry it — join on `workflow_execution_id` and read `input_context.execution_mode` from `GET /executions/{id}`.

## What does live mode require?

Two things, checked on every live request:

1. **An approved account.** Approval is granted by CRS after the activation form at [/activate](/activate) is reviewed. Until then every `execution_mode: live` request is refused with `403 live_mode_forbidden`.
2. **An active cascade.** Live triggers on a draft return `409 workflow_inactive`.

Live runs pull real consumer reports and are billable. On the CRS **sandbox** host, a live-mode run from an approved account with a normal key (not a docs key) also matches the registered test subjects: when the applicant matches a registry entry, the authored bureau response is replayed instead of a vendor pull, and a miss reaches the billable vendor — see [Test identities](/docs/sandbox/test-identities). You need a permissible purpose under the FCRA for every live pull — see [FCRA permissible purpose](/docs/compliance/fcra-permissible-purpose).

## Which requests are gated?

| Request | Sandbox account (not approved) |
|---|---|
| `POST /workflows/{id}/trigger` with `execution_mode: live` | `403 live_mode_forbidden` |
| `POST /workflows/{id}/batches`, test or live | `409 workflow_inactive`: the account's cascades are drafts, and a draft runs no batch |
| `POST /batches/{id}/resume`, `retry_failed` on a live batch | `403 live_mode_forbidden` |
| `POST /executions/{id}/re_evaluations` of a live execution | `403 live_mode_forbidden` |
| `POST /executions/{id}/review_decisions` on a live execution | `403 live_mode_forbidden` |
| `POST /workflows` with `active: true` | Created as a **draft**; the response carries a `note` explaining why |
| `PATCH /workflows/{id}` with `active: true` | `403 activation_forbidden` |

Everything else (reading, single test-mode triggers, webhooks, templates, deleting) works the same in both modes.

## How do I tell which mode a run used?

- The `trigger` and `batch` responses echo `execution_mode`.
- `GET /executions/{id}` includes it in `input_context.execution_mode`.
- Webhook payloads for `execution.*` events carry `execution_mode`; `adverse_action.*` payloads do not, so resolve the execution first.

Filter your own records on it before acting on a decision: a test-mode approval is a synthetic approval.

## Keys minted from the docs

When you are signed in, the key injected into these pages is a short-lived, **sandbox-only** token: it expires after an hour or when you sign out, and is refused for any live request even on an approved account. On an approved account the refusal says so: live requests answer `403 live_mode_forbidden` with "Docs keys are sandbox-only, so they never run live", activation answers `403 activation_forbidden`, and `POST /workflows` creates a draft with a note that names the docs key. Mint a real key at [/api-keys](/api-keys) for your integration, or activate the cascade in the app.

## Going live checklist

- [ ] Account approved (the sandbox banner in the app disappears)
- [ ] Cascade active (`active: true`), tested end to end in test mode
- [ ] Integration key holds only the scopes you need
- [ ] `Idempotency-Key` derived from a stable business id
- [ ] Webhook signature verification rejects stale `t` and wrong `v1`
- [ ] Your side records `execution_mode` from the trigger response or `GET /executions/{id}` and never treats a test decision as real

## Sitemap

See the full [sitemap](https://cascades.crscreditapi.com/sitemap.md) for all pages.
