# CAD and drawing extraction

> Turn native CAD files and 2D drawings into structured, agent-readable JSON. Upload STEP, IGES, DXF, PDF, SVG, or draw.io and receive four-cad.extraction.v1: solids with topology and mass properties, drawing entities, measured dimensions, annotations, and an optional Rowe-ready point_cloud_scene.

Source: https://fourechelon.com/docs/cad-extract · Machine-readable: https://fourechelon.com/openapi.json · Index: https://fourechelon.com/llms.txt

## Formats

| Extension | Kind | Detail |
| --- | --- | --- |
| step / stp | 3D CAD | ISO 10303 STEP solids and assemblies. Preferred 3D input. |
| iges / igs | 3D CAD | IGES solids and surfaces. |
| dxf | 2D drawing | AutoCAD DXF: layers, entities, dimensions, blocks, annotations. |
| pdf | 2D drawing | Vector PDF drawings parsed into pages and entities. |
| svg | 2D drawing | SVG vector drawings parsed into entities. |
| drawio / xml | Diagram | draw.io diagrams: nodes with absolute bounding boxes, containers, directed connectors, labels, spatial relations, and a graph summary. Compressed and multi-page files are handled. |
| png / svg (draw.io export) | Diagram | A draw.io PNG or SVG exported with 'Include a copy of my diagram' carries the diagram; it is read as diagram2d, not traced. A PNG without one is a 422. |
| sldprt / sldasm | rejected (415) | SolidWorks native files are not parsed. Export as STEP and upload the .step file. |

## Request

Multipart with `file`, JSON with `file_name` + `content_base64` (bodies are capped at ~6 MB by the platform, so about 4 MB of file), or JSON with `file_name` + `content_url` for files up to 25 MB.

```bash
curl https://fourechelon.com/api/v1/cad/extract \
  -H "Authorization: Bearer $FOUR_ECHELON_API_KEY" \
  -F "file=@bracket.step" \
  -F "target_contract=both"
```

```bash
curl https://fourechelon.com/api/v1/cad/extract \
  -H "Authorization: Bearer $FOUR_ECHELON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_name": "assembly.step",
    "target_contract": "both",
    "content_url": "https://files.example.com/exports/assembly.step"
  }'
```

## Response fields

| Field | Type | Description |
| --- | --- | --- |
| schema | string | Always four-cad.extraction.v1 for successful extractions. |
| source_format | string | Detected input format (step, stp, iges, igs, dxf, pdf, svg, drawio). |
| units | string | Length unit of the extraction, for example millimeter. |
| structure.kind | string | brep for 3D solids, drawing2d for DXF/PDF/SVG drawings, diagram2d for draw.io diagrams (pages, nodes, edges, relations, graph). |
| structure.assembly / structure.solids | array | 3D topology: per-solid bbox, volume, surface_area, center_of_mass, face/edge/vertex counts, typed faces (plane, cylinder, ...), and edge_types. |
| structure.layers / structure.entities | array | 2D drawing content: layers plus typed entities (line, circle, arc, polyline, text, ...) with geometry, layer, and text. |
| structure.dimensions | array | Measured drawing dimensions: dim_type, numeric measurement, display text, and definition points. |
| structure.annotations / structure.blocks / structure.pages | array | Notes, reusable block definitions, and page structure when the source has them. |
| structure.drawing_metadata | object | DXF and PDF drawings: title_block fields (title, drawing_number, revision, material, scale, sheet, drawn_by, ...), bom rows, revisions rows, and numbered notes, each with the source annotation ids and a confidence. Read from the vector text, never OCR. Omitted when the sheet has none. |
| structure.callouts | array | DXF/PDF: engineering callouts parsed from dimension and note text — threads (M6x1.0-6H, 1/4-20 UNC-2B), holes with counterbore/countersink/spotface, ±/bilateral tolerances, ISO fits (25 H7), radii, chamfers, surface finish (Ra), reference dimensions — each with quantity, through/depth, the source text id, and position. |
| point_cloud_scene | object | Rowe-ready point_clouds[] sampled from the geometry. Present when target_contract is point_cloud_scene or both. |
| statistics | object | Converter statistics about the parsed file. |
| warnings | array | Non-fatal parse warnings. Sections that do not apply to the source format are omitted. |
| usage | object | Metered spatial tokens: input from uploaded bytes, output from the extraction JSON. |
| request_id | string | Request id for support and debugging. |

```json
{
  "schema": "four-cad.extraction.v1",
  "source_format": "dxf",
  "units": "millimeter",
  "structure": {
    "kind": "drawing2d",
    "layers": ["0", "DIMENSIONS"],
    "entities": [
      {
        "id": "e1",
        "type": "line",
        "layer": "0",
        "geometry": { "start": [0, 0], "end": [120, 0] }
      },
      {
        "id": "e2",
        "type": "circle",
        "layer": "0",
        "geometry": { "center": [60, 40], "radius": 8 }
      }
    ],
    "dimensions": [
      {
        "id": "d1",
        "dim_type": "linear",
        "measurement": 120.0,
        "text": "120",
        "defpoints": [[0, 0], [120, 0]]
      }
    ],
    "annotations": [],
    "blocks": []
  },
  "point_cloud_scene": {
    "point_clouds": [
      {
        "object_id": "drawing",
        "kind": "surface",
        "points": [{ "x": 0, "y": 0, "z": 0 }]
      }
    ]
  },
  "statistics": { "entity_count": 2, "dimension_count": 1 },
  "warnings": [],
  "file_name": "drawing.dxf",
  "target_contract": "both",
  "usage": {
    "input_tokens": 20890,
    "output_tokens": 512,
    "estimated_input_cost_usd": 0.02089,
    "estimated_output_cost_usd": 0.002048,
    "estimated_cost_usd": 0.022938
  },
  "request_id": "req_..."
}
```

## Errors

| Status | Type | Meaning |
| --- | --- | --- |
| 400 | invalid_request_error | Missing file/file_name, invalid base64 content, or invalid target_contract. |
| 401 | authentication_error | Missing, revoked, or invalid API key. |
| 402 | payment_required | An active or trialing paid API subscription is required. |
| 413 | request_too_large | The request body is over the ~6 MB platform limit (inline base64 or multipart), or the file is over 25 MB. Files above ~4 MB: send content_url instead of content_base64; the server downloads it (public http(s) only, 20 s). |
| 415 | unsupported_file_type | Format outside STEP/STP/IGES/IGS/DXF/PDF/SVG/DRAWIO/XML, including SolidWorks files (export STEP). |
| 422 | converter error (passed through) | The converter parsed the request but could not extract the file; its error body is returned unchanged. |
| 502/503 | converter_unavailable | No converter is configured or the converter cannot be reached. Non-2xx responses are never billed. |

## Batch

| Field | Type | Description |
| --- | --- | --- |
| files / items | multipart or array | 1-32 files. Multipart: repeat the `files` part (shared `target_contract` field). JSON: `items[]` of `{ file_name, content_base64, target_contract? }`, the array form of the single endpoint's body. |
| object | string | The batch envelope is cad_extract_batch. |
| id | string | Batch id (cb_...). Poll `status_url`, or GET /api/v1/cad/extract/batch/{id}, with any key on the same account. |
| status | string | queued → running → done (at least one item succeeded) or failed (every item failed). expired after `expires_at`. |
| counts | object | Per-status item counts: queued, running, succeeded, failed. |
| items[].status | string | queued, running, succeeded, or failed. Converter 5xx and transport failures are retried up to 3 times with backoff; converter 4xx fails the item immediately. |
| items[].result / result_url | object or string | The four-cad.extraction.v1 body (identical to the single endpoint) inline up to 128 KB; larger extractions set `result_url` to GET /api/v1/cad/extract/batch/{id}/items/{index}/result, which streams the stored body with the same API key. |
| items[].usage | object | Metered exactly like one POST /api/v1/cad/extract call: input from uploaded bytes, output from the extraction JSON. Only 2xx items are billed; failed items report usage but are not charged; retries never charge twice. The batch envelope itself is free. |
| usage | object | Billed totals across succeeded items (input_tokens, output_tokens, estimated_cost_usd). |
| expires_at | string | Results and staged files are deleted 24 hours after submission. |
| Idempotency-Key | header | Optional. Resubmitting the same files with the same key returns the original batch (Idempotency-Replayed: true); different files return 409. |

```bash
curl https://fourechelon.com/api/v1/cad/extract/batch \
  -H "Authorization: Bearer $FOUR_ECHELON_API_KEY" \
  -F "files=@bracket.step" \
  -F "files=@plate.dxf" \
  -F "files=@housing.step" \
  -F "target_contract=both"

# Poll until status is done or failed
curl https://fourechelon.com/api/v1/cad/extract/batch/cb_0123456789abcdef01234567 \
  -H "Authorization: Bearer $FOUR_ECHELON_API_KEY"
```

| Status | Type | Meaning |
| --- | --- | --- |
| 400 | invalid_request_error | No files, more than 32, bad base64, or an invalid target_contract. `details` names the offending item index and file_name. |
| 413 | request_too_large | A single file over 25 MB, the batch total over 25 MB, or the request body over the ~6 MB platform limit. `details` reports limit_bytes and received_bytes. |
| 415 | unsupported_file_type | Any item outside STEP/STP/IGES/IGS/DXF/PDF/SVG/DRAWIO/XML rejects the whole batch before anything is staged or charged. |
| 429 | rate_limit_exceeded | More than 5 batches queued or running, or more than 10 submitted in a minute, on one key. Per-item token charges are unaffected. |
| 404 | not_found | GET with an id that does not exist or belongs to another account. |
