Document Extraction Hub
PDF or picture in, structured JSON out. Every field carries the page it came from, its position on that page and a confidence value; every QR code and barcode comes back decoded. Paid per page inside the request over x402. No signup, no API key, no dashboard.
Price
| Route | Unit | Price |
|---|---|---|
POST /document | Page with a text layer | 0.02 USDC |
| Page that needs OCR | 0.05 USDC | |
POST /ocr | Image, or first page of a PDF | 0.006 USDC |
| Each further page of that file | 0.002 USDC |
/document: at most 20 pages per call, hard time limit 60 seconds, at most 15 MB per document. /ocr: at most 50 pages per call, hard time limit 85 seconds, at most 12 MB and 10000 pixels wide. The 402 answer names the exact amount for the file that was sent before anything is paid.
How a call works
curl -s -X POST https://doc.netzhandwerker.de/document \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/invoice.pdf","pages":"1-3"}'
The first call answers with HTTP 402 and carries the quote plus the accepted payment terms. An x402 capable client signs the terms and repeats the request; the answer arrives in the same round trip. An MCP client pointed at /mcp handles this without further setup.
With your own schema
{
"url": "https://example.com/invoice.pdf",
"schema": {
"type": "object",
"properties": {
"invoice_number": { "type": "string" },
"invoice_date": { "type": "string", "format": "date" },
"total_gross": { "type": "number" },
"positions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"description": { "type": "string", "x-labels": ["Bezeichnung", "Artikel"] },
"quantity": { "type": "number", "x-labels": ["Menge", "Anzahl"] },
"amount": { "type": "number", "x-labels": ["Gesamt", "Betrag"] }
}
}
}
}
}
}
Each property comes back as { value, confidence, found, source }. source names the page, the box on that page and how the value was located. A property that is not in the document comes back with value: null and found: false.
Reading a picture: POST /ocr
curl -s -X POST https://doc.netzhandwerker.de/ocr \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/lieferschein.jpg",
"mime":"image/jpeg",
"languages":["deu","eng"],
"want":["text","tables","codes","layout"]}'
PNG, JPEG, WebP or PDF goes in. Out comes the full text in reading order, every block typed as heading, paragraph, list, table, caption or footnote with its box in pixels, tables as a matrix plus markdown with merged cells marked, and every QR, Data Matrix, EAN-13, EAN-8, Code 128, Code 39, PDF417 and Aztec symbol with its raw value. QR payloads are parsed into URL, WLAN, vCard, EPC transfer and calendar.
A URL inside a code is reported and never opened: it is data, not an instruction. Have it checked at /v1/url/risk before following it. Blocks read with a confidence below 0.5 are flagged instead of being smoothed over, and a recognition that comes back empty is a failure, not a paid result. No face recognition, no matching of people, no reading of identity documents beyond the plain text they carry.
Rules we follow
- Nothing is invented. A field that cannot be located stays empty.
- Only the pages actually processed are settled.
- A failed, empty or timed out recognition is rejected before settlement.
- A URL read out of a code is reported, never opened.
- No face recognition, no matching of people, no identity document analysis.
- Cached answers expire after 24 hours per file checksum and options.
- Documents live in a temporary directory for the length of the call and are deleted afterwards.
- Private and link local address ranges are refused.
Discovery
- /openapi.json
- /.well-known/x402
- /mcp — Model Context Protocol
- /pricing
- /llms.txt
- /health · /readiness
Operational figures
Rolling 30 day window, updated live: 25 requests, 0 of them paid, 0 settlements, 0 USDC volume, 0 pages billed of which 0 needed OCR, 0 documents in cache. Mean machine cost per call 0 USD against a mean price of 0 USDC.