Skip to content
API console (try a request with your own key)Get early access

Exports

GET /v1/extractions/{jobId}/export?format=json|csv|xlsx downloads a finished job’s values as one file. format is json when left out.

export.sh
#!/usr/bin/env bash
set -euo pipefail
API=https://api.speccapture.com
AUTH="Authorization: Bearer $SPECCAPTURE_API_KEY"
JOB_ID=7c9e6679-7425-40de-944b-e07fc1f90ae7 # the jobId the submission answered with
curl -sS --fail-with-body "$API/v1/extractions/$JOB_ID/export?format=xlsx" \
-H "$AUTH" \
-o extraction.xlsx
curl -sS --fail-with-body "$API/v1/extractions/$JOB_ID/export?format=csv" \
-H "$AUTH" \
-o extraction-csv.zip
curl -sS --fail-with-body "$API/v1/extractions/$JOB_ID/export?format=json" \
-H "$AUTH" \
-o extraction.json
echo "Saved extraction.xlsx, extraction-csv.zip and extraction.json"

Save as export.sh, set SPECCAPTURE_API_KEY, and run: bash export.sh. Needs curl; scripts also use bash and jq.

format Content type Saved as What it holds
json application/json {upload name}-extraction.json formatVersion (1), workspace, exportedAt, job - exactly what GET /v1/extractions/{jobId} answers - and sheets, each exactly what GET .../sheets/{n} answers. Indented UTF-8; ± and ° are written as themselves.
csv application/zip {upload name}-extraction-csv.zip sheets.csv (one row per sheet), one file per table type named by its path (revisionHistory.csv, bom.csv, holeTable.csv, application.csv, dashNumbers.csv) and generalNotes.csv.
xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet {upload name}-extraction.xlsx A Cover tab (workspace, job, file, template, status, engine version, export time, how to read it), Sheets, a tab per table type (named by the template: Revision History, Bill of Materials, …) and Notes.

The CSV is always a zip, even for a job whose drawings print no table: a program reading it finds the same files every time, and a table no sheet printed is a file with its heading row only. Each file is RFC 4180 (comma-separated, CRLF, a field quoted when it holds a comma, a quote or a line break) in UTF-8 with a byte-order mark, so Excel reads it as UTF-8. Times are ISO 8601 in UTC (2026-10-12T09:01:00Z).

Columns. The Sheets file and tab have Sheet, Sheet status, Sheet review, Engine version, Completed at, then every single-valued field the job’s template keeps, in its order, headed by its names (Part Number, Drawing Number, …, or the workspace’s own). A table or the notes the template leaves out has no file or tab. A table’s file and tab have Sheet, Sheet review, Row (1 for the table’s first row: the API’s rowIndex + 1), then the template’s columns. Every column is there whether or not the job has a value for it, so the files’ shape depends on the template, never on what one drawing printed; a value at a path the template does not name gets a column of its own after the template’s, headed by its path, so nothing read is ever dropped.

Every value is four columns side by side: the value as it stands (a reviewer’s correction when there is one); - as read, what the engine read, filled only beside a correction; - review (autoAccepted, needsReview, accepted, corrected); and - confidence (0 to 1; empty for a general note, which is not scored). The notes are generalNotes.csv and the Notes tab: one row per note, sheet by sheet in printed order, under Note. A value waiting for review is never exported as if it were final. In the workbook, values are always text (1:2 stays a scale, 0012 keeps its zeros, nothing is run as a formula), confidences are numbers, every tab has a frozen, filterable heading row, a value waiting for review is shaded amber and a correction blue. In the CSV a value is written exactly as the API returns it, except one a spreadsheet would run as a formula - it starts with =, @, a tab, or a sign followed by more than a number - which gets a leading apostrophe; an amount such as -, -.005 or +.002/-.000 is left alone.

Values only. A template whose exportLayout is valuesOnly - for an ERP import - has one column per field instead of four: Sheet, Sheet review, then each field under its name, then Waiting for review. A value still waiting for a person is left blank (shaded amber in the workbook) and its heading is named in Waiting for review, so nothing unchecked is imported as final; a corrected value is the correction. A table’s file is the same, row by row. No sheet is ever left out. The workbook’s cover names the template and its version.

Always current. The file says what the API says at the moment it is asked: a value a reviewer corrected after the job finished is exported corrected. Two downloads of the same values differ only in exportedAt (and the cover’s export time). Answers carry Cache-Control: no-store.

From the dashboard. A document’s Export menu offers the same three files, named for what arrives: Excel, CSV files (zip) and JSON. One difference: a JSON file downloaded there names each sheet’s resultUrl as a full address on the API (https://api.speccapture.com/v1/extractions/{jobId}/sheets/1), because a file kept away from the API has nothing to resolve a path against; the API’s own download keeps the paths its answers give.

Answer When
200 The job is completed or failed (a failed job exports its sheets with no values)
400 invalid_request format is not json, csv or xlsx
404 not_found No such job in the workspace - another workspace’s id answers the same
409 not_finished The job is queued, splitting or extracting; the problem’s jobStatus says which
501 test_mode_not_available An sc_test_ key, until test keys replay sample results