# Get Playground usage

```http
GET /api/public/v1/competitions/mathematics-distillation-challenge-equational-theories-stage2/playground/usage
```

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

Returns the account and platform snapshot needed to preflight a new Stage 2 practice Run: the current UTC-day credit allowance, outstanding reservations, live quotas, per-Run constraints, general availability, and historical activity.

This response is advisory. [Create a Playground Run](./create-playground-run.md) checks enrollment, the selected resources, required credits, and live limits when accepting the Run. A successful preflight does not reserve credits or capacity.

All periods and timestamps use UTC. Credits and quotas are account-wide across the Stage 2 browser Playground and public API; switching clients or API keys does not create another allowance. This endpoint remains readable when the Playground is read-only or the competition is closed so clients can inspect usage and the corresponding availability blocker.

## Credit policy

Stage 2 uses a daily credit allowance. Every Run is assigned to the UTC-day period in which it is created. Active Runs reserve credits from that period; after terminal settlement, the reservation is replaced by the settled charge. Cancellation before evaluator claim releases the complete reservation.

| Field | Type | Description |
| :--- | :--- | :--- |
| `credits.policy` | string | Always `daily_quota`. |
| `credits.currency` | string | Always `credit`. |
| `credits.rate` | number | Positive US-dollar value represented by one credit. |
| `credits.creditsPerProblem` | number | Credit reservation for each problem included in a new Run. |
| `credits.dailyAllowance` | number | Account allowance for the current UTC-day period. |
| `credits.available` | number | Credits currently available for new reservations in this period. |
| `credits.reserved` | number | Credits held by active Runs created in this period. |
| `credits.consumed` | number | Settled charges for terminal Runs created in this period. |
| `credits.accounted` | number | `reserved + consumed` for this period. |
| `credits.periodStartedAt` | string | Inclusive start of the current UTC-day period. |
| `credits.resetsAt` | string | Start of the next UTC-day period. |

The values reconcile as follows:

```text
credits.accounted = credits.reserved + credits.consumed
credits.available = max(credits.dailyAllowance - credits.accounted, 0)
```

The reset starts a new allowance period; it does not add credits to a wallet. Historical Runs retain their original period assignment, and a Run crossing midnight does not move its reservation or charge into the new period.

`credits.rate` is a conversion rate, not the price of one problem. The initial reservation for a request is:

```text
creditsHeld = problemIds.length × credits.creditsPerProblem
```

## Quotas

`quotas` contains independent account limits that affect Run creation:

| Field | Unit and window |
| :--- | :--- |
| `runsPerUtcDay` | Successful user-created Runs in the current UTC-day period. |
| `costUsdPerUtcDay` | USD cost committed by Runs created in the current UTC-day period. |

Every quota is a `QuotaSnapshot`:

| Field | Type | Description |
| :--- | :--- | :--- |
| `limit` | number \| null | Configured limit; `null` means the quota is disabled. |
| `used` | number | Current usage even when the limit is disabled. |
| `remaining` | number \| null | `max(limit - used, 0)`, or `null` when disabled. |
| `resetAt` | string \| null | Time when the current quota period ends, or `null` when disabled. |

A successful Run creation counts against `runsPerUtcDay` even if the Run is later cancelled or fails. An exact idempotent replay does not count again.

The cost quota counts the USD equivalent of outstanding reservations for active Runs and the recorded cost of terminal Runs. Replacing a reservation with a smaller terminal charge releases the difference, so concurrent active Runs cannot bypass the quota.

## Per-Run constraints

| Field | Type | Description |
| :--- | :--- | :--- |
| `constraints.maxProblemsPerRun` | integer \| null | Maximum unique problems in one Run, or `null` when no additional business limit is configured. |
| `constraints.maxSolverBytes` | integer | Maximum UTF-8 byte length of `solverCode`. It uses the same live source as `submissionSpec.limits.maxBytes` in [Get Competition Detail](./get-competition-detail.md). |

Track-specific request rules, including Marathon configuration, remain documented by [Create a Playground Run](./create-playground-run.md).

## Availability

`availability.canCreateRun` is `false` when an account-wide or platform-wide condition currently blocks every new Run. A value of `true` does not guarantee that a particular problem selection fits the remaining credits or per-Run constraints.

`availability.blockers` contains zero or more objects with a stable `code` and nullable `retryAt`. `retryAt` is `null` when the service cannot predict when the condition will clear.

| Blocker code | Meaning |
| :--- | :--- |
| `ACCOUNT_DISABLED` | The account cannot create practice Runs. |
| `NOT_ENROLLED` | The account has not completed Stage 2 enrollment. |
| `PLAYGROUND_READ_ONLY` | New Runs are disabled, while existing usage and Runs remain readable. |
| `NO_MODELS_AVAILABLE` | No executable Stage 2 model is currently available. |
| `CREDIT_ALLOWANCE_EXHAUSTED` | The remaining credit allowance cannot fund the smallest valid Run. |
| `RUN_QUOTA_EXCEEDED` | The account exhausted its current Run-creation quota. |
| `COST_QUOTA_EXCEEDED` | The account exhausted its current USD-cost quota. |
| `PLATFORM_CAPACITY_EXCEEDED` | Platform-wide cost, Run, queue, or evaluator capacity currently blocks admission. |

## Activity

| Field | Type | Description |
| :--- | :--- | :--- |
| `activity.runsCreated.total` | integer | All user-created Stage 2 practice Runs across browser and public API clients. |
| `activity.runsCreated.last30Days` | integer | Runs created since `activity.last30DaysStartedAt`. |
| `activity.problemsIncluded.total` | integer | Problems snapshotted into those Runs, including Runs that later failed or were cancelled. |
| `activity.problemsIncluded.last30Days` | integer | Problems snapshotted into Runs created since `activity.last30DaysStartedAt`. |
| `activity.last30DaysStartedAt` | string | Inclusive start of the rolling 30-day activity window. |
| `updatedAt` | string | ISO 8601 UTC time of this snapshot. |

Platform-managed benchmark Runs are excluded. Removing a Run from history does not restore spent credits or Run quota.

## Example request

```bash
curl "https://api.sair.foundation/api/public/v1/competitions/mathematics-distillation-challenge-equational-theories-stage2/playground/usage" \
  -H "Authorization: Bearer $SAIR_API_KEY"
```

## Example response

The values below illustrate the response shape. Use the live response for admission decisions.

```json
{
  "ok": true,
  "data": {
    "credits": {
      "policy": "daily_quota",
      "currency": "credit",
      "rate": 0.001,
      "creditsPerProblem": 0.1,
      "dailyAllowance": 50,
      "available": 42,
      "reserved": 0.4,
      "consumed": 7.6,
      "accounted": 8,
      "periodStartedAt": "2026-08-31T00:00:00Z",
      "resetsAt": "2026-09-01T00:00:00Z"
    },
    "quotas": {
      "runsPerUtcDay": {
        "limit": 50,
        "used": 11,
        "remaining": 39,
        "resetAt": "2026-09-01T00:00:00Z"
      },
      "costUsdPerUtcDay": {
        "limit": 2,
        "used": 0.027,
        "remaining": 1.973,
        "resetAt": "2026-09-01T00:00:00Z"
      }
    },
    "constraints": {
      "maxProblemsPerRun": 100,
      "maxSolverBytes": 500000
    },
    "availability": {
      "canCreateRun": true,
      "blockers": []
    },
    "activity": {
      "runsCreated": {
        "total": 37,
        "last30Days": 12
      },
      "problemsIncluded": {
        "total": 420,
        "last30Days": 138
      },
      "last30DaysStartedAt": "2026-08-01T02:14:00Z"
    },
    "updatedAt": "2026-08-31T02:14:00Z"
  }
}
```

## Errors

See [Errors](../../../errors.md). An unavailable competition returns `404 NOT_FOUND`.
