# Create a Playground Run

```http
POST /api/public/v1/competitions/mathematics-distillation-challenge-equational-theories-stage1/playground/runs
Content-Type: application/json
```

**Scope**: `playground.write`.

Creates a billable, asynchronous Stage 1 practice Run. This operation does not create a formal competition submission or affect the leaderboard. Competition enrollment is not required for practice Runs.

A cell is one model × problem × configuration combination. Every cell executes `repeat` times and produces one result row per execution:

```text
executionCount = models.length × problems.length × configurations.length × repeat
```

The service resolves and snapshots the selected problems and cheatsheet content during creation. Later edits, deletion, or catalog changes do not alter an already-created Run.

## Idempotency

`idempotencyKey` is required because an uncertain network retry must not create a second billable Run or reserve credits twice.

- Generate one key for one logical Run creation and reuse it only when retrying the exact same request.
- The trimmed key must be non-empty and at most 200 UTF-8 bytes.
- The first successful creation returns `201 Created`.
- Replaying the same key with the same normalized request returns the recorded creation response with `200 OK` and does not reserve credits or enqueue work again.
- Reusing the key with a different request returns `409 IDEMPOTENCY_CONFLICT`.

Keys are isolated by calling account and competition.

## Request fields

| Field | Type | Required | Description |
| :--- | :--- | :---: | :--- |
| `idempotencyKey` | string | Yes | Retry key for this logical Run creation. |
| `models` | string[] | Yes | Non-empty, unique IDs from [List Playground models](./list-playground-models.md). |
| `problems` | [RunProblem](#problem-shapes)[] | Yes | Non-empty, unique problem-set references or inline custom problems. |
| `configurations` | [RunConfiguration](#configuration-fields)[] | Yes | Non-empty, unique cheatsheet configurations to compare. |
| `repeat` | integer | No | Executions per cell. Default `1`; minimum `1`; maximum `5`. |

Unknown top-level or nested fields are rejected. An empty `configurations` array is invalid: Stage 1 execution requires cheatsheet content, and this API does not define an unconditioned baseline.

The endpoint also enforces the live frequency, problem-count, credit, cost, and cooldown limits returned by [Get Playground usage](./get-playground-usage.md).

### Problem shapes

Each problem must have exactly one of these shapes:

| Shape | Use |
| :--- | :--- |
| `{ "problemSet": string, "index": integer }` | Select the zero-based index returned by [Get a Playground problem set](./get-playground-problem-set.md). |
| `{ "custom": { "equation1": string, "equation2": string, "goldAnswer": boolean } }` | Run one inline practice problem. Both equations must contain non-whitespace text. `goldAnswer` is used for scoring and is not sent to the model. |

### Configuration fields

| Field | Type | Required | Description |
| :--- | :--- | :---: | :--- |
| `cheatsheet` | string | Yes | An owned cheatsheet ID from the [private Stage 1 library](./cheatsheets.md). Its content is snapshotted during creation. |

A published cheatsheet remains usable by its owner even though it is read-only until withdrawal.

## Example request

Generate a new idempotency key for this logical Run—for example, `stage1-run-$(openssl rand -hex 16)` in a shell—and keep the resulting value unchanged if the request must be retried. The body below shows one generated value:

```json
{
  "idempotencyKey": "stage1-run-7d3fc0f0d9c948b7a0d51ced9df77529",
  "models": ["qwen3"],
  "problems": [
    {
      "problemSet": "pset_hard3",
      "index": 0
    },
    {
      "custom": {
        "equation1": "x + y = y + x",
        "equation2": "y + x = x + y",
        "goldAnswer": true
      }
    }
  ],
  "configurations": [
    {
      "cheatsheet": "cs_01JSTAGE100000000000000001"
    }
  ],
  "repeat": 1
}
```

This request creates two executions: one model × two problems × one configuration × one repetition.

## Response

Creation validates the selected resources and current limits. A rejected request leaves no credit reservation.

A new Run returns `201 Created`:

```json
{
  "ok": true,
  "data": {
    "runId": "run_01JSTAGE100000000000000001",
    "status": "pending",
    "executionCount": 2,
    "creditsHeld": 1.4
  }
}
```

`creditsHeld` is the temporary maximum reserved for the Run. After the Run reaches a terminal state, unused credits are returned and the settled grouped charge is available from [Get a Playground Run](./get-playground-run.md).

Use [Get a Playground Run](./get-playground-run.md) to poll status or [List Playground Runs](./list-playground-runs.md) to discover the Run later.

## Errors

See [Errors](../../../errors.md). Endpoint-specific errors are:

| HTTP | Code | When |
| :---: | :--- | :--- |
| `400` | `MALFORMED_BODY` | The JSON or top-level request shape is invalid. |
| `403` | `RUN_BUDGET_EXCEEDED` | The required credit hold exceeds the available balance. |
| `404` | `NOT_FOUND` | The Stage 1 competition is unavailable. |
| `409` | `IDEMPOTENCY_CONFLICT` | The idempotency key was already used with a different request. |
| `422` | `RUN_PARAMS_INVALID` | A model, problem, configuration, repeat value, nested shape, or referenced resource is invalid. |
| `429` | `PLAYGROUND_RUN_LIMIT_EXCEEDED` | A live per-account Run frequency, cost, credit, or cooldown limit was reached. |
