One endpoint that reads any business document — invoices, contracts, registration forms — and returns structured, semantic JSON. No templates to configure, no fields to map.
Every request carries your organisation's API key in the x-api-key header. Your organisation has one key; owners and admins can view (masked) and rotate it any time at app.blueport.io → PDF2JSON → API key. Rotation invalidates the old key immediately — treat the key as a secret, keep it server-side, never ship it in a browser or mobile app.
Send the PDF either way — or import the ready-made
Postman collection
(File → Import → paste the URL, then set the apiKey variable):
Raw binary — simplest, no encoding step:
curl -X POST https://pdf.blueport.io/pdf2json \ -H "x-api-key: YOUR_API_KEY" \ -H "content-type: application/pdf" \ --data-binary @invoice.pdf
JSON body — when the PDF is already in memory:
// Node.js const pdf = fs.readFileSync("invoice.pdf") .toString("base64"); const r = await fetch( "https://pdf.blueport.io/pdf2json", { method: "POST", headers: { "x-api-key": process.env.PDF2JSON_KEY, "content-type": "application/json", }, body: JSON.stringify({ pdf }), }); const { ok, data } = await r.json();
The data object is the document, understood: a documentType, then logical entity groups with camelCase keys, ISO dates, and real JSON numbers for money. The shape follows the document — an invoice yields dealer/customer/vehicle/pricing groups, a registration form yields its own sections.
{
"ok": true,
"data": {
"documentType": "TAX INVOICE",
"pages": 2,
"currency": "AUD",
"dealer": { "name": "Example Motors Pty Ltd", "abn": "12 345 678 901", … },
"invoice": { "invoiceNo": "10023456", "date": "2026-08-01", … },
"vehicle": { "vin": "6XY12345678900123", "odometer": 1, … },
"pricing": { … }
},
"meta": { "request_id": "req_a1b2c3", "duration_ms": 17000 }
}
meta.request_id in any support conversation — it identifies the exact request in our logs (the document itself is never stored).| Status | Meaning | What to do |
|---|---|---|
| 401 | Missing or invalid API key | Check the header name and value; confirm the key wasn't rotated |
| 400 | Body isn't a PDF / no PDF found | Send raw with content-type: application/pdf or JSON {"pdf": "<base64>"} |
| 413 | PDF over 8 MB | Compress or split the document |
| 422 | Extraction declined | The document was rejected by content safety — contact support with the request_id |
| 502 | Extraction returned unusable output | Rare and transient — retry once |
| 500 | Service error | Retry with backoff; persistent failures → support |
• Latency: extraction is synchronous and typically 10–25 seconds per document — set your HTTP client timeout to 120 s and call it from a background job, not a user-facing request.
• Retries: safe to retry on 5xx; every successful call counts one document against your plan.
• Usage: your document count and history are on your dashboard at app.blueport.io; you'll be notified as you approach your monthly allowance.
• Privacy: documents are processed in-flight and never persisted — only usage counts and timings are recorded.