# Get Claims Source: https://docs.capout.ai/api-reference/claims/get-claims /openapi.json get /claims Check claim balance for the authenticated organization. # Download Esx Source: https://docs.capout.ai/api-reference/esx-downloads/download-esx /openapi.json get /{document_id}.esx Authorize an organization and redirect to a freshly signed ESX object. # API Reference Overview Source: https://docs.capout.ai/api-reference/overview Endpoint map, auth model, and the fastest route to the generated reference pages. Base URL: `https://api.capout.ai` ## Auth model * REST endpoints use the `capout-api-key` header. * Realtime streams use a short-lived `token` minted from `POST /ws/token`. * `GET /{document_id}.esx` uses `capout-api-key` and only authorizes documents in that key's organization. ## Endpoint map ### Upload * `POST /upload`: submit one PDF to generate Contractor and Carrier ESX files * `POST /upload/json`: submit a pre-structured JSON estimate (`StructuredEstimateV1`) * `POST /upload/csv`: submit a CSV estimate file with optional JSON metadata envelope Every upload response includes stable Contractor and Carrier download URLs. PDF uploads accept and record optional `xn_address` and `profile_code` values. Use the download URL's `profile` parameter to select Contractor or Carrier. Structured imports support the `Idempotency-Key` header. ### Status * `GET /status/{document_id}`: poll one document's workflow state * `GET /documents`: list documents submitted by the authenticated organization Both status endpoints include the stable download links when export metadata is available. ### ESX downloads * `GET /{document_id}.esx`: download Contractor (`8D`) by default * `GET /{document_id}.esx?profile=contractor`: explicitly download Contractor (`8D`) * `GET /{document_id}.esx?profile=carrier`: download Carrier (`5L`) The authenticated route returns `404` for unknown or cross-organization documents and `409` until the export is ready. When ready, it returns a non-cached `307` to a freshly signed private S3 URL. Store the clean CapOut URL, not the redirected URL, and send `capout-api-key` with every request. ### Claims * `GET /claims`: inspect the current organization claim balance ### Realtime * `POST /ws/token`: mint a short-lived realtime token * `GET /sse/status`: subscribe over SSE * `wss://api.capout.ai/ws/status`: subscribe over WebSocket after minting a token ## How to use this section Use the generated endpoint pages in the sidebar for request schemas, examples, and the interactive playground. The guides in the Documentation tab cover the recommended integration flow around those endpoints. # Sse Status Source: https://docs.capout.ai/api-reference/sse/sse-status /openapi.json get /sse/status SSE endpoint for streaming one or more documents' status updates. Requires a valid realtime ``token`` query param plus either one or more `document_id` values, or `recent=10`. # Get Document Status Source: https://docs.capout.ai/api-reference/status/get-document-status /openapi.json get /status/{document_id} Get the current processing status of a document (one-shot poll). # List Documents Source: https://docs.capout.ai/api-reference/status/list-documents /openapi.json get /documents List all API-submitted documents for the authenticated organization. # Upload Csv Source: https://docs.capout.ai/api-reference/upload/upload-csv /openapi.json post /upload/csv Upload a CSV estimate for catalog resolution, validation, and ESX generation. # Upload Document Source: https://docs.capout.ai/api-reference/upload/upload-document /openapi.json post /upload Upload a PDF document for processing. Exactly one of ``file_base64``, ``url``, or ``s3_path`` must be provided. # Upload Json Source: https://docs.capout.ai/api-reference/upload/upload-json /openapi.json post /upload/json Upload a structured JSON estimate for catalog resolution, validation, and ESX generation. # Create Realtime Ws Token Source: https://docs.capout.ai/api-reference/websocket/create-realtime-ws-token /openapi.json post /ws/token Mint a short-lived realtime token for WebSocket or SSE authentication. Connection flow: 1. Call `POST /ws/token` with your `capout-api-key`. 2. Read `token`, `ws_url`, and `sse_url` from the response. 3. Connect to `wss://api.capout.ai/ws/status?token=` for WebSocket updates, or `https://api.capout.ai/sse/status?token=` for Server-Sent Events. 4. Optionally scope the initial subscription with either: - `&document_id=` repeated one or more times - `&recent=10` to subscribe to the most recent organization-owned documents WebSocket example: `wss://api.capout.ai/ws/status?token=&document_id=doc_123` SSE example: `https://api.capout.ai/sse/status?token=&recent=10` After a WebSocket connection is established, clients can send JSON commands such as: `{"action":"subscribe","document_ids":["doc_123"]}` # Authentication Source: https://docs.capout.ai/authentication Use API keys for REST requests and short-lived tokens for realtime subscriptions. CapOut uses two authenticated access models: | Use case | Auth method | | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | | REST endpoints like `/upload`, `/status/{document_id}`, `/documents`, `/claims`, `/ws/token`, and `/{document_id}.esx` | `capout-api-key` request header | | Realtime subscriptions over `/ws/status` and `/sse/status` | `token` query parameter returned by `POST /ws/token` | ## API key header Send your organization-scoped API key in the `capout-api-key` header on REST calls. ```bash theme={null} curl https://api.capout.ai/documents \ -H "capout-api-key: $CAPOUT_API_KEY" ``` ## Authenticated ESX download links `GET /{document_id}.esx` requires the same `capout-api-key` header as upload. CapOut derives the caller's organization from that key and returns `404` when the document is unknown or belongs to another organization. Never put an API key in the URL or query string. The route does not expose a permanent S3 URL. After authorization and export completion, it returns a non-cached `307` redirect to a freshly signed private artifact. See [Download ESX files](/guides/download-esx). ## Realtime tokens Realtime connections do not use the API key directly. Instead: 1. Call `POST /ws/token` with your API key. 2. Read `token`, `ws_url`, `sse_url`, and `expires_at`. 3. Connect with `?token=` in the query string. This separation matters for browser clients, especially for SSE, where setting custom headers is not supported by `EventSource`. ## Token-based stream URLs Specific documents: ```text theme={null} wss://api.capout.ai/ws/status?token=&document_id=doc_123 https://api.capout.ai/sse/status?token=&document_id=doc_123 ``` Recent organization documents: ```text theme={null} wss://api.capout.ai/ws/status?token=&recent=10 https://api.capout.ai/sse/status?token=&recent=10 ``` ## Expiration strategy Treat realtime tokens as short-lived connection credentials: * Mint them just before opening a stream. * Re-mint on reconnect if the token has expired. * Keep API keys on trusted backend infrastructure when possible. # Claims and Usage Source: https://docs.capout.ai/guides/claims-and-usage Read organization claim balances and interpret expiring buckets. Use `GET /claims` to inspect the authenticated organization's available claim balance before kicking off more work or to display usage state in an admin UI. Each successful live workflow uses 1 claim and generates both Contractor and Carrier ESX files. ## Response shape The claims response includes: * `organization_id`: the owner of the balance * `available_claims`: the current spendable total * `expiring_claims_in_30_days`: claims that will age out soon * `total_granted_claims`: claims granted across eligible buckets * `total_used_claims`: claims already consumed from eligible buckets * `buckets`: individual purchased-claim buckets with remaining claims and expiration timestamps ## Example ```bash theme={null} curl https://api.capout.ai/claims \ -H "capout-api-key: $CAPOUT_API_KEY" ``` ```json theme={null} { "organization_id": "org_123", "available_claims": 5, "expiring_claims_in_30_days": 0, "total_granted_claims": 8, "total_used_claims": 3, "buckets": [ { "id": "purchased-claims-id", "source_type": "TOPUP_ONE_TIME", "quantity": 5, "claims_remaining": 4, "expires_at": "2026-08-01T00:00:00Z", "created_at": "2026-06-01T00:00:00Z" } ] } ``` ## Practical uses * Block or warn before high-volume export batches * Surface expiring balances in internal tooling * Reconcile billing and usage reports against CapOut balances ## Downloads and test mode A successful live conversion consumes one claim for both ESX profiles. Status checks, downloading either profile, repeating downloads, and refreshing expired signed URLs do not consume additional claims. Reuse the existing document ID instead of uploading again. Test keys generate real Contractor and Carrier ESX files with zero claims consumed and no XactNet delivery. They do not require a paid claim balance. # Download ESX Files Source: https://docs.capout.ai/guides/download-esx 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 records the `profile_code` supplied with your upload. Use the download URL's `profile` parameter to select the Contractor or Carrier file. ## 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. ## Re-download without another claim Downloading an existing export is free. Request the same stable `.esx` URL with a valid API key for the document’s organization whenever you need the file again. Downloading both Contractor and Carrier files does not consume additional claims. If a signed S3 URL expires, request the stable CapOut URL again to receive a fresh signature. This does not start another conversion or charge another claim. Do not re-upload the PDF just to retrieve an existing export. Use the upload response `document_id` in the URL, not an internal workflow or ESX task ID. A bare browser link cannot authenticate: the request needs the `capout-api-key` header. ## Test-key downloads New successful test-key exports generate real Contractor and Carrier ESX files with zero claims consumed and no XactNet delivery. Download them through the same authenticated URLs. Historical mock test exports have no generated artifact and may return `ESX_PROFILE_NOT_AVAILABLE`; they do not become real files retroactively. ## 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 prepares a signed download URL for 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 # Realtime Updates Source: https://docs.capout.ai/guides/realtime-updates Stream document status changes with WebSocket or Server-Sent Events. CapOut supports two realtime transports: * WebSocket for long-lived interactive clients that may want to change subscriptions after connecting * SSE for simpler browser-friendly one-way event delivery Both transports start with `POST /ws/token`. ## 1. Mint a realtime token ```bash theme={null} curl https://api.capout.ai/ws/token \ -X POST \ -H "capout-api-key: $CAPOUT_API_KEY" ``` Example response: ```json theme={null} { "token": "rt_123", "organization_id": "org_123", "expires_at": "2026-04-14T14:45:00Z", "ws_url": "/ws/status", "sse_url": "/sse/status" } ``` If the response contains relative paths, resolve them against `https://api.capout.ai` or `wss://api.capout.ai`. ## WebSocket example ```js theme={null} const tokenResponse = await fetch("https://api.capout.ai/ws/token", { method: "POST", headers: { "capout-api-key": process.env.CAPOUT_API_KEY } }).then((res) => res.json()); const wsUrl = new URL(tokenResponse.ws_url, "wss://api.capout.ai"); wsUrl.searchParams.set("token", tokenResponse.token); wsUrl.searchParams.append("document_id", "doc_123"); const socket = new WebSocket(wsUrl); socket.addEventListener("open", () => { socket.send(JSON.stringify({ action: "subscribe", document_ids: ["doc_123"] })); }); socket.addEventListener("message", (event) => { console.log(JSON.parse(event.data)); }); ``` ## SSE example ```js theme={null} const tokenResponse = await fetch("https://api.capout.ai/ws/token", { method: "POST", headers: { "capout-api-key": process.env.CAPOUT_API_KEY } }).then((res) => res.json()); const streamUrl = new URL(tokenResponse.sse_url, "https://api.capout.ai"); streamUrl.searchParams.set("token", tokenResponse.token); streamUrl.searchParams.set("recent", "10"); const source = new EventSource(streamUrl); source.onmessage = (event) => { console.log(JSON.parse(event.data)); }; ``` ## Scoping subscriptions You can scope the initial stream in two ways: * Repeat `document_id` to follow specific documents * Send `recent=10` to follow the latest organization-owned documents ## Export completion and download links `export.completed` is the download-ready signal. Its `export` object contains the same stable links returned by upload, status, and document history: ```json theme={null} { "event": "export.completed", "data": { "document_id": "doc_123", "status": "exported", "export": { "claims_used": 1, "line_item_count": 112, "exported_at": "2026-08-04T16:20:00Z", "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" } } } ``` `download_url` selects Contractor by default. CapOut broadcasts only the stable clean links, never the expiring S3 signature. Request a clean link with the organization's `capout-api-key`; after authorizing the document, CapOut obtains a fresh signature and returns a non-cached `307` redirect. ## Reconnect behavior Handle disconnects with token expiry in mind: 1. Detect closure or error. 2. Mint a fresh realtime token. 3. Re-open the connection with the same document scope. See [Download ESX files](/guides/download-esx) for profile selection and redirect behavior. # Structured Estimate Imports (JSON & CSV) Source: https://docs.capout.ai/guides/structured-estimate-imports Import pre-structured estimates directly via JSON or CSV to bypass OCR, resolve catalog items, and generate Contractor and Carrier ESX files. In addition to PDF uploads, CapOut supports direct, typed estimate imports via: * `POST /upload/json`: structured JSON estimate payload. * `POST /upload/csv`: multipart CSV file. Upload an estimate as JSON or CSV to review its line items and download Contractor and Carrier ESX files. Every accepted import returns a `document_id`, providing the same status tracking, realtime events, and clean `/{document_id}.esx` downloads as PDF estimates. *** ## Download example files * [Download the 50-line-item, multiroom JSON scope](/examples/estimate-long.json) * [Download the compact CSV sample](https://app.capout.ai/examples/estimate.csv) The JSON example uses fictional claim details and illustrative customer prices. It covers nine room or area labels, roof and exterior work, interior repairs, multiple activities, 29 explicit category/selector pairs, 21 exact catalog descriptions, a disabled alternate, and an F9 note. The prices are examples only; replace them with your own pricing. Put the estimate rows in the request body's `line_items` array. ## Key Principles & Pricing Policy * **Pricing:** Supplied prices are preserved as custom prices. If an item omits pricing, it is exported as an explicit custom **`$0.00`** item. CapOut never fetches external market prices or modifies customer prices. * **Catalog Resolution:** You can provide exact Xactimate Category/Selector pairs (e.g. `cat: "RFG", sel: "240"`) or an item `description`. Description-only items are resolved against the official Xactimate taxonomy. * **Dual Profiles:** Both Contractor (`8D`) and Carrier (`5L`) ESX files are automatically generated upon export. * **Enabled / Disabled Items:** Items can be flagged with `enabled: false` (or `active: 0`). Disabled items are retained in review but excluded from ESX calculations and export totals. * **Paid When Incurred:** `enabled` controls the initial eligibility of these rows too. Enabled PWI rows export as active priced items; disabled PWI rows can remain in the ESX with a paid-if-incurred flag and contribute nothing to its payable total. *** ## JSON Import (`POST /upload/json`) Submit an `application/json` payload matching the `StructuredEstimateV1` schema. ### JSON Request Example ```json theme={null} { "schema_version": "1", "file_name": "sample-multiroom-restoration.json", "estimate_name": "Sample Multiroom Restoration", "claim_number": "SAMPLE-2026-050", "line_items": [ { "id": "scope-001", "description": "Laminated - comp. shingle rfg. - w/out felt", "quantity": 24.5, "unit": "SQ", "activity": "&", "unit_price": 128.4, "room": "Main Roof", "section": "Roof covering", "enabled": true, "cat": "RFG", "sel": "300S", "f9_note": "Illustrative customer price. Replace with your own pricing before submission." }, { "id": "scope-002", "description": "Roofing felt - synthetic underlayment", "quantity": 24.5, "unit": "SQ", "activity": "+", "unit_price": 36.75, "room": "Main Roof", "section": "Roof covering", "enabled": true, "f9_note": "Exact catalog description demonstrates import without cat/sel." }, { "id": "scope-010", "description": "Gutter / downspout - aluminum - up to 5\"", "quantity": 42, "unit": "LF", "activity": "R", "unit_price": 8.25, "room": "Front Elevation", "section": "Siding and trim", "enabled": false, "f9_note": "Disabled alternate scope; retained for review but excluded from export.", "cat": "SFG", "sel": "GUTA" } ] } ``` The example includes 50 line items across nine rooms, using Cat/Sel codes, descriptions, different activities, and one disabled item. ### Upload the JSON File ```bash theme={null} curl -X POST "https://api.capout.ai/upload/json" \ -H "capout-api-key: $CAPOUT_API_KEY" \ -H "Content-Type: application/json" \ --data-binary @estimate-long.json ``` ### Test the example Generate a test API key in [CapOut Settings](https://app.capout.ai/settings/api-keys). Set `CAPOUT_API_KEY` to your `capout_test_` key and use the upload request above with the public API at `https://api.capout.ai`. ```bash theme={null} export CAPOUT_API_KEY="capout_test_your_api_key" ``` Use the returned `document_id` to [check processing status](/quickstart), then [download the ESX files](/guides/download-esx). You can also review the document in your normal CapOut dashboard. For this sample, expect 50 review rows across nine rooms, one disabled alternate, 49 active export rows, and a total of **\$29,479.35**. Compare the review rows and generated export with these expected values. ### Response (`200 OK`) ```json theme={null} { "document_id": "doc_9f8e7d6c5b4a", "status": "processing", "source_type": "JSON", "created_at": "2026-09-17T12:00:00Z", "status_url": "/status/doc_9f8e7d6c5b4a", "ws_url": "/ws/status", "download_url": "/doc_9f8e7d6c5b4a.esx", "contractor_download_url": "/doc_9f8e7d6c5b4a.esx?profile=contractor", "carrier_download_url": "/doc_9f8e7d6c5b4a.esx?profile=carrier" } ``` *** ## CSV Import (`POST /upload/csv`) Upload a CSV file as `multipart/form-data`. ### CSV Format Requirements * **Encoding:** UTF-8 (optional BOM is automatically stripped). * **Headers:** Case-insensitive, supporting canonical names or common aliases (e.g. `cat` or `category`, `qty` or `quantity`, `price` or `unit_price`). * **Booleans:** Accepts `true`/`false`, `1`/`0`, or `yes`/`no` (case-insensitive). Blank or omitted `enabled` defaults to `true`. * **Rooms:** Use the `Room` or `Area` column to group line items. If omitted, items default to `"General"`. ### Sample CSV File (`estimate.csv`) ```csv theme={null} id,cat,sel,description,quantity,unit,activity,unit_price,line_item_total,tax,overhead_profit,rcv,acv,depreciation,depreciation_applicable,depreciation_recoverable,overhead_profit_applicable,is_paid_when_incurred,enabled,room,section,f9_note roof-001,RFG,240,3-tab composition shingles,10,SQ,+,125,1250,100,250,1600,1280,320,true,true,true,false,true,Main Roof,Roof covering,"Example customer price, replace with your own pricing." roof-002,,,Drip edge - aluminum,80,LF,+,2.75,,,,,,,,,,,true,Main Roof,Edges,Description-only item for catalog resolution. roof-003,,,Roofing felt - 15 lb.,10,SQ,+,,,,,,,,,,,,true,Main Roof,Underlayment,No price supplied: exports with an explicit custom $0.00 price. roof-004,,,Drip edge - aluminum,20,LF,+,2.75,,,,,,,,,,,false,Garage Roof,Edges,Alternate scope: retained in review and excluded from export. ``` ### cURL Example ```bash theme={null} curl -X POST "https://api.capout.ai/upload/csv" \ -H "capout-api-key: $CAPOUT_API_KEY" \ -F "file=@estimate.csv;type=text/csv" ``` ### Python Example ```python theme={null} import httpx url = "https://api.capout.ai/upload/csv" headers = {"capout-api-key": "your_api_key"} with open("estimate.csv", "rb") as f: files = {"file": ("estimate.csv", f, "text/csv")} response = httpx.post(url, headers=headers, files=files) result = response.json() print("Document ID:", result["document_id"]) print("Download URL:", result["download_url"]) ``` *** ## Field Reference & Aliases | Field | Supported Aliases | Type | Description | | -------------------------- | ---------------------------------- | ------- | -------------------------------------------------------------------------------------------------------- | | `cat` | `category`, `component_code` | string | Xactimate category code (e.g. `RFG`, `DRY`, `WTR`). | | `sel` | `selector`, `selector_code` | string | Xactimate selector code (e.g. `240`, `3TAB`, `1/2`). | | `description` | `desc`, `item_description` | string | Item text description. Required if `cat` and `sel` are omitted. | | `quantity` | `qty`, `calculation`, `calc` | number | **Required:** Quantity greater than 0. | | `unit` | `uom`, `unit_of_measure` | string | Unit of measure (e.g. `SQ`, `EA`, `LF`, `SF`). | | `activity` | `action`, `act` | string | Activity code (`+`, `-`, `&`, `R`, `I`, `M`) or name (`Install`, `Remove`, `Replace`, `Detach & Reset`). | | `unit_price` | `price`, `unitprice` | number | Custom unit price. If omitted, defaults to `$0.00`. | | `tax` | `tax_amount`, `sales_tax` | number | Line-item sales tax dollar amount. | | `overhead_profit` | `o&p`, `op`, `overhead_and_profit` | number | Line-item Overhead & Profit dollar amount. | | `rcv` | `replacement_cost_value` | number | Whole-line replacement cost value. | | `acv` | `actual_cash_value` | number | Whole-line actual cash value. | | `depreciation` | `deprec`, `dep` | number | Depreciation dollar amount. | | `depreciation_recoverable` | `recoverable` | boolean | `true` for recoverable (default), `false` for non-recoverable. | | `is_paid_when_incurred` | `pwi`, `paid_when_incurred` | boolean | Flag indicating paid-when-incurred item. | | `enabled` | `active`, `is_enabled` | boolean | Set to `false` (or `0`) to retain row in review while excluding from ESX export. | | `room` | `area`, `room_name` | string | Room or area grouping (defaults to `"General"`). | | `section` | `subsection` | string | Section within room (e.g. `"Walls"`, `"Ceiling"`). | | `f9_note` | `note`, `notes` | string | Multiline F9 text note. | | `id` | `source_row_id`, `row_id` | string | Optional customer row ID, unique within the estimate. | *** ## Idempotency Support Both endpoints support the optional `Idempotency-Key` header: ```http theme={null} POST /upload/json HTTP/1.1 Host: api.capout.ai capout-api-key: Idempotency-Key: est-upload-2026-09-17-001 Content-Type: application/json ``` * If a request is retried with the **same idempotency key and identical payload**, CapOut returns the existing `document_id` and download links. * If the same key is reused with a **different payload**, CapOut returns `409 Conflict`. # Upload a Document Source: https://docs.capout.ai/guides/upload-a-document Send a document by URL or inline base64 for ESX generation and track it with the returned document ID. `POST /upload` is the entry point for generating Contractor and Carrier ESX files. 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" } ``` ### 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" } ``` ## Required fields Every upload includes `file_name`, the original filename shown in downstream responses. Exactly one of these payload fields must be present: * `url`: an immediately downloadable HTTPS PDF * `file_base64`: PDF bytes encoded as base64 * `s3_path`: a protected staged path returned by `POST /upload-url` You can supply `xn_address` and `profile_code` with your upload; CapOut records both values. Use `8D` for Contractor or `5L` for Carrier. Both ESX files are available, and the download URL's `profile` parameter selects which file to download. If multiple source fields are present, or if no source 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" }' ``` ## What to store after upload Persist at least these response fields on your side: * `document_id` * `status` * `created_at` * `status_url` * `download_url`: stable Contractor download URL and the default link * `contractor_download_url`: explicit Contractor (`8D`) link * `carrier_download_url`: explicit Carrier (`5L`) link That gives you enough to start polling immediately and to join later status changes to your own job record. The download URLs are returned while processing, but respond with `409` until export completion. Store the clean `api.capout.ai` links, not the temporary S3 URL reached after redirect. ## Use the document ID for every follow-up The JSON field is `document_id`. Use this ID for polling, realtime subscriptions, and ESX download URLs, or follow the returned `status_url` and download URLs. Internal workflow and ESX task IDs are not public tracking identifiers and are not returned in upload or export metadata. If an older integration stored `workflow_id`, migrate it to the upload response `document_id`. ## Validation and retries * Review `422` responses first when an upload is rejected. They indicate request-shape problems such as sending multiple PDF sources, sending no source, or omitting `file_name`. * 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. 5. Give the user `download_url` for Contractor or `carrier_download_url` for Carrier after the export completes, and require their client to send the same organization's `capout-api-key` when requesting it. See [Download ESX files](/guides/download-esx) for redirect, profile, and error behavior. # CapOut API Source: https://docs.capout.ai/index Upload insurance PDFs through REST or MCP, track status, stream updates, and monitor claims. CapOut gives you a straightforward API for submitting insurance PDFs, generating downloadable Contractor and Carrier ESX files, and subscribing to status changes as work completes. If you are working in Codex, Claude Code, Gemini CLI, OpenCode, GitHub Copilot CLI, or another MCP-aware client, CapOut also exposes the same workflow through the hosted MCP endpoint `https://mcp.capout.ai/mcp`. ## Base endpoints * REST: `https://api.capout.ai` * WebSocket status stream: `wss://api.capout.ai/ws/status` * SSE status stream: `https://api.capout.ai/sse/status` ## Core workflow 1. Send `capout-api-key` on REST requests. 2. Upload a PDF for ESX generation with `POST /upload`. 3. Poll `GET /status/{document_id}` or subscribe to realtime updates while the export workflow runs. 4. Download the Contractor or Carrier ESX file from the stable links returned at upload time. 5. Read claim balances with `GET /claims`. ## MCP setup For Codex, install CapOut MCP with: ```bash theme={null} codex mcp add capout --url https://mcp.capout.ai/mcp ``` CapOut's hosted MCP endpoint is: ```text theme={null} https://mcp.capout.ai/mcp ``` For copyable setup examples in Codex, `npx add-mcp`, Claude Code, Gemini CLI, OpenCode, and GitHub Copilot CLI, see [MCP Installation](/mcp/installation). ## Start here * [Quickstart](/quickstart) for the shortest end-to-end path. * [Authentication](/authentication) for API key and realtime token behavior. * [CapOut MCP](/mcp/overview) for ChatGPT, Claude, Codex, and other agent clients. * [Upload a document](/guides/upload-a-document) for request design and upload tradeoffs. * [Download ESX files](/guides/download-esx) for stable Contractor and Carrier links. * [Realtime updates](/guides/realtime-updates) for WebSocket and SSE examples. * [API reference overview](/api-reference/overview) for the full endpoint map. ## What the API covers ### Uploads Submit an insurance PDF either by passing a public `url` or by sending `file_base64`. Every accepted upload returns a `document_id` plus stable Contractor and Carrier download links that you can store immediately. CapOut generates both ESX profiles; you can supply optional `xn_address` and `profile_code` values, which CapOut records with the upload. For agent-driven workflows, the CapOut MCP can also process PDFs directly and uses a staged local upload flow for local files because the CapOut MCP is hosted remotely. ### Status tracking Use `GET /status/{document_id}` when polling a single job, or `GET /documents` when you need the authenticated organization's recent uploads and their workflow state. ### ESX downloads Request `https://api.capout.ai/{document_id}.esx` with `capout-api-key` for the Contractor (`8D`) file, or add `?profile=carrier` for Carrier (`5L`). These stable, organization-scoped links refresh the private S3 signature after authorization, so store the CapOut URL rather than the redirected storage URL. ### Realtime delivery Call `POST /ws/token` to mint a short-lived token, then connect over WebSocket or SSE using that token as a query parameter. ### Claims Use `GET /claims` to see the current organization claim balance plus any buckets that expire soon. A live Xactimate export uses 1 claim. # MCP Installation Source: https://docs.capout.ai/mcp/installation Connect CapOut MCP from Codex, Claude Code, Gemini CLI, OpenCode, GitHub Copilot CLI, and agent installers using each client's documented remote MCP setup flow. CapOut MCP is a hosted remote MCP server. Use the Streamable HTTP endpoint below, not the bare domain root: ```text theme={null} https://mcp.capout.ai/mcp ``` ## Copy to Codex Run this in your terminal to add CapOut MCP to Codex: ```bash theme={null} codex mcp add capout --url https://mcp.capout.ai/mcp ``` Codex starts the login flow automatically when the server needs authentication. Use `/mcp` inside Codex to confirm the server is connected. ## Install with `add-mcp` For clients supported by the `add-mcp` installer, this command can detect installed coding agents and configure CapOut MCP for them: ```bash theme={null} npx add-mcp --name capout --transport http https://mcp.capout.ai/mcp ``` Use `--all` to install to all detected agents, `-g` for a global install across projects, or `-y` to skip the confirmation prompt: ```bash theme={null} npx add-mcp --name capout --transport http --all -g https://mcp.capout.ai/mcp ``` ## Claude Code Anthropic documents remote HTTP MCP servers with `claude mcp add --transport http `. ```bash theme={null} claude mcp add --transport http capout https://mcp.capout.ai/mcp claude mcp list ``` If Claude Code asks you to authenticate the server, use `/mcp` inside the session and complete the sign-in flow there. ## Gemini CLI Gemini CLI documents remote HTTP MCP servers with `gemini mcp add --transport http `. ```bash theme={null} gemini mcp add --transport http capout https://mcp.capout.ai/mcp gemini mcp list ``` If Gemini marks the server as needing authentication, run this inside Gemini CLI: ```text theme={null} /mcp auth capout ``` ## OpenCode OpenCode documents remote MCP servers in `opencode.json` or `opencode.jsonc`. For a user-wide setup, put this in `~/.config/opencode/opencode.json`. For a project-only setup, put it in `opencode.json` at your project root. ```json theme={null} { "$schema": "https://opencode.ai/config.json", "mcp": { "capout": { "type": "remote", "url": "https://mcp.capout.ai/mcp", "enabled": true } } } ``` If OpenCode needs authentication, or if you want to trigger it manually: ```bash theme={null} opencode mcp auth capout opencode mcp list ``` ## GitHub Copilot CLI GitHub documents both interactive `/mcp add` setup and a non-interactive `copilot mcp add` command. The CLI reference also documents `--tools` for enabling all tools from the remote server. ```bash theme={null} copilot mcp add capout --type http --url https://mcp.capout.ai/mcp --tools "*" copilot mcp list ``` If Copilot CLI shows `needs-auth`, run this inside an interactive Copilot CLI session: ```text theme={null} /mcp auth capout ``` If you prefer config instead of a command, GitHub documents `~/.copilot/mcp-config.json`: ```json theme={null} { "mcpServers": { "capout": { "type": "http", "url": "https://mcp.capout.ai/mcp", "tools": ["*"] } } } ``` ## What the agent can do after install * Process PDFs into downloadable Xactimate ESX files * Poll export status until completion * Return stable Contractor and Carrier ESX download links * Check remaining CapOut claims * Manage legacy XactNet recipient addresses when an older workflow still needs them * Inspect and switch between live and test API keys ## How CapOut chooses the upload path CapOut MCP is hosted remotely. That means it cannot read your local `/Users/...` paths, workspace paths, or other files from your machine directly. The MCP uses different tools depending on where the PDF lives. ### Attachment, HTTPS URL, or inline bytes When the client can provide a PDF attachment, a public `https://` PDF URL, or inline base64 bytes, the agent uses `capout_process_pdf`. ### Local CLI or workspace PDF When the PDF lives on the local machine or workspace, the agent should not send a local path like `/Users/...` to the hosted server. Instead it should: 1. Call `capout_create_upload_url` 2. Run the returned `curl_command` locally 3. Call `capout_process_staged_upload` with the returned `s3_path` and `file_name` ## API key examples Use `capout_api_keys` to see the current key and any other available live or test keys. Use `capout_select_api_key` to switch when needed. Selecting a key updates which stored key is marked `mcp=true` for MCP-authenticated requests. The model does not receive raw API key values. If no CapOut API key exists yet, create one in the CapOut app: ```text theme={null} https://app.capout.ai/settings/api-keys ``` ## Starter prompts ```text theme={null} Use CapOut on this attached PDF and give me both ESX download links ``` ```text theme={null} Use CapOut on /Users/me/Downloads/estimate.pdf and give me the Contractor download ``` ```text theme={null} Show me which CapOut API key this MCP is using ``` ```text theme={null} Switch CapOut to the test API key ``` # CapOut MCP Source: https://docs.capout.ai/mcp/overview Use CapOut from ChatGPT, Claude, Codex, and other MCP-aware clients to process PDFs, track exports, and receive stable ESX download links. CapOut MCP exposes the CapOut document-processing workflow as agent tools. The CapOut MCP is hosted remotely, so local machine and workspace PDFs use the staged upload flow rather than direct filesystem reads. Use it when you want an agent to process PDFs, wait for completion, and return stable Contractor and Carrier ESX URLs with the required download-authentication guidance. ## Install CapOut MCP is exposed as a hosted Streamable HTTP endpoint. For Codex, install it with: ```bash theme={null} codex mcp add capout --url https://mcp.capout.ai/mcp ``` The endpoint is: ```text theme={null} https://mcp.capout.ai/mcp ``` For copyable setup examples in Codex, `npx add-mcp`, Claude Code, Gemini CLI, OpenCode, and GitHub Copilot CLI, see [MCP Installation](/mcp/installation). ## Tool map * `capout_process_pdf`: process one PDF from `pdf`, `url`, `file_base64`, or `file_path` * `capout_create_upload_url`: create a short-lived staged upload link for local CLI or workspace PDFs * `capout_process_staged_upload`: submit a staged local upload for processing * `capout_document_status`: get a one-shot status check for a document * `capout_wait_for_document`: wait for progress and completion inside the agent UI * `capout_claims`: inspect remaining claims * `capout_xactnet_addresses`: list legacy saved recipient addresses * `capout_create_xactnet_address`: save a legacy recipient address * `capout_update_xactnet_address_profile`: assign `profile_code` on a legacy address * `capout_delete_xactnet_address`: remove a legacy recipient address * `capout_api_keys`: list available live and test API keys * `capout_select_api_key`: switch the active API key ## Choose the right workflow * Use [Process PDFs](/mcp/tools/process-pdf) when the agent has an attachment, a public HTTPS PDF URL, or inline base64. * Use [Staged Uploads](/mcp/tools/staged-uploads) when the PDF lives on the local machine or workspace. * Processing calls accept and record optional `xn_address` and `profile_code` values. * Use [Status and Waiting](/mcp/tools/status-and-waiting) after every accepted upload until the document reaches a terminal state. * On success, the agent should give the user the stable default Contractor URL and explicit Carrier URL, explain that `capout-api-key` is required, and never put that key in either URL. ## Common prompts ```text theme={null} Use CapOut on this PDF and give me both ESX downloads ``` ```text theme={null} Show me my CapOut claims ``` ```text theme={null} List my saved XactNet addresses ``` ```text theme={null} Switch CapOut to the live API key ``` ## Next steps * [Install and authenticate](/mcp/installation) * [Process PDFs](/mcp/tools/process-pdf) * [Staged uploads](/mcp/tools/staged-uploads) # API Keys Source: https://docs.capout.ai/mcp/tools/api-keys Use capout_api_keys and capout_select_api_key to inspect or switch the active CapOut key for MCP traffic. ## capout\_api\_keys Use this tool to see which CapOut API key is currently selected for MCP traffic and any other available live or test keys. The tool does not expose raw API key values to the model. It returns selection metadata such as labels, ids, status, and whether a key is marked with `mcp=true`. ```json theme={null} { "tool": "capout_api_keys", "arguments": {} } ``` Example output: ```text theme={null} CAPOUT MCP API KEYS STATUS: 2 AVAILABLE Current Key : LIVE - Production Selection Mode : EXPLICIT (mcp=true) Execution Status : READY MCP Selection : AVAILABLE [1] LIVE - Production | CURRENT | MCP PIN ID : api_key_live Status : ACTIVE [2] TEST - Sandbox ID : api_key_test Status : ACTIVE ``` ## capout\_select\_api\_key by kind Use `key_kind=live` for live or production traffic: ```json theme={null} { "tool": "capout_select_api_key", "arguments": { "key_kind": "live" } } ``` Use `key_kind=test` for test traffic: ```json theme={null} { "tool": "capout_select_api_key", "arguments": { "key_kind": "test" } } ``` If a user says `prod` or `production`, map that to `key_kind=live`. Selecting a key does not reveal the secret API key value. It updates which stored organization key is marked `mcp=true` for future MCP-authenticated requests. ## capout\_select\_api\_key by explicit id ```json theme={null} { "tool": "capout_select_api_key", "arguments": { "api_key_id": "api_key_live" } } ``` Example result: ```text theme={null} CAPOUT MCP API KEY STATUS: UPDATED Selected Key : LIVE - Production ID : api_key_live Status : ACTIVE MCP Pin : YES ``` ## No key available yet If the organization has not created any CapOut API keys yet, create one in the CapOut app first: ```text theme={null} https://app.capout.ai/settings/api-keys ``` # Claims Source: https://docs.capout.ai/mcp/tools/claims Use capout_claims to inspect the authenticated organization's remaining CapOut claims. `capout_claims` returns the current claim balance for the active CapOut organization. One successful live document workflow spends one claim and generates both Contractor and Carrier ESX files. ## Example call ```json theme={null} { "tool": "capout_claims", "arguments": {} } ``` ## Example response ```json theme={null} { "available_claims": 42, "ok": true, "organization_id": "org_123" } ``` ## Related tool If you also need to see or switch the active CapOut API key, use [API Keys](/mcp/tools/api-keys). # Process PDFs Source: https://docs.capout.ai/mcp/tools/process-pdf Use capout_process_pdf to generate Contractor and Carrier ESX files from one PDF. `capout_process_pdf` is the primary MCP tool for single-document processing. ## Required arguments * Send exactly one of: * `pdf` * `url` * `file_base64` * `file_path` * When using `file_base64`, also send `file_name` When using `file_base64`, keep the PDF at or below `50 MiB`. You can supply optional `xn_address` and `profile_code` values; CapOut records both. CapOut generates both Contractor (`8D`) and Carrier (`5L`) files for every successful workflow. For local or workspace PDFs on a hosted MCP, use [Staged Uploads](/mcp/tools/staged-uploads), which supports PDFs up to `50 MiB`. For the public CapOut MCP, the practical inputs are `pdf`, `url`, and `file_base64`. The MCP is hosted remotely and cannot read your local machine paths directly. ## Use the right source type * Use `pdf` for ChatGPT-style file attachments that include `download_url` and `file_id` * Use `url` for a public `https://` PDF URL * Use `file_base64` when the client has bytes but not a URL and the inline payload stays within the `50 MiB` limit * Use `file_path` only for a path that already exists on the CapOut MCP server itself. Do not send your local `/Users/...` or workspace path here. CapOut MCP is hosted remotely and cannot read your local filesystem. For local workspace PDFs, use [Staged Uploads](/mcp/tools/staged-uploads). ## Example: attached PDF ```json theme={null} { "tool": "capout_process_pdf", "arguments": { "pdf": { "download_url": "https://files.chatgpt.com/file-123", "file_id": "file-123" } } } ``` ## Example: HTTPS PDF URL ```json theme={null} { "tool": "capout_process_pdf", "arguments": { "url": "https://example.com/claims/123/estimate.pdf" } } ``` ## Example: inline base64 ```json theme={null} { "tool": "capout_process_pdf", "arguments": { "file_base64": "JVBERi0xLjQKJ...", "file_name": "claim-123-estimate.pdf" } } ``` ## Successful response The MCP returns the document handoff plus stable links that can be saved immediately: ```json theme={null} { "document_id": "b9cf4ef8-9fa3-441b-b0d3-990bee7fbcce", "download_url": "https://api.capout.ai/b9cf4ef8-9fa3-441b-b0d3-990bee7fbcce.esx", "contractor_download_url": "https://api.capout.ai/b9cf4ef8-9fa3-441b-b0d3-990bee7fbcce.esx?profile=contractor", "carrier_download_url": "https://api.capout.ai/b9cf4ef8-9fa3-441b-b0d3-990bee7fbcce.esx?profile=carrier", "download_authentication": "Send your CapOut API key in the capout-api-key header when requesting an ESX URL. Never put the key in the URL or query string.", "message": "CapOut accepted the document for background processing. Keep polling until terminal is true; the download links return 409 until export completes." } ``` The returned `download_url` is the default Contractor link. The URLs stay stable and refresh their private S3 signature after an authenticated request. The key must belong to the document's organization. ## What to do next After the document is accepted, keep polling until the export reaches a terminal state: * [capout\_document\_status](/mcp/tools/status-and-waiting) * [capout\_wait\_for\_document](/mcp/tools/status-and-waiting) When the status tool reports success, return `download_url` and `carrier_download_url` with the `capout-api-key` header requirement. Do not put the key in a URL, and do not return or retain the redirected S3 URL. # Staged Uploads Source: https://docs.capout.ai/mcp/tools/staged-uploads Use capout_create_upload_url and capout_process_staged_upload for local PDFs because the CapOut MCP is hosted remotely. Use the staged upload flow for PDFs that exist on the local machine or workspace. CapOut MCP is hosted remotely, so it cannot read those files directly. This is an MCP-only workflow. It is separate from the public REST `POST /upload` API. Staged uploads support PDFs up to `50 MiB`. ## Rate limit `capout_create_upload_url` is limited to `10` signed upload URLs per minute per authenticated API key. For folder runs, batch runs, or subagent-heavy flows, create at most 10 staged upload URLs at a time before requesting more. ## Step 1: create a friendly upload URL ```json theme={null} { "tool": "capout_create_upload_url", "arguments": { "file_name": "broderick.pdf", "file_size_bytes": 271456 } } ``` Typical response: ```json theme={null} { "content_type": "application/pdf", "curl_command": "curl -X PUT -H 'content-type: application/pdf' --upload-file 'broderick.pdf' 'https://api.capout.ai/u/Shingle-Gutter-Nails-Felt-Flashing'", "expires_in_seconds": 900, "file_name": "broderick.pdf", "friendly_upload_url": "https://api.capout.ai/u/Shingle-Gutter-Nails-Felt-Flashing", "headers": { "content-type": "application/pdf" }, "method": "PUT", "next_step": "Run curl_command locally, then call capout_process_staged_upload with s3_path and file_name.", "request_id": "req_123", "s3_path": "protected/owner/pdf-intake/req_123/123-broderick.pdf" } ``` The MCP does not expose raw presigned S3 upload URLs here. It returns a short CapOut upload URL plus a ready-to-run `curl_command`. This one-time upload link is separate from the stable ESX download links returned after the staged PDF is submitted for processing. ## Step 2: upload the PDF locally Run the returned command on the same machine where the PDF exists: ```bash theme={null} curl -X PUT \ -H 'content-type: application/pdf' \ --upload-file 'broderick.pdf' \ 'https://api.capout.ai/u/Shingle-Gutter-Nails-Felt-Flashing' ``` ## Step 3: process the staged upload ```json theme={null} { "tool": "capout_process_staged_upload", "arguments": { "file_name": "broderick.pdf", "s3_path": "protected/owner/pdf-intake/req_123/123-broderick.pdf" } } ``` Successful response: ```json theme={null} { "document_id": "b9cf4ef8-9fa3-441b-b0d3-990bee7fbcce", "download_url": "https://api.capout.ai/b9cf4ef8-9fa3-441b-b0d3-990bee7fbcce.esx", "contractor_download_url": "https://api.capout.ai/b9cf4ef8-9fa3-441b-b0d3-990bee7fbcce.esx?profile=contractor", "carrier_download_url": "https://api.capout.ai/b9cf4ef8-9fa3-441b-b0d3-990bee7fbcce.esx?profile=carrier", "download_authentication": "Send your CapOut API key in the capout-api-key header when requesting an ESX URL. Never put the key in the URL or query string.", "message": "CapOut accepted the document for background processing. Keep polling until terminal is true; the download links return 409 until export completes." } ``` ## What to do next After `capout_process_staged_upload` succeeds, keep polling until completion with [Status and Waiting](/mcp/tools/status-and-waiting). You can supply optional `xn_address` and `profile_code` values; CapOut records both. Once complete, return the friendly Contractor and Carrier URLs plus their header-authentication requirement rather than the redirected S3 URL. # Status and Waiting Source: https://docs.capout.ai/mcp/tools/status-and-waiting Use capout_document_status and capout_wait_for_document to follow ESX generation until it reaches a terminal state. CapOut processing calls return quickly with a `document_id`. After that, use one of the status tools until the export is complete or failed. ## capout\_document\_status Use this for a one-shot status check. ```json theme={null} { "tool": "capout_document_status", "arguments": { "document_id": "b9cf4ef8-9fa3-441b-b0d3-990bee7fbcce" } } ``` ## capout\_wait\_for\_document Use this when you want the agent UI to wait and stream progress for a bounded window. ```json theme={null} { "tool": "capout_wait_for_document", "arguments": { "document_id": "b9cf4ef8-9fa3-441b-b0d3-990bee7fbcce", "max_wait_ms": 110000, "poll_interval_ms": 3000 } } ``` Never send `max_wait_ms` above `110000`. If one wait window ends and the document is still in progress, call `capout_wait_for_document` again immediately. ## Example output Both tools return a terminal-friendly export panel instead of raw JSON. A completed export looks like: ```text theme={null} GENERATING ESX FILES STATUS: COMPLETE Terminal : YES Workflow Complete : YES File Name : broderick.pdf Message : ESX files are ready. Contractor ESX : https://api.capout.ai/b9cf4ef8-9fa3-441b-b0d3-990bee7fbcce.esx Carrier ESX : https://api.capout.ai/b9cf4ef8-9fa3-441b-b0d3-990bee7fbcce.esx?profile=carrier Download auth : send capout-api-key with the request; never put the key in the URL. ``` The successful output uses stable CapOut links. It must not expose the temporary signed S3 URL behind either redirect or embed an API key in a link. ## Terminal state Treat the workflow as finished when the returned panel indicates a terminal result. For successful runs, expect: * `STATUS: COMPLETE` * `Terminal : YES` * `Workflow Complete : YES` * Contractor and Carrier URLs plus the `capout-api-key` header requirement An explicit `Terminal : NO` is authoritative even if an upstream stage already reports workflow completion. Keep calling one of these tools until the durable result is terminal. When it completes, give the user the friendly download URLs and authentication guidance directly; do not merely say that processing finished. # Quickstart Source: https://docs.capout.ai/quickstart Go from API key to downloadable Contractor and Carrier ESX files. If you are using ChatGPT, Claude, Codex, or another MCP-aware client, start with [CapOut MCP](/mcp/overview). This page covers the direct REST API. ## 1. Authenticate REST calls Include your API key as the `capout-api-key` header. ```bash theme={null} export CAPOUT_API_KEY="capout_test_your_api_key" ``` ## 2. Upload a document The upload API supports both a fetchable `url` and an inline `file_base64` payload. ```bash theme={null} curl https://api.capout.ai/upload \ -X POST \ -H "content-type: application/json" \ -H "capout-api-key: $CAPOUT_API_KEY" \ -d '{ "url": "https://example.com/claims/123/estimate.pdf", "file_name": "claim-123-estimate.pdf" }' ``` Inline base64 uploads use the same endpoint with a different request body: ```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": "BASE64_PDF_CONTENT", "file_name": "claim-123-estimate.pdf" }' ``` See [Upload a document](/guides/upload-a-document) for Python and Node.js examples that turn a local file into the `file_base64` value. Store the returned `document_id` and use it to track workflow completion. This is the only public tracking ID; use it in `/status/{document_id}` and `/{document_id}.esx`, or follow the returned `status_url` and download URLs: Expected shape: ```json theme={null} { "document_id": "doc_123", "status": "processing", "created_at": "2026-04-14T14:30:00Z", "status_url": "/status/doc_123", "ws_url": "/ws/status", "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" } ``` Store these clean CapOut download URLs. They are stable, even though the private S3 URL they redirect to is short-lived. Opening one before export completion returns `409`. ## 3. Poll the document status ```bash theme={null} curl https://api.capout.ai/status/doc_123 \ -H "capout-api-key: $CAPOUT_API_KEY" ``` Typical response while work is still running: ```json theme={null} { "document_id": "doc_123", "status": "processing", "workflow_complete": false, "completed_at": null, "updated_at": "2026-04-14T14:31:12Z" } ``` After a successful export, the status response includes the same links: ```json theme={null} { "document_id": "doc_123", "status": "exported", "terminal": true, "workflow_complete": true, "export": { "status": "COMPLETED", "claims_used": 1, "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" } } ``` ## 4. Download an ESX file The default link downloads the Contractor (`8D`) file. Use the Carrier link when you need the `5L` profile: ```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 download route requires the same `capout-api-key` as upload. The document must belong to that key's organization; never put the key in the URL or query string. ## 5. Switch to realtime updates Mint a short-lived token, then connect with SSE or WebSocket. ```bash theme={null} curl https://api.capout.ai/ws/token \ -X POST \ -H "capout-api-key: $CAPOUT_API_KEY" ``` Browser-friendly SSE example: ```js theme={null} const tokenResponse = await fetch("https://api.capout.ai/ws/token", { method: "POST", headers: { "capout-api-key": process.env.CAPOUT_API_KEY, }, }).then((res) => res.json()); const streamUrl = new URL(tokenResponse.sse_url, "https://api.capout.ai"); streamUrl.searchParams.set("token", tokenResponse.token); streamUrl.searchParams.append("document_id", "doc_123"); const source = new EventSource(streamUrl); source.onmessage = (event) => { console.log(JSON.parse(event.data)); }; ``` ## 6. Check remaining claims ```bash theme={null} curl https://api.capout.ai/claims \ -H "capout-api-key: $CAPOUT_API_KEY" ``` Next: * [Authentication](/authentication) * [CapOut MCP](/mcp/overview) * [Download ESX files](/guides/download-esx) * [Realtime updates](/guides/realtime-updates) * [API reference](/api-reference/overview)