# Download a creative's final file

Redirects to a download link for the final video of one approved creative of your organisation. Use it to fetch the file automatically once the creative's record says `final.ready` is `true`.

```
GET /api/delivery/v1/creatives/{id}/file
```

**Scope:** `creatives:export`

## Description

Downloads the same file as the record's `final.file_url`, but with your API key instead of a public share link: use it when you would rather not rely on share links. The URL `https://www.wandura.ai/api/delivery/v1/creatives/{id}/file` does not expire. Call it with your API key; it answers `302` with a download link in `Location`, valid for 15 minutes. The file is the clean final, with your company's brand mark if your org has one: an MP4, 1080 × 1920.

- The download link needs no key and is not cacheable. Do not store it: call this endpoint again for a fresh one.
- Most HTTP clients follow the redirect for you and drop the `Authorization` header on the way, which is fine.
- Add `redirect=0` to get the link and its expiry as JSON instead of a redirect.
- A creative that does not exist, belongs to another organisation, or is not in status `approved` or `pushed` returns the same `404`. An approved creative whose final is not ready yet returns `409`. Once your export rights for the film end, it returns `403` with `code` `4032`.
- Every call is logged against your API key and shares the rate-limit counter of the other creatives endpoints.

## Request parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `Authorization` | header | string | Yes | `Bearer <API key>` for a key with the `creatives:export` scope. |
| `id` | path | string | Yes | The `creative_id` of the creative. A value that is not a UUID returns 404. |
| `redirect` | query | string | No | `0` returns the download link as JSON (200) instead of redirecting. |
| `Wandura-Version` | header | string | No | Optional. A dated API version (YYYY-MM-DD) to use for this request instead of the version pinned to your API key. Unknown or retired values answer 400 with `error_code` `unsupported_version`. |

## Request example

```bash
curl -sL -o final.mp4 https://www.wandura.ai/api/delivery/v1/creatives/5e1b7c3a-2d4f-4a6b-9c8d-0e1f2a3b4c5d/file \
  -H "Authorization: Bearer $WANDURA_API_KEY"
```

## Response

`302 Found`: the download link is in the `Location` header. The body is empty.

`200 OK` (only with `redirect=0`):

| Field | Type | Description |
|---|---|---|
| `code` | integer | `0`. |
| `message` | string | `"ok"`. |
| `data.url` | string | Download link of the final MP4. Needs no key. Do not store it. |
| `data.expires_at` | integer | When `url` stops working, in Unix epoch seconds (15 minutes after the call). |
| `server_time` | integer | Server time in Unix epoch seconds. |

## Response example

```json
{
  "code": 0,
  "message": "ok",
  "data": { "url": "https://media.example.com/final.mp4?signature=7f3a9c", "expires_at": 1790679932 },
  "server_time": 1790679032
}
```

## Response headers
| Header | Responses | Description |
|---|---|---|
| `Wandura-API-Status` | all | API status. `beta` today, on every response, success or error. |
| `Wandura-Version` | all | The dated API version (YYYY-MM-DD) this response was produced in: the version pinned to your API key, or the one you sent in the `Wandura-Version` request header. Keys created before dated versions existed use `2026-10-02`. |
| `Wandura-Request-Id` | all | An opaque id for this request (`req_` followed by 26 characters). Every response carries it, errors included, and error bodies repeat it as `request_id`. Log it, and quote it when you contact Wandura about a request: it finds the exact request in our logs. Do not parse it. |
| `Cache-Control` | all | Always `no-store`. Do not cache these responses in shared caches. |
| `Location` | 302 | Download link of the final MP4. Needs no key. Do not store it. |
| `Retry-After` | 429 | Seconds to wait before retrying. Sent with 429 and with retryable 503 responses. |
| `X-RateLimit-Limit` | 429 | Requests (for playback, tickets) allowed per window for this endpoint group and your organisation. |
| `X-RateLimit-Window` | 429 | Window length in seconds. |

## Errors

| Status | `code` | When |
|---|---|---|
| 400 | none | The `Wandura-Version` header, or the version pinned to your key, is unknown or retired. The body adds `supported_versions` and `latest_version` (and `upgrade_to` when your pin was retired). |
| 401 | 4010 | The `Authorization: Bearer` header is missing. |
| 401 | 4011 | The key is unknown or revoked. |
| 403 | 4030 | The key lacks the `creatives:export` scope. |
| 403 | 4031 | Your organisation's access is suspended. |
| 403 | 4032 | `rights_ended`: your organisation no longer has export rights for this creative's film (`rights.ends_at` has passed, or the license was suspended). |
| 404 | 4040 | No approved creative with this ID exists for your organisation, or the ID is not a UUID. |
| 409 | 4090 | `final_not_ready`: the final file is still being made. Retry when the record's `final.ready` is `true`. |
| 429 | none | Rate limit reached. Flat body with `error_code` `rate_limited`, not the envelope. |
| 503 | 5030 | The creative data is temporarily unavailable. Retry with backoff. |
| 503 | 5031 | Wandura could not verify the API key in time. The key is not wrong: retry with backoff. |
| 503 | 5032 | The download link could not be prepared right now. Retry with backoff. |

See [Errors](https://docs.wandura.ai/developers/concepts/errors#creative-file-errors) for what to do in each case.
