> ## 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.

# Upload a Document

> Send a document by URL or inline base64 for automatic Xactimate export and track it with the returned document ID.

`POST /upload` is the entry point for automatic Xactimate export. Every accepted upload returns a `document_id`, which becomes the handle for polling, streaming, and downstream bookkeeping.

If you are using an agent client such as ChatGPT, Claude, or Codex, see [CapOut MCP](/mcp/overview) instead. The MCP staged upload flow is separate from the public REST `POST /upload` contract documented here.

## Supported request shapes

### Send a `url`

Use `url` when the document is already available at a fetchable HTTPS location.

```json theme={null}
{
  "url": "https://example.com/claims/123/estimate.pdf",
  "file_name": "claim-123-estimate.pdf",
  "xn_address": "restoration-team@example.xn",
  "profile_code": "5L"
}
```

### Send `file_base64`

Use `file_base64` when your application sends document bytes inline in the JSON payload.

Inline base64 uploads are supported up to `50 MiB`.

```json theme={null}
{
  "file_base64": "JVBERi0xLjQKJ...",
  "file_name": "claim-123-estimate.pdf",
  "xn_address": "restoration-team@example.xn",
  "profile_code": "5L"
}
```

## Required fields

Every upload includes:

* `file_name`: the original filename shown in downstream responses
* `xn_address`: the Xactnet recipient address tied to the document
* `profile_code`: the Xactimate profile, `5L` for Carrier or `8D` for Contractor

Exactly one of these payload fields must be present:

* `url`
* `file_base64`

If both fields are present, or if neither field is present, the API returns `422`.

Your request chooses the PDF source. CapOut chooses the protected AWS storage
bucket and key used for intake; callers cannot override where the PDF is written
inside CapOut's AWS storage.

## Encode a local file to base64

These examples show the local-file-to-base64 step that teams often use before constructing an inline upload request, including workflows that start with scanner images or other local files.

### Python

```python theme={null}
from base64 import b64encode
from pathlib import Path

source_path = Path("./claim-123-estimate.pdf")
file_base64 = b64encode(source_path.read_bytes()).decode("utf-8")

print(file_base64)
```

### Node.js

```js theme={null}
import { readFile } from "node:fs/promises";

const sourcePath = "./claim-123-estimate.pdf";
const fileBuffer = await readFile(sourcePath);
const fileBase64 = fileBuffer.toString("base64");

console.log(fileBase64);
```

### `curl`

Use the base64 string as the `file_base64` field in the upload request:

```bash theme={null}
curl https://api.capout.ai/upload \
  -X POST \
  -H "content-type: application/json" \
  -H "capout-api-key: $CAPOUT_API_KEY" \
  -d '{
    "file_base64": "PASTE_BASE64_STRING_HERE",
    "file_name": "claim-123-estimate.pdf",
    "xn_address": "restoration-team@example.xn",
    "profile_code": "5L"
  }'
```

## What to store after upload

Persist at least these response fields on your side:

* `document_id`
* `status`
* `created_at`
* `status_url`

That gives you enough to start polling immediately and to join later status changes to your own job record.

## Validation and retries

* Review `422` responses first when an upload is rejected. They indicate request-shape problems such as sending both `url` and `file_base64`, sending neither field, or omitting a required field.
* Retry upload failures from the same source document after correcting the request or transport problem.
* Reuse the returned `document_id` for all follow-up status checks, realtime subscriptions, and internal job mapping.

## Typical follow-up flow

1. Upload the document.
2. Store `document_id` on your internal job or claim record.
3. Poll `GET /status/{document_id}` for simple backends, or open a realtime stream for richer UX while the export workflow completes.
4. Optionally query `GET /documents` to reconcile the authenticated organization's recent uploads.
