Browse all documentation

POST /API/V1/CAD/EXTRACT

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.

POST /api/v1/cad/extract

Authenticate with your API key, upload a file up to 25 MB, and pick a target_contract: structured (default) for the agent-readable extraction, point_cloud_scene for Rowe-ready geometry, or both. The endpoint accepts multipart uploads and JSON with base64 content.

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

The same request as JSON with base64-encoded content:

Terminal
$ curl https://fourechelon.com/api/v1/cad/extract \
-H "Authorization: Bearer $FOUR_ECHELON_API_KEY" \
-H "Content-Type: application/json" \
-d "{
$ \"file_name\": \"drawing.dxf\",
$ \"target_contract\": \"structured\",
$ \"content_base64\": \"$(base64 -i drawing.dxf | tr -d '\n')\"
$ }"

Request bodies are capped at about 6 MB by the hosting platform, so inline uploads (multipart or base64) work up to roughly 4 MB of file. For larger files, up to 25 MB, send a public content_url instead and the server downloads it (http(s) only, 20 s; private and loopback hosts are refused):

Terminal
$ 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 schema

Successful extractions return four-cad.extraction.v1. 3D sources fill structure.solids with topology and mass properties; 2D drawings fill structure.entities and structure.dimensions. Sections that do not apply to the source are omitted.

schemastring

Always four-cad.extraction.v1 for successful extractions.

source_formatstring

Detected input format (step, stp, iges, igs, dxf, pdf, svg, drawio).

unitsstring

Length unit of the extraction, for example millimeter.

structure.kindstring

brep for 3D solids, drawing2d for DXF/PDF/SVG drawings, diagram2d for draw.io diagrams (pages, nodes, edges, relations, graph).

structure.assembly / structure.solidsarray

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

2D drawing content: layers plus typed entities (line, circle, arc, polyline, text, ...) with geometry, layer, and text.

structure.dimensionsarray

Measured drawing dimensions: dim_type, numeric measurement, display text, and definition points.

structure.annotations / structure.blocks / structure.pagesarray

Notes, reusable block definitions, and page structure when the source has them.

structure.drawing_metadataobject

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

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_sceneobject

Rowe-ready point_clouds[] sampled from the geometry. Present when target_contract is point_cloud_scene or both.

statisticsobject

Converter statistics about the parsed file.

warningsarray

Non-fatal parse warnings. Sections that do not apply to the source format are omitted.

usageobject

Metered spatial tokens: input from uploaded bytes, output from the extraction JSON.

request_idstring

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_..."
}

Supported formats

step / stp3D CAD

ISO 10303 STEP solids and assemblies. Preferred 3D input.

iges / igs3D CAD

IGES solids and surfaces.

dxf2D drawing

AutoCAD DXF: layers, entities, dimensions, blocks, annotations.

pdf2D drawing

Vector PDF drawings parsed into pages and entities.

svg2D drawing

SVG vector drawings parsed into entities.

drawio / xmlDiagram

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 / sldasmrejected (415)

SolidWorks native files are not parsed. Export as STEP and upload the .step file.

Errors and pricing

Extraction is metered like every Rowe request: uploaded bytes count as input spatial tokens and the extraction JSON counts as output spatial tokens at the standard token rates. Only 2xx extractions are billed; converter and validation failures are recorded but never charged.

400invalid_request_error

Missing file/file_name, invalid base64 content, or invalid target_contract.

401authentication_error

Missing, revoked, or invalid API key.

402payment_required

An active or trialing paid API subscription is required.

413request_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).

415unsupported_file_type

Format outside STEP/STP/IGES/IGS/DXF/PDF/SVG/DRAWIO/XML, including SolidWorks files (export STEP).

422converter error (passed through)

The converter parsed the request but could not extract the file; its error body is returned unchanged.

502/503converter_unavailable

No converter is configured or the converter cannot be reached. Non-2xx responses are never billed.

Batch extraction: POST /api/v1/cad/extract/batch

Submit 1-32 files in one request (25 MB per file, 25 MB total) and get a 202 Accepted with a batch id. Extraction runs in the background; poll status_url until status is done or failed. Each item is authorized, extracted, and metered exactly like one call to /api/v1/cad/extract: same converter, same token counts, same 2xx-only billing, and at most 5 batches queued or running per key.

POST → https://fourechelon.com/api/v1/cad/extract/batch
Terminal
$ 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"

The 202 response:

JSON
HTTP/1.1 202 Accepted
Location: https://fourechelon.com/api/v1/cad/extract/batch/cb_0123456789abcdef01234567
{
"object": "cad_extract_batch",
"id": "cb_0123456789abcdef01234567",
"status": "queued",
"item_count": 3,
"counts": { "queued": 3, "running": 0, "succeeded": 0, "failed": 0 },
"usage": { "input_tokens": 0, "output_tokens": 0, "estimated_cost_usd": 0 },
"status_url": "https://fourechelon.com/api/v1/cad/extract/batch/cb_0123456789abcdef01234567",
"created_at": "2026-09-02T18:04:11.000Z",
"started_at": null,
"completed_at": null,
"expires_at": "2026-09-03T18:04:11.000Z",
"items": [
{ "index": 0, "file_name": "bracket.step", "source_format": "step", "target_contract": "both", "status": "queued", "status_code": null, "request_id": null, "attempts": 0, "result": null, "result_url": null, "result_bytes": null, "error": null, "usage": null, "started_at": null, "completed_at": null },
{ "index": 1, "file_name": "plate.dxf", "source_format": "dxf", "target_contract": "both", "status": "queued", "status_code": null, "request_id": null, "attempts": 0, "result": null, "result_url": null, "result_bytes": null, "error": null, "usage": null, "started_at": null, "completed_at": null },
{ "index": 2, "file_name": "housing.step", "source_format": "step", "target_contract": "both", "status": "queued", "status_code": null, "request_id": null, "attempts": 0, "result": null, "result_url": null, "result_bytes": null, "error": null, "usage": null, "started_at": null, "completed_at": null }
],
"request_id": "req_..."
}

Batch status: GET /api/v1/cad/extract/batch/{id}

Returns the aggregate status plus every item in submission order. Small results are inline under result; results over 128 KB are served from result_url instead, which is an authenticated GET on the same key (no public storage links). Results are kept until expires_at (24 hours).

files / itemsmultipart 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.

objectstring

The batch envelope is cad_extract_batch.

idstring

Batch id (cb_...). Poll `status_url`, or GET /api/v1/cad/extract/batch/{id}, with any key on the same account.

statusstring

queued → running → done (at least one item succeeded) or failed (every item failed). expired after `expires_at`.

countsobject

Per-status item counts: queued, running, succeeded, failed.

items[].statusstring

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_urlobject 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[].usageobject

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.

usageobject

Billed totals across succeeded items (input_tokens, output_tokens, estimated_cost_usd).

expires_atstring

Results and staged files are deleted 24 hours after submission.

Idempotency-Keyheader

Optional. Resubmitting the same files with the same key returns the original batch (Idempotency-Replayed: true); different files return 409.

JSON
{
"object": "cad_extract_batch",
"id": "cb_0123456789abcdef01234567",
"status": "done",
"item_count": 3,
"counts": { "queued": 0, "running": 0, "succeeded": 2, "failed": 1 },
"usage": { "input_tokens": 31204, "output_tokens": 1810, "estimated_cost_usd": 0.19222 },
"status_url": "https://fourechelon.com/api/v1/cad/extract/batch/cb_0123456789abcdef01234567",
"created_at": "2026-09-02T18:04:11.000Z",
"started_at": "2026-09-02T18:04:12.000Z",
"completed_at": "2026-09-02T18:04:39.000Z",
"expires_at": "2026-09-03T18:04:11.000Z",
"items": [
{
"index": 0,
"file_name": "bracket.step",
"source_format": "step",
"target_contract": "both",
"status": "succeeded",
"status_code": 200,
"request_id": "req_item0...",
"attempts": 1,
"result": {
"schema": "four-cad.extraction.v1",
"source_format": "step",
"units": "millimeter",
"structure": { "kind": "brep", "solids": [{ "id": "s1", "volume": 1350.2 }] },
"point_cloud_scene": { "point_clouds": [{ "object_id": "s1", "kind": "surface", "points": [{ "x": 0, "y": 0, "z": 0 }] }] },
"statistics": { "solid_count": 1 },
"warnings": [],
"file_name": "bracket.step",
"target_contract": "both",
"usage": { "input_tokens": 20890, "output_tokens": 1298, "estimated_input_cost_usd": 0.10445, "estimated_output_cost_usd": 0.02596, "estimated_cost_usd": 0.13041 },
"request_id": "req_item0..."
},
"result_url": null,
"result_bytes": 4812,
"error": null,
"usage": { "input_tokens": 20890, "output_tokens": 1298, "estimated_cost_usd": 0.13041 },
"started_at": "2026-09-02T18:04:12.000Z",
"completed_at": "2026-09-02T18:04:21.000Z"
},
{
"index": 1,
"file_name": "plate.dxf",
"source_format": "dxf",
"target_contract": "both",
"status": "succeeded",
"status_code": 200,
"request_id": "req_item1...",
"attempts": 1,
"result": null,
"result_url": "https://fourechelon.com/api/v1/cad/extract/batch/cb_0123456789abcdef01234567/items/1/result",
"result_bytes": 913442,
"error": null,
"usage": { "input_tokens": 10314, "output_tokens": 512, "estimated_cost_usd": 0.06181 },
"started_at": "2026-09-02T18:04:12.000Z",
"completed_at": "2026-09-02T18:04:30.000Z"
},
{
"index": 2,
"file_name": "housing.step",
"source_format": "step",
"target_contract": "both",
"status": "failed",
"status_code": 422,
"request_id": "req_item2...",
"attempts": 1,
"result": { "error": { "message": "STEP entity graph is truncated.", "type": "extraction_error" }, "file_name": "housing.step", "target_contract": "both", "request_id": "req_item2...", "usage": { "input_tokens": 15020, "output_tokens": 43, "estimated_input_cost_usd": 0.0751, "estimated_output_cost_usd": 0.00086, "estimated_cost_usd": 0.07596 } },
"result_url": null,
"result_bytes": 268,
"error": { "message": "STEP entity graph is truncated.", "type": "extraction_error" },
"usage": { "input_tokens": 15020, "output_tokens": 43, "estimated_cost_usd": 0.07596 },
"started_at": "2026-09-02T18:04:21.000Z",
"completed_at": "2026-09-02T18:04:39.000Z"
}
],
"request_id": "req_..."
}

Batch-specific errors (per-file validation errors match the single endpoint and reject the whole batch before anything is staged):

400invalid_request_error

No files, more than 32, bad base64, or an invalid target_contract. `details` names the offending item index and file_name.

413request_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.

415unsupported_file_type

Any item outside STEP/STP/IGES/IGS/DXF/PDF/SVG/DRAWIO/XML rejects the whole batch before anything is staged or charged.

429rate_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.

404not_found

GET with an id that does not exist or belongs to another account.