# Get competition detail

```http
GET /api/public/v1/competitions/igp24
```

**Scope**: `competition.read`.

Returns IGP24 metadata, the polynomial payload contract, the frozen official submission window, and the caller's current post-event validation status. Read this endpoint before verifying or persisting a batch so the client does not hard-code capabilities, limits, team policy, or quota state.

Most fields describe competition-wide configuration. `submissionSpec.submissionStatus` is caller-specific and time-sensitive; do not cache it across API keys or use a previous response as proof that a later submission will be admitted.

## Example request

```bash
curl "https://api.sair.foundation/api/public/v1/competitions/igp24" \
  -H "Authorization: Bearer $SAIR_API_KEY"
```

## Example response

The text, publication state, timestamps, usage, and limits below illustrate the response shape. Use the values returned by the live endpoint.

```json
{
  "ok": true,
  "data": {
    "id": "igp24",
    "title": "Inverse Galois Problem (IGP24)",
    "description": "Submit degree 24 polynomial candidates.",
    "capabilities": {
      "playground": false,
      "contributorNetwork": false,
      "leaderboard": true
    },
    "leaderboardPublished": true,
    "leaderboardTeamDetailsEnabled": true,
    "submissionSpec": {
      "kind": "igp24-polynomial",
      "schema": {
        "type": "object",
        "required": ["polynomials"],
        "properties": {
          "polynomials": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1000,
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      },
      "metaSchema": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 500
          }
        },
        "additionalProperties": false
      },
      "permission": {
        "teamRole": "deadlineTeamMember"
      },
      "window": {
        "opensAt": "2026-06-15T10:00:00Z",
        "closesAt": "2026-08-16T12:00:00Z"
      },
      "limits": {
        "maxBytes": 1000000,
        "maxPolynomials": 1000,
        "maxRequestBytes": 1310720
      },
      "submissionStatus": {
        "currentMode": "discovery_only",
        "maySubmit": true,
        "denialReason": null,
        "dailyBatchLimit": 10,
        "usedBatchesToday": 3,
        "remainingBatchesToday": 7,
        "perBatchPolynomialLimit": 1000,
        "nextUtcResetAt": "2026-08-18T00:00:00Z",
        "discoveryOnlyEndsAt": null,
        "sourcePhase": "discovery_only",
        "officialScoringEligible": false,
        "teamId": "teamv2_a7a863ce80e6447881ad068bab82498e"
      }
    }
  }
}
```

## Response fields

| Field | Type | Description |
| :--- | :--- | :--- |
| `id` | `"igp24"` | Stable competition ID used in IGP24 routes. |
| `title` | string | Display title. |
| `description` | string \| null | Competition description, when configured. |
| `capabilities.playground` | boolean | Whether the competition exposes a separate persistent Playground lifecycle. IGP24 returns `false`; use [Verify a polynomial batch](./verify-polynomials.md) for a non-persistent check. |
| `capabilities.contributorNetwork` | boolean | Whether the competition supports Contributor Network items. IGP24 returns `false`. |
| `capabilities.leaderboard` | boolean | Whether official leaderboard results are currently published. |
| `leaderboardPublished` | boolean | Explicit official leaderboard publication state. It currently matches `capabilities.leaderboard`. |
| `leaderboardTeamDetailsEnabled` | boolean | Whether a published leaderboard may include the [`teamDetails` projection](../../competitions.md#leaderboard-team-details-and-privacy). |
| `submissionSpec` | object | Live structural contract and caller-specific status for IGP24 validation batches. |

### Submission specification

| Field | Type | Description |
| :--- | :--- | :--- |
| `kind` | `"igp24-polynomial"` | Submission discriminator. |
| `schema` | object | JSON Schema for the request's `payload`. It validates the array structure; mathematical validity is reported per polynomial by the verification service. Unknown payload fields are rejected. |
| `metaSchema` | object | JSON Schema for optional `meta`. IGP24 accepts only an optional batch `description`. |
| `permission.teamRole` | `"deadlineTeamMember"` | Admission and shared history are scoped to the immutable team recorded at the official deadline, not a team the caller joins later. |
| `window.opensAt` | string \| null | Frozen official-competition submission opening time as an ISO 8601 UTC string. |
| `window.closesAt` | string \| null | Frozen official-competition deadline as an ISO 8601 UTC string. It does not close an enabled post-event validation mode. |
| `limits.maxBytes` | integer | Maximum UTF-8 byte length of the submitted polynomial lines joined with `\n`, without an added trailing newline. |
| `limits.maxPolynomials` | integer | Maximum number of polynomial positions in one verification or persistent batch. It matches `schema.properties.polynomials.maxItems` and `submissionStatus.perBatchPolynomialLimit`. |
| `limits.maxRequestBytes` | integer | Separate maximum for the normalized JSON request, including `idempotencyKey`, `payload`, `meta`, field names, and string-escaping overhead. |
| `submissionStatus` | object \| null | Caller-specific current admission and team-budget snapshot. `null` means the status service is temporarily unavailable; do not infer permission from the official window. |

IGP24 uses append-only submission history, so it has no replaceable current-entry or slot limit. The live batch budget belongs in `submissionStatus`, not in a generic `limits.maxEntries` field.

### Submission status

| Field | Type | Description |
| :--- | :--- | :--- |
| `currentMode` | `"competition"` \| `"discovery_only"` \| `"closed"` | Current admission mode. `discovery_only` is the stable wire value for post-event validation. |
| `maySubmit` | boolean | Whether the caller passes the status precheck at response time. Eligibility is checked again when a new batch is submitted. |
| `denialReason` | string \| null | Stable reason when `maySubmit` is `false`; values are listed below. |
| `dailyBatchLimit` | integer \| null | Deadline team's persistent batch allowance for the current UTC day. `null` when that mode has no applicable daily budget. |
| `usedBatchesToday` | integer \| null | Persistent batches already admitted for the deadline team in the current UTC day. |
| `remainingBatchesToday` | integer \| null | Remaining persistent batches before the next UTC reset. |
| `perBatchPolynomialLimit` | integer | Maximum polynomial positions in one persistent batch. |
| `nextUtcResetAt` | string | Next UTC-day boundary as an ISO 8601 UTC timestamp. It is quota metadata, not a promise that submission mode stays open until then. |
| `discoveryOnlyEndsAt` | string \| null | Configured end of post-event validation, or `null` when no end is scheduled. |
| `sourcePhase` | `"competition"` \| `"discovery_only"` | Immutable source classification assigned to a batch accepted now. |
| `officialScoringEligible` | boolean | Whether a newly accepted batch can affect official scoring. It is `false` in post-event validation mode. |
| `teamId` | string \| null | Deadline-team ID used for admission and shared quota, or `null` when no applicable team is resolved. Do not send this value back as authority. |

`maySubmit` is a precheck, not a reservation. Team usage, eligibility, disqualification, mode, and service health can change before the write reaches admission.

### Denial reasons

| Value | Meaning |
| :--- | :--- |
| `OFFICIAL_STORE_FROZEN` | This service instance exposes the frozen official store and does not accept writes. |
| `DISCOVERY_ONLY_CLOSED` | Post-event validation is disabled or has ended. |
| `DISCOVERY_ONLY_NOT_ELIGIBLE` | The caller has no eligible deadline-team participation. |
| `DISCOVERY_ONLY_TEAM_DISQUALIFIED` | The deadline team is not permitted to submit post-event batches. |
| `TEAM_DAILY_LIMIT` | The deadline team has used its current UTC-day batch budget. |

Do not derive `maySubmit` by comparing the official `window` with the client clock. Read `submissionStatus`, then handle the write response as authoritative.

See [Verify a polynomial batch](./verify-polynomials.md) for a synchronous non-persistent check and [Submit polynomials](./submit-polynomials.md) for the append-only request and response fields.

## Errors

| HTTP | Code | When |
| :---: | :--- | :--- |
| `404` | `NOT_FOUND` | IGP24 does not exist or is not publicly visible. |

See [Errors](../../../errors.md) for shared authentication, scope, and rate-limit errors.
