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

# Test mode

> A deterministic sandbox for sk_test_ keys: realistic sample data, simulated writes, and reproducible errors.

A `sk_test_` key is served entirely from a small fixed dataset. Reads return realistic
sample data; writes report success and change nothing. It's the **same code path** as
live — same validation, same response shapes, same rate limits — with a different data
source.

<Note>
  Nothing in test mode touches your real data. You cannot see, create, modify or delete a
  real assessment, candidate or submission with a test key. Build freely.
</Note>

## The sandbox is stateless

This is the one thing that surprises people:

<Warning>
  Writes are **simulated**. A `POST` returns a realistic created object with a fixed id,
  but nothing persists — a `GET` afterwards returns the unchanged sample data. Don't write
  a test that creates something and then expects to read it back.
</Warning>

The upside is that responses are byte-stable. The same request always returns the same
bytes (apart from `request_id`), so you can snapshot-test your integration against us.

## Sample data

The sandbox is one small, internally consistent organization: three challenges, two
assessments, four invitations across different statuses, and three submissions — one fully
evaluated with a complete report, one in progress, one submitted but not yet graded.

These ids resolve in test mode and are safe to hard-code:

| Resource                                     | Id                                     |
| -------------------------------------------- | -------------------------------------- |
| Challenge (single-task)                      | `00000000-0000-4000-8000-000000000001` |
| Challenge (multi-task, has tasks)            | `00000000-0000-4000-8000-000000000002` |
| Challenge (private to the org)               | `00000000-0000-4000-8000-000000000003` |
| Assessment (active, has cohort stats)        | `00000000-0000-4000-8000-000000000011` |
| Assessment (closed, multi-task)              | `00000000-0000-4000-8000-000000000012` |
| Invitation (sent — resend/revoke work)       | `00000000-0000-4000-8000-000000000021` |
| Invitation (evaluated — revoke answers 400)  | `00000000-0000-4000-8000-000000000024` |
| Submission (evaluated, full report + events) | `00000000-0000-4000-8000-000000000031` |
| Submission (in progress)                     | `00000000-0000-4000-8000-000000000032` |
| Submission (submitted, not yet graded)       | `00000000-0000-4000-8000-000000000033` |

## Reproducing errors

Most failures happen naturally: send an invalid body for a `400`, use a read-only key on a
write for a `403`, hammer an endpoint for a `429`, or revoke the already-evaluated
invitation above for a `400`.

Two cases can't be triggered that way, so the sandbox recognises these values:

| Send this                              | Where                           | You get                      |
| -------------------------------------- | ------------------------------- | ---------------------------- |
| `00000000-0000-4000-8000-0000000000ff` | Any `{id}` path segment         | **404 NOT\_FOUND**           |
| `limit@example.com`                    | `candidate_email` when inviting | **402 PLAN\_LIMIT\_REACHED** |

## What test mode does not do

<AccordionGroup>
  <Accordion title="It doesn't send email" icon="envelope">
    Creating an invitation returns a realistic `invitation_url`, but no email is sent and
    the token is not redeemable. To exercise the candidate side, use a live key on a real
    assessment.
  </Accordion>

  <Accordion title="It doesn't run grading" icon="gears">
    Reports come from fixed sample data rather than a real evaluation. The evaluated
    submission always returns the same report.
  </Accordion>

  <Accordion title="Workspace downloads are always null" icon="file-zipper">
    `workspace_archive_url` is `null` for every sandbox submission — there's no real
    archive to sign. Treat `null` as "not available", which is also what live returns
    before a candidate submits.
  </Accordion>

  <Accordion title="Rate limits are real" icon="gauge-high">
    Test keys draw on the same hourly quotas as live keys, deliberately, so you can see
    and handle a real `429` with its `Retry-After` header before you go to production.
  </Accordion>
</AccordionGroup>

## Using the playground

The interactive playground in the [API reference](/api-reference) sends real requests.
**Use a test key there.** Requests are proxied server-side rather than sent from your
browser, so a key pasted into the playground travels through Mintlify's infrastructure —
fine for a sandbox credential, not something to do with a live key.
