> ## Documentation Index
> Fetch the complete documentation index at: https://docs.capout.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Download ESX Files

> Give users stable CapOut links for Contractor and Carrier ESX files without storing expiring S3 signatures.

Every accepted upload returns stable links for both generated ESX profiles:

```json theme={null}
{
  "download_url": "https://api.capout.ai/doc_123.esx",
  "contractor_download_url": "https://api.capout.ai/doc_123.esx?profile=contractor",
  "carrier_download_url": "https://api.capout.ai/doc_123.esx?profile=carrier"
}
```

The links are safe to store in your application. The private S3 signatures behind them are not.

## Choose a profile

| Link                                    | ESX profile                    |
| --------------------------------------- | ------------------------------ |
| `/{document_id}.esx`                    | Contractor (`8D`), the default |
| `/{document_id}.esx?profile=contractor` | Contractor (`8D`)              |
| `/{document_id}.esx?profile=carrier`    | Carrier (`5L`)                 |

CapOut generates both files for every successful export. The deprecated upload field `profile_code` does not choose which artifact is generated or downloaded.

## Download from an authenticated client

Send the same organization-scoped `capout-api-key` used for upload, status, and
document history. Do not put the key in the URL or a query parameter.

```bash theme={null}
# Contractor (default)
curl -L "https://api.capout.ai/doc_123.esx" \
  -H "capout-api-key: $CAPOUT_API_KEY" \
  -o estimate-contractor.esx

# Carrier
curl -L "https://api.capout.ai/doc_123.esx?profile=carrier" \
  -H "capout-api-key: $CAPOUT_API_KEY" \
  -o estimate-carrier.esx
```

The URL alone does not grant access. A valid key for the document's organization
is required each time CapOut issues a fresh signed redirect.

## How the stable redirect works

1. Your integration stores the clean `api.capout.ai` URL returned by CapOut.
2. The client requests the link with `capout-api-key`.
3. CapOut validates the key and verifies that the durable document belongs to its organization.
4. CapOut forwards the caller's key to the frontend workflow action, which independently checks access and signs the selected Contractor or Carrier artifact.
5. The route returns a non-cached `307` redirect to a signed private S3 URL.
6. The S3 signature expires after 15 minutes, while the original CapOut link remains stable and can issue another fresh redirect later.

Do not copy the redirected S3 URL into your database or send it as the durable link. Always retain the clean CapOut URL.

## Readiness and errors

The clean links are returned immediately after upload so you can store them with the job. They become downloadable only after ESX generation completes.

| Status | Meaning                                                                              |
| ------ | ------------------------------------------------------------------------------------ |
| `307`  | Export is ready; follow the redirect to download it                                  |
| `401`  | `capout-api-key` is missing or invalid                                               |
| `404`  | Document is unknown or inaccessible, or the requested profile artifact was not found |
| `409`  | Export is still processing or otherwise not ready                                    |
| `422`  | `profile` is not `contractor` or `carrier`                                           |
| `502`  | CapOut could not refresh a valid signed artifact URL                                 |
| `503`  | Durable download lookup is temporarily unavailable                                   |

Wait for `export.completed`, or for `GET /status/{document_id}` to report a completed export, before presenting the link as ready. A client that opens it early can retry after receiving `409`.

## Where the links appear

The same stable URLs are available from:

* `POST /upload`
* `GET /status/{document_id}` under `export`
* `GET /documents` under each document's `export`
* realtime `export.completed` events
* CapOut MCP processing, status, and waiting tools
