PDFCraft
Extraction guide

Extract a shipping manifest PDF to JSON

Everything below is the response the live API returned for a shipping manifest, 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 customs brokers keying manifests that arrive as PDF from a carrier portal.

The job, in the words people search for: “read a container manifest into a freight system”.

What makes this shape awkward

Wide table with eight columns and a page break in the middle, header repeated on the second page. The repeated header is proof the first row is a header — and it is also a row of data waiting to be filed if the stitching does not drop it.

The measured result

Pages read1
Time10 ms (10 ms/page)
Labelled fields found unprompted6
Tables1 (30 rows)
Inputshipping-manifest.pdf (33 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 shipping manifest>",
    "schema": {
      "manifest_number": "string",
      "container": "string",
      "eta": "date"
    }
  }'

What came back

Fieldrawvalueconfidence
manifest_numberMAN-2026-90114"MAN-2026-90114"60%
containerMSKU 441 7223"MSKU 441 7223"60%
eta2026-04-02"2026-04-02"70%

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.

Manifest Number, Vessel, Container, Port of Loading, Port of Discharge, ETA

Tables

Line · Marks · Packages · Description · HS code · Gross kg · Net kg · CBM · 30 rows × 8 columns · page 1

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

LineMarksPackagesDescriptionHS codeGross kgNet kgCBM
1MK-10012Machine parts8400.104303962.35
2MK-10139Textiles8401.114073741.79
3MK-10215Ceramics8402.124984581.80

First 3 of 30 rows.

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

{
  "Line": "1",
  "Marks": "MK-100",
  "Packages": "12",
  "Description": "Machine parts",
  "HS code": "8400.10",
  "Gross kg": "430",
  "Net kg": "396",
  "CBM": "2.35"
}

What this does not do

Try it on your own shipping manifest

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