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

# Test mode

> A sandbox key for building and testing your integration, with no model, OCR or enrichment calls.

A **test key** lets you build against the API without spending anything. Jobs made with it run through the real
pipeline with every paid service switched off, are kept apart from your live jobs, and are not metered.

## Get a test key

Create one with `mode: test` (needs `keys:manage`). The key is returned once, as for any key.

```bash theme={null}
curl -sS -X POST "$API/v1/api-keys" -H "X-API-Key: $LIVE_KEY" -H "Content-Type: application/json" \
     -d '{"name": "CI sandbox", "mode": "test"}'
# {"id": "...", "mode": "test", "key": "pk_test_...", "scopes": ["jobs:write", "jobs:read", "underwriting:write"], ...}
```

* Test keys start `pk_test_`, in every environment. A live key starts `pk_live_` in production; elsewhere every
  key starts `pk_test_`, so read `mode` (on the key, from `GET /v1/api-keys`) rather than the prefix.
* A platform that provisions tenants can ask for one: `issue_api_key: true` with `api_key_mode: "test"`.
* Rotating a key keeps its mode.
* A test key holds **job scopes only**: `jobs:write`, `jobs:read`, `jobs:delete` and `underwriting:write`. It
  cannot manage keys, webhooks, mailboxes, integrations or settings, so a leaked one reaches no live job and
  cannot mint a live key.

Use it exactly like a live key: `POST /v1/parse`, `GET /v1/jobs/{job_id}`, corrections, file downloads.

## What is off

A test job is read as a deployment without the paid services would read it, and says so: `test_mode: true` on
the job (`GET /v1/jobs/{job_id}`) and on its `result`.

| Live | Test mode |
| - | - |
| Text-layer statements read by the layout engine | The same, for free: a text statement reconciles and is verified as in live mode |
| Scanned pages read by Mistral OCR and GPT-6 Luna | Not read: the document is `luna_unavailable` and the job is `review_required` |
| Rows categorized by GPT-6 Luna (and transact) | Categorized by the rules alone: `enrichment: rules_only` and the review reason `transactions_not_labelled` |
| MCA positions decided with Luna, unverified deposits investigated with Luna | Positions from the rules alone; no deposit findings |
| Replayed answers and the packet cache | Not used: a test job reads its packet each time and leaves nothing a live job could take |
| Email intake (`POST /v1/intake/email`, mailboxes, `/v1/emails`) | Live only: a test key gets `403` |

So a test result is real but unlabelled: use it to check your integration (upload, webhook, status handling,
mapping the response fields), not to judge categories or positions. A test job costs nothing and its
`usage.cost_usd` is `0`.

## Test and live are separate

Like Stripe's two modes, a key sees only the jobs of its own mode:

* `GET /v1/jobs` lists test jobs for a test key and live jobs for a live key.
* A job of the other mode is `404` on every `/v1/jobs/{job_id}` route (result, files, corrections, erasure). An
  `Idempotency-Key` used in one mode cannot be reused in the other (`409`).
* `DELETE /v1/jobs?end_user_id=` erases the jobs of the key's own mode.
* Test jobs are not metered: they do not appear in `GET /v1/usage`, the quality report, or toward a monthly
  budget, and a spent monthly budget does not stop them.

## Webhooks

Your webhook endpoints belong to the tenant, not to a mode, so they receive test jobs' events too. Check
`payload.livemode`: it is `false` for a test job and `true` for a live one.

```json theme={null}
{"topic": "job.review_required", "payload": {"job_id": "...", "status": "review_required", "livemode": false, ...}}
```

A test job's event is **not** sent to your CRM integrations, so test data never reaches your real CRM.

## Limits still apply

A test key is rate limited like any key, and `max_active_jobs` caps the queued and running test jobs (counted
apart from your live jobs, so a test run never holds up production).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.