# List Playground run results

```http
GET /api/public/v1/competitions/mathematics-distillation-challenge-equational-theories-stage1/playground/runs/{runId}/results
```

**Scope**: `playground.read`.

Returns completed execution rows for a Run owned by the calling account. One row represents one model × problem × configuration × repetition execution; rows are never aggregates.

Results may be read while the Run is active. Each stored row is immutable, and rows are ordered by the execution plan's stable `executionIndex`.

## Path parameters

| Parameter | Type | Required | Description |
| :--- | :--- | :---: | :--- |
| `runId` | string | Yes | Run ID returned by create, list, or detail. |

## Query parameters

| Parameter | Type | Required | Default | Description |
| :--- | :--- | :---: | :--- | :--- |
| `cursor` | string | No | — | Opaque cursor returned by the preceding response. |
| `limit` | integer | No | `25` | Page size from `1` through `100`. |
| `includeOutput` | boolean | No | `false` | Include each row's raw `output`. Use only when the response text is needed. |

Filters are not supported. Use the stable positions and IDs in each row to group results client-side.

## Result outcomes

| Outcome | Meaning |
| :--- | :--- |
| `scored` | A model answer was parsed and compared with the expected answer. |
| `unscored` | A model response exists, but it could not be parsed or scored. |
| `failed` | The execution ended without a usable model response. |

## Result fields

| Field | Type | Description |
| :--- | :--- | :--- |
| `resultId` | string | Stable result row ID. |
| `executionIndex` | integer | Zero-based position in the Run's complete execution plan. |
| `modelId` | string | Evaluated model ID. |
| `problem.position` | integer | Position of the problem snapshot in `params.problems`. |
| `problem.source.type` | string | `problem-set` or `custom`. |
| `problem.source.problemSetId` | string | Present for a `problem-set` source. |
| `problem.source.index` | integer | Original problem-set index; present for a `problem-set` source. |
| `configuration.position` | integer | Position of the configuration snapshot in `params.configurations`. |
| `configuration.cheatsheetId` | string | Snapshotted cheatsheet ID. |
| `repeatIndex` | integer | Zero-based repetition index within the execution cell. |
| `outcome` | string | `scored`, `unscored`, or `failed`. |
| `expectedAnswer` | boolean | Snapshotted practice answer. It is not sent to the model. |
| `parsedAnswer` | boolean \| null | Answer parsed from the model output, or `null` when parsing failed or no output exists. |
| `correct` | boolean \| null | Whether `parsedAnswer` equals `expectedAnswer`; `null` when unscored. |
| `diagnostic` | object \| null | Stable `code` and human-readable `message` for an unscored or failed execution. |
| `usage.inputTokens` | integer \| null | Provider-reported input tokens. |
| `usage.outputTokens` | integer \| null | Provider-reported output tokens. |
| `usage.costUsd` | number \| null | Actual model cost before conversion to credits. |
| `elapsedMs` | integer \| null | Execution duration in milliseconds. |
| `completedAt` | string | ISO 8601 UTC time when the row became terminal. |
| `output` | string \| null | Present only when `includeOutput=true`; raw model output, or `null` when none was produced. |

Problem and configuration positions refer to the immutable snapshots returned by [Get a Playground Run](./get-playground-run.md). Multiple custom problems therefore remain distinct instead of sharing a synthetic index.

## Response fields

| Field | Type | Description |
| :--- | :--- | :--- |
| `runId` | string | Run whose results were requested. |
| `runStatus` | string | Current Run lifecycle status. |
| `progress.completedExecutions` | integer | Executions that have finished. |
| `progress.totalExecutions` | integer | Total rows expected for the Run. |
| `items` | `Stage1Result[]` | Result rows ordered by `executionIndex`, then `resultId`. |
| `nextCursor` | string \| null | Cursor for the next page of rows already stored, or `null` when caught up. |
| `pollCursor` | string \| null | Resume cursor returned only when the response is caught up but the Run is still active. |

Follow `nextCursor` until it becomes `null`. If `pollCursor` is non-null, the Run is still active; poll with that cursor to receive later rows without restarting pagination. When both cursors are `null`, every stored row from the terminal Run has been returned. Polling consumes the normal read quota, so clients should back off between empty responses.

## Example request

```bash
curl "https://api.sair.foundation/api/public/v1/competitions/mathematics-distillation-challenge-equational-theories-stage1/playground/runs/run_01JSTAGE100000000000000001/results?limit=25&includeOutput=true" \
  -H "Authorization: Bearer $SAIR_API_KEY"
```

## Example response

```json
{
  "ok": true,
  "data": {
    "runId": "run_01JSTAGE100000000000000001",
    "runStatus": "done",
    "progress": {
      "completedExecutions": 1,
      "totalExecutions": 1
    },
    "items": [
      {
        "resultId": "result_01JSTAGE100000000000000001",
        "executionIndex": 0,
        "modelId": "qwen3",
        "problem": {
          "position": 0,
          "source": {
            "type": "problem-set",
            "problemSetId": "pset_hard3",
            "index": 0
          }
        },
        "configuration": {
          "position": 0,
          "cheatsheetId": "cs_01JSTAGE100000000000000001"
        },
        "repeatIndex": 0,
        "outcome": "scored",
        "expectedAnswer": true,
        "parsedAnswer": true,
        "correct": true,
        "diagnostic": null,
        "usage": {
          "inputTokens": 412,
          "outputTokens": 86,
          "costUsd": 0.0032
        },
        "elapsedMs": 1240,
        "completedAt": "2026-08-30T08:21:32Z",
        "output": "VERDICT: TRUE"
      }
    ],
    "nextCursor": null,
    "pollCursor": null
  }
}
```

## Errors

See [Pagination](../../../pagination.md) for invalid cursors and [Errors](../../../errors.md) for shared errors. A missing, cross-account, or cross-competition Run returns `404 NOT_FOUND`.
