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

# Structured Estimate Imports (JSON & CSV)

> 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: <your_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`.
