# Downloads

Approved films are downloaded with `GET /films/{id}/file`, their subtitles with `GET /films/{id}/subtitles.srt`.
Storyboard previews work the same way with `GET /films/{id}/storyboard-preview/file`. Downloads are free of credits.

### ETag = SHA-256

Every file comes with a strong `ETag`: the SHA-256 of the file in quotes. For films it equals `approval.sha256` of the
film. Compute the SHA-256 of the bytes you received and compare. If an event is older than the current approval,
the `ETag` counts.

### Resume a download

Send `Range: bytes=<from>-` together with `If-Range: <ETag>`. If the file is unchanged, mint answers `206` with the
rest; if a new approval exists in the meantime, `200` with the whole new file. One range per request is supported.

### Skip unchanged files

Send `If-None-Match: <ETag>`. mint answers `304` without a body if you already have the current file. `HEAD` returns
the headers only.

### When a download is not possible

| Response | Meaning |
|---|---|
| `404 not_approved` | The film has no active approval (never approved, or revoked). |
| `404 subtitles_not_available` | The approval has no subtitles. |
| `409 file_unavailable` | The file is temporarily not available. Retry later. |
| `429 rate_limited` | Too many downloads at the same time (`details.reason` `parallel_downloads`). Wait for `Retry-After`. |
| `503` | mint is briefly checking the file. Wait for `Retry-After`. |

```sh Download and verify
curl https://api.cream-ai.de/api/v1/films/k7m2xq9v4t8n1b5r3c6d0wza/file \
  -H "Authorization: Bearer $MINT_API_KEY" \
  -D headers.txt -o film.mp4
grep -i etag headers.txt
shasum -a 256 film.mp4
```

```sh Resume an interrupted download
curl https://api.cream-ai.de/api/v1/films/k7m2xq9v4t8n1b5r3c6d0wza/file \
  -H "Authorization: Bearer $MINT_API_KEY" \
  -H "Range: bytes=33554432-" \
  -H 'If-Range: "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b"' \
  -o film.part
```
