# Download a submission

```http
GET /api/public/v1/competitions/igp24/submissions/{submissionId}/download
```

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

Downloads the exact polynomial string values stored for one append-only IGP24 submission-history record.

The record belongs to the immutable team recorded at the competition deadline. Every eligible deadline-team member can download it; an owner role and current active-team membership are not required. Obtain the opaque `submissionId` from [List my submissions](./list-my-submissions.md) or [Get a submission by ID](./get-submission.md).

This endpoint returns a plain-text attachment rather than the standard JSON success envelope.

## Path parameter

| Parameter | Type | Required | Description |
| :--- | :--- | :---: | :--- |
| `submissionId` | string | Yes | Exact, case-sensitive public history-record ID returned by a submission endpoint. |

## Example request

```bash
curl \
  --remote-header-name \
  --remote-name \
  "https://api.sair.foundation/api/public/v1/competitions/igp24/submissions/sub_01JIGP24000000000000000001/download" \
  -H "Authorization: Bearer $SAIR_API_KEY"
```

`--remote-name` saves the response, and `--remote-header-name` uses the server-provided attachment filename.

## Response

```http
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Disposition: attachment; filename="igp24-sub_01JIGP24000000000000000001-polynomials.txt"
Cache-Control: private, no-store
X-Content-Type-Options: nosniff
```

The response body contains the stored string values in their original request order:

```text
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]
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 # duplicate candidate
1,2,3 # malformed example retained in the source record
```

## Serialization

- Each `payload.polynomials` string from the accepted request is written unchanged. The server does not trim whitespace, remove comments, canonicalize coefficients, deduplicate positions, or omit malformed and filtered positions.
- Values are joined with an LF byte (`\n`), and the response ends with one final LF. The result is a reconstruction of the submitted string array, not the original JSON request bytes.
- Duplicate inputs remain duplicate lines. Their positions match `polynomialIndex` values returned by [Get a submission by ID](./get-submission.md).
- This file contains source input only. It does not include validation status, labels, scoring metadata, or error messages.

If the exact stored string values cannot be recovered, the endpoint returns `404 ORIGINAL_PAYLOAD_UNAVAILABLE`. It must not silently substitute normalized canonical polynomials or an incomplete subset.

## Resource behavior

- The attachment filename is `igp24-{submissionId}-polynomials.txt`.
- An IGP24 submission-history record is append-only. Repeating this request for the same `submissionId` returns the same source body; later validation results do not change it.
- The source remains downloadable after the official competition closes and after the caller leaves or changes an active team, provided the caller belongs to the record's deadline team.
- Moving a valid `submissionId` to another competition path, using another deadline team's ID, or requesting an unknown ID produces the same not-found response.
- The response is private team data and is marked `no-store`; clients should avoid placing it in shared caches or logs.

## Errors

| HTTP | Code | When |
| :---: | :--- | :--- |
| `404` | `NOT_FOUND` | IGP24 is not publicly visible, or the submission does not exist in IGP24 or is not visible to the caller's deadline team. |
| `404` | `ORIGINAL_PAYLOAD_UNAVAILABLE` | The submission is visible to the caller, but its exact stored polynomial strings cannot be recovered. |
| `503` | `IGP24_SERVICE_UNAVAILABLE` | Exact source recovery depends on an authoritative service that is temporarily unavailable. |

Error responses use the standard JSON error envelope even though a successful response is plain text. The not-found cases intentionally share `NOT_FOUND` so submission IDs cannot be used to discover another team's work. See [Errors](../../../errors.md) for shared authentication, scope, and account-rate-limit errors.
