# Submit a competition entry

```http
POST /api/public/v1/competitions/{competitionId}/submissions
```

**Scope**: `competition.write`.

Creates or replaces an entry according to the competition's `submissionSpec`. Send `Content-Type: application/json`.

## Common contract

| Field | Type | Required | Description |
| :--- | :--- | :---: | :--- |
| `competitionId` | string | Yes | Path parameter identifying the competition. |
| `slot` | integer | Conditional | Top-level model-reference slot. Defaults to `1`. |
| `payload` | object | Yes | Kind-specific judged payload. |
| `meta` | object | No | Kind-specific unjudged metadata. Unknown fields are rejected. |

Creating an entry returns `201`. Replacing an overwrite-in-place entry returns `200`. IGP24 always creates a new history record and returns `201`.

## Response DTO

```ts
type SubmitCompetitionEntryResponse = {
  ok: true;
  data: SubmissionDto;
};
```

`SubmissionDto` is expanded for each concrete competition below. See [Submission record DTOs](../../../reference/submission-kinds.md#submission-record-dtos) for the named union.

## Modular Arithmetic Challenge

Request DTO: [`SubmitModelReferenceRequest`](../../../reference/submission-kinds.md#submit-request-dtos).

```bash
curl -X POST "https://api.sair.foundation/api/public/v1/competitions/modular-arithmetic-challenge/submissions" \
  -H "Authorization: Bearer $SAIR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "slot": 2,
    "payload": {
      "modelName": "your-team/your-model",
      "commitHash": "0123456789abcdef0123456789abcdef01234567"
    },
    "meta": {
      "description": "Pinned model revision for official evaluation."
    }
  }'
```

Complete request body:

```json
{
  "slot": 2,
  "payload": {
    "modelName": "your-team/your-model",
    "commitHash": "0123456789abcdef0123456789abcdef01234567"
  },
  "meta": {
    "description": "Pinned model revision for official evaluation."
  }
}
```

Complete `201 Created` or `200 OK` response:

```json
{
  "ok": true,
  "data": {
    "submissionId": "sub_01JMAC00000000000000000001",
    "competitionId": "modular-arithmetic-challenge",
    "kind": "model-reference",
    "slot": 2,
    "payload": {
      "modelName": "your-team/your-model",
      "commitHash": "0123456789abcdef0123456789abcdef01234567"
    },
    "meta": {
      "description": "Pinned model revision for official evaluation."
    },
    "createdAt": "2026-05-18T12:34:56Z",
    "updatedAt": "2026-05-20T08:11:02Z"
  }
}
```

`slot` defaults to `1`, never means "first empty slot", and must be between `1` and `submissionSpec.limits.maxEntries`. `model-reference` does not accept `meta.contributorNetworkItemId`.

## Mathematics Distillation Stage 1

Request DTO: [`SubmitCheatsheetRequest`](../../../reference/submission-kinds.md#submit-request-dtos).

```bash
curl -X POST "https://api.sair.foundation/api/public/v1/competitions/mathematics-distillation-challenge-equational-theories-stage1/submissions" \
  -H "Authorization: Bearer $SAIR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "payload": {
      "content": "When the equation has a neutral element, test substitutions that preserve it before expanding the search."
    },
    "meta": {
      "description": "Playground-tested cheatsheet.",
      "contributorNetworkItemId": "cn_01JSTAGE100000000000000001"
    }
  }'
```

Complete request body:

```json
{
  "payload": {
    "content": "When the equation has a neutral element, test substitutions that preserve it before expanding the search."
  },
  "meta": {
    "description": "Playground-tested cheatsheet.",
    "contributorNetworkItemId": "cn_01JSTAGE100000000000000001"
  }
}
```

Complete `201 Created` or `200 OK` response:

```json
{
  "ok": true,
  "data": {
    "submissionId": "sub_01JSTAGE100000000000000001",
    "competitionId": "mathematics-distillation-challenge-equational-theories-stage1",
    "kind": "cheatsheet",
    "payload": {
      "content": "When the equation has a neutral element, test substitutions that preserve it before expanding the search."
    },
    "meta": {
      "description": "Playground-tested cheatsheet.",
      "contributorNetworkItemId": "cn_01JSTAGE100000000000000001"
    },
    "createdAt": "2026-05-18T12:34:56Z",
    "updatedAt": "2026-05-18T12:34:56Z"
  }
}
```

## Mathematics Distillation Stage 2

Request DTO: [`SubmitSolverParticipationRequest`](../../../reference/submission-kinds.md#submit-request-dtos).

Use `track` and `modelId` values returned by the current competition detail response.

```bash
curl -X POST "https://api.sair.foundation/api/public/v1/competitions/mathematics-distillation-challenge-equational-theories-stage2/submissions" \
  -H "Authorization: Bearer $SAIR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "payload": {
      "track": "solo",
      "modelId": "openai-gpt-oss-120b",
      "solverCode": "import Mathlib\n\nexample (n : Nat) : n = n := by\n  rfl"
    },
    "meta": {
      "description": "Playground-tested Lean solver.",
      "contributorNetworkItemId": "cn_01JSTAGE200000000000000001"
    }
  }'
```

Complete request body:

```json
{
  "payload": {
    "track": "solo",
    "modelId": "openai-gpt-oss-120b",
    "solverCode": "import Mathlib\n\nexample (n : Nat) : n = n := by\n  rfl"
  },
  "meta": {
    "description": "Playground-tested Lean solver.",
    "contributorNetworkItemId": "cn_01JSTAGE200000000000000001"
  }
}
```

Complete `201 Created` or `200 OK` response:

```json
{
  "ok": true,
  "data": {
    "submissionId": "sub_01JSTAGE200000000000000001",
    "competitionId": "mathematics-distillation-challenge-equational-theories-stage2",
    "kind": "solver-participation",
    "payload": {
      "track": "solo",
      "modelId": "openai-gpt-oss-120b",
      "solverCode": "import Mathlib\n\nexample (n : Nat) : n = n := by\n  rfl"
    },
    "meta": {
      "description": "Playground-tested Lean solver.",
      "contributorNetworkItemId": "cn_01JSTAGE200000000000000001"
    },
    "createdAt": "2026-05-18T12:34:56Z",
    "updatedAt": "2026-05-18T12:34:56Z"
  }
}
```

One current entry is stored per track. Re-submitting `solo` does not replace `marathon`.

## Inverse Galois Problem (IGP24)

Request DTO: [`SubmitIgp24PolynomialRequest`](../../../reference/submission-kinds.md#submit-request-dtos).

```bash
curl -X POST "https://api.sair.foundation/api/public/v1/competitions/igp24/submissions" \
  -H "Authorization: Bearer $SAIR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "payload": {
      "polynomials": [
        "3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 # poly_disc_primes=[2,3]"
      ]
    },
    "meta": {
      "description": "Search batch 12."
    }
  }'
```

Complete request body:

```json
{
  "payload": {
    "polynomials": [
      "3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 # poly_disc_primes=[2,3]"
    ]
  },
  "meta": {
    "description": "Search batch 12."
  }
}
```

Complete `201 Created` response while background verification is queued:

```json
{
  "ok": true,
  "data": {
    "submissionId": "sub_01JIGP24000000000000000001",
    "competitionId": "igp24",
    "kind": "igp24-polynomial",
    "payload": {
      "queuedPolynomials": [
        {
          "polynomialIndex": 0,
          "status": "queued"
        }
      ]
    },
    "meta": {
      "description": "Search batch 12."
    },
    "verifiedPolynomials": [],
    "failedPolynomials": [],
    "createdAt": "2026-05-18T12:34:56Z",
    "updatedAt": "2026-05-18T12:34:56Z",
    "description": "Search batch 12.",
    "batchId": "igp24_batch_4fa85f64f18d4dc59eea4d2ef65db490",
    "submissionStatus": "queued",
    "queuedCount": 1,
    "rejectedCount": 0
  }
}
```

The response intentionally omits submitted coefficient strings. Save the returned `submissionId` for reads and downloads, and use `batchId` with [Get IGP24 submission batch status](./get-submission-batch-status.md) to poll verification status.

## Errors

| HTTP | Code | When |
| :---: | :--- | :--- |
| `400` | `MALFORMED_BODY` | The request is not valid JSON or does not use JSON content type. |
| `403` | `EMAIL_NOT_VERIFIED` | The account email is not verified. |
| `403` | `ENROLL_REQUIRED` | The caller has not enrolled. |
| `403` | `TEAM_OWNER_REQUIRED` | The caller does not satisfy the configured owner requirement. |
| `403` | `SUBMISSION_WINDOW_NOT_OPEN` | The submission window has not opened. |
| `403` | `SUBMISSION_WINDOW_CLOSED` | The submission window has closed. |
| `413` | `FILE_TOO_LARGE` | The configured payload or request-size limit was exceeded. |
| `422` | `SUBMISSION_PAYLOAD_INVALID` | `payload` failed its kind-specific schema. |
| `422` | `SUBMISSION_META_INVALID` | `meta` failed its kind-specific schema. |
| `422` | `SUBMISSION_SLOT_INVALID` | `slot` is outside `1..submissionSpec.limits.maxEntries`. |
| `429` | `IGP24_SUBMISSION_RATE_LIMIT_EXCEEDED` | The IGP24 team submission quota was exceeded. |

Model-reference validation can additionally return the stable Hugging Face lookup errors documented in [Errors](../../../errors.md).
