# Submit solutions

```http
POST /api/public/v1/competitions/acc/submissions
```

**Scope**: `competition.write`. An API key is required.

Accepts an immutable, team-owned Discovery batch for asynchronous verification. Success returns **202 Accepted** with a queued Submission.

A batch may mix AC and Stable AC challenge IDs; the server selects the corresponding move specification and target for each challenge. All active team members share the same team/day quota across website and Public API.

## Request body

Send UTF-8 `application/json` with these fields. Read the TXT file as strict UTF-8, preserving its BOM, comments, whitespace, line endings, and move literals.

| Field              | Requirement and type                                                                                                                                                 |
| :----------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `payload`          | Required object containing only `text`.                                                                                                                              |
| `payload.text`     | Required string — Complete TXT, at most `limits.maxBodyBytes` UTF-8 bytes after JSON decoding.                                                                       |
| `meta`             | Optional object containing only `description`; cannot be null.                                                                                                       |
| `meta.description` | Optional string — Independent submission note. Trimmed before counting Unicode code points against `limits.maxNotesChars`. Omitted or whitespace-only means no note. |

All other fields are rejected. The TXT contains one challenge per physical line. A batch may mix both problems:

```text
# AC
ac-08491: [7, 4, 12, 12, 3, 1, 5, 5]
sac-08491: [7, 4, 12, 12, 3, 1, 5, 5, 16, 15] # Stable AC
```

Blank lines and whole-line comments are allowed. The first `#` starts a comment through the end of that line. Each moves array must fit on one physical line. LF, CRLF, and an initial UTF-8 BOM are supported. Comments do not become submission notes.

The batch must contain between one and `limits.maxSolutions` challenge lines; duplicate challenge IDs are rejected. Arrays are parsed for structure, but invalid moves, unknown challenge IDs, excessive paths, and incorrect final states are reported per solution after admission. For verified solutions, moves must be integer JSON literals in the corresponding problem's range and fit `limits.maxPathLength`. Empty arrays are allowed.

Do not parse and reserialize move arrays: `1.0` and `1e0` must not silently become integer `1`. JSON serialization of the **outer request** preserves `payload.text`; its escaping overhead and the note do not count toward the TXT byte limit.

TXT structure checks run in order: UTF-8 byte limit, all line syntax, nonempty and challenge count, then duplicate IDs. Invalid request fields, notes, or TXT structure do not create a submission or consume team quota. Line-format errors and duplicate IDs include a positive `error.details.line_number`, counting physical lines from 1, including comments and blank lines.

## Example request

This mixed batch is used throughout the submission, history, detail, and download examples.

```json
{
  "payload": {
    "text": "# AC\nac-08491: [7, 4, 12, 12, 3, 1, 5, 5]\nsac-08491: [7, 4, 12, 12, 3, 1, 5, 5, 16, 15] # Stable AC\n"
  },
  "meta": { "description": "Search run notes" }
}
```

Save the outer JSON as `request.json`, then send it:

```bash
export SAIR_API_BASE="https://api.sair.foundation/api/public/v1"

curl "$SAIR_API_BASE/competitions/acc/submissions" \
  -H "Authorization: Bearer $SAIR_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @request.json
```

## Response fields

The data object is a [Submission](../acc.md#submission). `202` means admitted and queued, not mathematically verified. Save its ID and use [Get a submission](./get-submission.md) to await `complete` or `failed`.

## Example response

```json
{
  "ok": true,
  "data": {
    "submissionId": "142",
    "competitionId": "acc",
    "teamId": "team-17",
    "submittedBySairId": "sair-example-member",
    "status": "queued",
    "receivedAt": "2026-09-10T12:00:00.123456Z",
    "updatedAt": "2026-09-10T12:00:00.123456Z",
    "solutionCount": 2,
    "results": [],
    "errorMessage": null,
    "meta": { "description": "Search run notes" }
  }
}
```

## Quota and retries

Every accepted TXT batch consumes one unit of the owning team's `limits.dailySubmissions`, regardless of solution count or the verification or processing outcome. The counter is shared by all active members, website and API submissions, and resets at `00:00:00Z`. This operation does not consume the generic `account-write` tier. Read and polling requests consume `account-read`.

On `429 DAILY_QUOTA_EXCEEDED`, use these ACC quota response fields:

| Field | Type and meaning |
| :--- | :--- |
| `Retry-After` header | Integer number of seconds to wait before another submission. |
| `error.details.limit` | Positive `integer` — Team submission limit for the UTC day. |
| `error.details.used` | Non-negative `integer` — Accepted batches counted against the team's UTC-day limit. |
| `error.details.resetsAt` | UTC ISO 8601 `string` — Time when the team's daily counter resets. |

There is no idempotency contract for this POST. Do not automatically resubmit after a timeout or uncertain `5xx`: each accepted retry creates another batch and consumes another unit. Inspect [team history](./list-my-submissions.md) and compare a candidate's [original download](./download-submission.md) before deciding whether to send again. Do not use `canSubmit: true` as proof of remaining quota.

## Errors

| HTTP  | Code                    | Meaning                                                                                                                                                                                          |
| :---: | :---------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400` | `E_MALFORMED`           | Invalid media type, UTF-8, JSON, Unicode, fields, note, TXT size or syntax, empty TXT, or challenge count. `details.detail` describes the cause; line errors also include `details.line_number`. |
| `400` | `E_DUPLICATE_CHALLENGE` | A repeated challenge ID. `details.detail` describes the error and `details.line_number` locates the duplicate in the TXT.                                                                        |
| `403` | `NOT_ENROLLED`          | ACC enrollment is incomplete.                                                                                                                                                                    |
| `403` | `TEAM_REQUIRED`         | No currently active ACC team.                                                                                                                                                                    |
| `403` | `SUBMISSION_NOT_OPEN`   | Competition status or submission window forbids new batches.                                                                                                                                     |
| `429` | `DAILY_QUOTA_EXCEEDED`  | Current team's UTC-day batch budget is exhausted.                                                                                                                                                |

See [shared errors](../acc.md#shared-errors) for authentication, scope, availability, and configuration errors.
