PDFCraft
Extraction guide

Extract a quotation PDF to JSON

Everything below is the response the live API returned for a quotation, generated when this page was built. Not a description of what it would return — the output itself, including what it scored low on.

Who this is for

Procurement and RFQ tooling comparing several suppliers’ quotes for the same basket.

The job, in the words people search for: “extract line items and validity dates from a supplier quote”.

What makes this shape awkward

The optional-extras table sits directly under the main one with the same column count, and only a slightly larger vertical gap separates them. Whether they come back as one table or two is decided entirely by the row-pitch threshold.

The measured result

Pages read1
Time9 ms (9 ms/page)
Labelled fields found unprompted5
Tables1 (7 rows)
Inputquotation.pdf (27 KB — synthetic, generated from a spec in the repo; real documents of this type cannot be published)

Fields, with a schema

Ask for the fields you want by the label printed on the page. Each answer carries the text exactly as printed (raw), the value coerced to the type you asked for, a confidence, and a bounding box you can draw on the page to check it.

curl -X POST https://api.pdfcraft.dev/v1/extract \
  -H "Authorization: Bearer $PDFCRAFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file": "<base64 of your quotation>",
    "schema": {
      "quote_number": "string",
      "issued": "date",
      "valid_until": "date",
      "quote_total": "currency"
    }
  }'

What came back

Fieldrawvalueconfidence
quote_numberQT-2026-0447"QT-2026-0447"60%
issued2026-03-05"2026-03-05"70%
valid_until2026-04-05"2026-04-05"70%
quote_totalEUR 28,410.0028410 EUR70%

Every label it found without being asked

Send no schema and you get all of these, keyed by the label as printed. Useful for discovering what a new supplier’s layout actually contains before you write a schema against it.

Quote Number, Issued, Valid Until, Lead Time, Quote Total

Tables

Item · Description · Qty · Unit price · Total · 7 rows × 5 columns · page 1

Table confidence 90%. Header confidence 100% — the first row was promoted out of the data.

ItemDescriptionQtyUnit priceTotal
1Control cabinet12120.001,440.00
2Servo drive22943.0020,746.00
3Encoder cable22347.007,634.00

First 3 of 7 rows.

With options.rows_as_objects, the same row keyed by its header:

{
  "Item": "1",
  "Description": "Control cabinet",
  "Qty": "12",
  "Unit price": "120.00",
  "Total": "1,440.00"
}

What this does not do

Try it on your own quotation

The playground takes a file and shows the same JSON, with every bounding box drawn over the page. No key and no signup for the first few; a free key gives you 100 pages a month.

Related