# Get Playground usage

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

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

Returns the account and platform snapshot needed to preflight a new Stage 1 practice Run: spendable credits, 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 the selected models, resources, required credits, and live limits when accepting the Run.

All periods and timestamps use UTC. A quota `limit` of `null` means that quota is disabled. Credits and quotas are account-wide across the Stage 1 browser Playground and public API; switching clients does not create a second allowance.

## Credit fields

| Field | Type | Description |
| :--- | :--- | :--- |
| `credits.available` | number | Credits currently spendable after outstanding reservations. |
| `credits.reserved` | number | Credits held by active Runs and not yet settled. |
| `credits.chargedToday` | number | Credits settled during the current UTC day. |
| `credits.currency` | string | Always `credit`. |
| `credits.rate` | number | Positive USD-per-credit conversion rate used for new Runs. |
| `credits.dailyMinimumBalance` | number \| null | Daily minimum spendable balance, or `null` when automatic refresh is disabled. |
| `credits.nextDailyRefreshAt` | string \| null | Next UTC refresh time, or `null` when automatic refresh is disabled. |

At the daily refresh, the service raises `credits.available` to at least `dailyMinimumBalance`. It does not add that amount on top of a higher balance and does not reduce a higher balance.

## Quota fields

`quotas` contains these independent windows:

| Field | Unit and window |
| :--- | :--- |
| `runsPerRollingHour` | Successful Run creations in the trailing 60 minutes. |
| `runsPerUtcDay` | Successful Run creations in the current UTC day. |
| `creditsPerRollingHour` | Credits committed by Runs created in the trailing 60 minutes. |
| `creditsPerUtcDay` | Credits committed by Runs created in the current UTC day. |
| `costUsdPerUtcDay` | USD cost committed by Runs created in the current UTC day. |

Every quota window is a `QuotaSnapshot`:

| Field | Type | Description |
| :--- | :--- | :--- |
| `limit` | number \| null | Configured limit; `null` means 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 | Next time usage leaves the window; `null` when no reset is pending. |

A successful Run creation counts against the Run quotas even if the Run is later cancelled or hidden. Credit and USD windows count outstanding reservations for active Runs and settled charges for terminal Runs, so concurrent pending Runs cannot bypass a limit. Released reservations no longer count against credit or cost quotas.

## Per-Run constraints

| Field | Type | Description |
| :--- | :--- | :--- |
| `constraints.maxModelsPerRun` | integer | Maximum unique models in one Run. |
| `constraints.maxProblemsPerRun` | integer | Maximum unique problems in one Run. |
| `constraints.maxConfigurationsPerRun` | integer | Maximum unique cheatsheet configurations in one Run. |
| `constraints.maxRepeat` | integer | Maximum repetitions per execution cell. |
| `constraints.maxExecutionsPerRun` | integer | Maximum value of the complete execution-count formula. |
| `constraints.maxCheatsheetBytes` | integer | Maximum UTF-8 bytes in every referenced cheatsheet snapshot. |
| `constraints.cooldownSeconds` | integer | Minimum delay between successful Run creations. |

The request must satisfy every individual constraint and the total execution limit.

## Availability fields

`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 request has sufficient credits or valid resources.

`availability.blockers` contains zero or more objects with a stable `code` and `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. |
| `CREDIT_BALANCE_EMPTY` | No spendable credit remains. |
| `RUN_COOLDOWN_ACTIVE` | The account must wait before another Run creation. |
| `RUN_QUOTA_EXCEEDED` | An hourly or daily Run quota is exhausted. |
| `CREDIT_QUOTA_EXCEEDED` | An hourly or daily credit quota is exhausted. |
| `COST_QUOTA_EXCEEDED` | The daily USD-cost quota is exhausted. |
| `PLATFORM_CAPACITY_EXCEEDED` | The platform is temporarily refusing new Runs. |

## Activity fields

| Field | Type | Description |
| :--- | :--- | :--- |
| `activity.runsCreated.total` | integer | All user-created Stage 1 practice Runs across browser and public API clients. |
| `activity.runsCreated.last30Days` | integer | Runs created since `activity.last30DaysStartedAt`. |
| `activity.executionsCompleted.total` | integer | Stored terminal execution rows; not planned cells. |
| `activity.executionsCompleted.last30Days` | integer | Execution rows completed since `activity.last30DaysStartedAt`. |
| `activity.last30DaysStartedAt` | string | Inclusive UTC start of the rolling 30-day activity window. |
| `updatedAt` | string | ISO 8601 UTC time of this snapshot. |

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

## Example request

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

## Example response

```json
{
  "ok": true,
  "data": {
    "credits": {
      "available": 124.5,
      "reserved": 2.1,
      "chargedToday": 12.4,
      "currency": "credit",
      "rate": 0.01,
      "dailyMinimumBalance": 50,
      "nextDailyRefreshAt": "2026-09-01T00:00:00Z"
    },
    "quotas": {
      "runsPerRollingHour": {
        "limit": 10,
        "used": 3,
        "remaining": 7,
        "resetAt": "2026-08-31T02:31:00Z"
      },
      "runsPerUtcDay": {
        "limit": 50,
        "used": 11,
        "remaining": 39,
        "resetAt": "2026-09-01T00:00:00Z"
      },
      "creditsPerRollingHour": {
        "limit": null,
        "used": 4.6,
        "remaining": null,
        "resetAt": null
      },
      "creditsPerUtcDay": {
        "limit": 500,
        "used": 15.3,
        "remaining": 484.7,
        "resetAt": "2026-09-01T00:00:00Z"
      },
      "costUsdPerUtcDay": {
        "limit": 2,
        "used": 0.153,
        "remaining": 1.847,
        "resetAt": "2026-09-01T00:00:00Z"
      }
    },
    "constraints": {
      "maxModelsPerRun": 10,
      "maxProblemsPerRun": 10,
      "maxConfigurationsPerRun": 5,
      "maxRepeat": 5,
      "maxExecutionsPerRun": 500,
      "maxCheatsheetBytes": 10240,
      "cooldownSeconds": 10
    },
    "availability": {
      "canCreateRun": true,
      "blockers": []
    },
    "activity": {
      "runsCreated": {
        "total": 187,
        "last30Days": 41
      },
      "executionsCompleted": {
        "total": 73200,
        "last30Days": 15800
      },
      "last30DaysStartedAt": "2026-08-01T02:14:00Z"
    },
    "updatedAt": "2026-08-31T02:14:00Z"
  }
}
```

## Errors

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