PDFCraft
Extraction guide

Extract a bill of lading PDF to JSON

Everything below is the response the live API returned for a bill of lading, 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

Freight forwarders and TMS vendors replacing manual keying at the point a shipment is booked.

The job, in the words people search for: “digitise bills of lading”.

What makes this shape awkward

Dense boxed form with a great many short labelled fields and one small commodity table. The boxes are drawn with ruling lines that produce no text at all, so the geometry has to work entirely from whitespace.

The measured result

Pages read1
Time9 ms (9 ms/page)
Labelled fields found unprompted7
Tables1 (6 rows)
Inputbill-of-lading.pdf (31 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 bill of lading>",
    "schema": {
      "bol_number": "string",
      "ship_date": "date",
      "total_weight": "string"
    }
  }'

What came back

Fieldrawvalueconfidence
bol_numberBOL-2026-11884"BOL-2026-11884"60%
ship_date2026-03-11"2026-03-11"70%
total_weight2,144 kg"2,144 kg"60%

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.

BOL Number, Ship Date, Shipper, Consignee, Carrier, Freight Terms, Total Weight

Tables

Pieces · Package type · Description · Weight (kg) · Class · 6 rows × 5 columns · page 1

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

PiecesPackage typeDescriptionWeight (kg)Class
6PalletMachine parts43670
4CrateHydraulic fluid63085
14CartonSpare motors18792.5

First 3 of 6 rows.

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

{
  "Pieces": "6",
  "Package type": "Pallet",
  "Description": "Machine parts",
  "Weight (kg)": "436",
  "Class": "70"
}

What this does not do

Try it on your own bill of lading

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