Document extraction API

PDF, scan or photo in → typed JSON out. Presets for invoices, receipts, bank statements, contracts, tables, or your own field list. Every field comes with a confidence; nothing is guessed. Try it on the demo page.

Authentication

Header X-API-Key: dx_…. Limit 500 calls per key per day. Keys are issued by the service owner.

Extract (sync)

curl -X POST https://extract.skakalkin.fyi/v1/extract -H "X-API-Key: dx_…" \
  -F "file=@invoice.pdf" -F "preset=invoice"

{"id": "job_…", "status": "done", "preset": "invoice", "pages": 1, "language": "de",
 "fields": {"supplier_name": "Muster GmbH", "invoice_number": "RE-2026-0142", "invoice_date": "2026-10-03",
            "currency": "EUR", "total": 1190.0, "items": [{"description": "Consulting", "quantity": 10, "unit_price": 100.0, "amount": 1000.0}]},
 "confidence": {"supplier_name": 0.95, "total": 0.95, "due_date": 0}, "uncertain": [], "notes": "", "ms": 6400}

Your own fields

-F "preset=generic" -F 'schema={"fields": {
  "policy_number": "insurance policy number",
  "insured": "insured person, full name",
  "valid_from": {"type": "date"}, "valid_to": {"type": "date"},
  "premium": {"type": "number", "description": "annual premium"},
  "covers": {"type": "array", "fields": {"risk": "", "limit": {"type": "number"}}}
}}' -F "hint=amounts in UAH"

Types: string (default), number, integer, date (ISO), boolean, array of flat objects. Up to 60 fields, 10 pages, 20 MB.

Async with callback (big files, batches)

-F "async=1" -F "callback_url=https://your.app/hook"
→ {"id": "job_…", "status": "queued", "pages": 8, "poll": "https://extract.skakalkin.fyi/v1/jobs/job_…"}

GET https://extract.skakalkin.fyi/v1/jobs/job_…   → the same result object when done; the callback receives it as JSON POST

Other

GET  https://extract.skakalkin.fyi/v1/presets          field lists of all presets
GET  https://extract.skakalkin.fyi/v1/jobs             your last 50 jobs
POST https://extract.skakalkin.fyi/v1/keys  (X-Admin-Key, form name=…)   issue a client key   ·   DELETE /v1/keys/{key}

Errors

CodeMeaning
401missing or revoked key
413file over the size limit
422unreadable file or invalid schema
429daily limit reached
502model error, retry

Files are not stored (only a SHA-256 of the upload and the result JSON, so a job can be polled). Stack: Python, FastAPI, OpenAI vision with strict JSON schema, PyMuPDF.