API Reference
The Deep-OCR API lets you extract structured data from any document with a single HTTP request. POST a file — optionally with a document type — and receive a typed JSON object back. No configuration, no model training, no SDKs required.
curl -X POST "https://api.deep-ocr.com/v1/ocr?document_type=invoice" \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "file=@invoice.pdf"
Authentication
All requests require an API key passed as a Bearer token in the Authorization header. You can create and manage keys in the .
Authorization: Bearer deep_ocr_sk_live_xxxxxxxxxxxxxxxxxxxx
Keep your API keys secret. Never commit them to version control. Use environment variables or a secrets manager in production.
POST /v1/ocr
The single endpoint for all document extraction. Accepts a multipart/form-data body and always returns structured JSON.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| file | binary | required | The document file. Accepted formats: PDF, PNG, JPG, JPEG, WebP, TIFF. Max 20 MB. |
| document_type | string | optional | Extraction schema to use. Omit to let the API auto-detect the type. One of: invoice, receipt, contract, id_document, delivery_note, bank_statement, payslip, purchase_order, handwriting, generic |
Code Examples
curl -X POST "https://api.deep-ocr.com/v1/ocr?document_type=invoice" \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "file=@invoice.pdf"
Document Types
Each document_type uses a pre-defined extraction schema. The returned content object always matches that schema — every field is present, unknown fields are null.
Auto-detect
Omit document_type entirely and the API will classify the document with a lightweight first pass, then apply the matching schema automatically. This adds one extra model call but removes the need to know the type upfront. The detected type is returned in document_type in the response.
Use generic if you want a flexible free-form extraction without auto-detection overhead.
invoicereceiptcontractid_documentdelivery_notebank_statementpayslippurchase_orderhandwritinggenericField Reference
Monetary values are returned as numbers (e.g. 583.10) so they can be used directly in calculations — the currency is always available separately in the currency field as an ISO 4217 code (e.g. EUR). Dates are ISO 8601 YYYY-MM-DD. Every field not found in the document is returned as null.
Invoiceinvoice
| Field | Type | Description |
|---|---|---|
| vendor.name | string | Company or person issuing the invoice |
| vendor.address | string | Full address of the vendor |
| vendor.tax_id | string | VAT / tax ID of the vendor (e.g. DE123456789) |
| vendor.email | string | Contact email of the vendor |
| vendor.phone | string | Contact phone of the vendor |
| customer.name | string | Name of the invoice recipient |
| customer.address | string | Full address of the recipient |
| customer.customer_number | string | Customer number assigned by the vendor |
| invoice_number | string | Unique invoice identifier |
| invoice_date | date | Date the invoice was issued (ISO 8601) |
| due_date | date | Payment due date |
| performance_date_from | date | Start of the service/delivery period if stated separately from the invoice date |
| performance_date_to | date | End of the service/delivery period |
| purchase_order_number | string | Buyer's PO reference number if quoted on the invoice |
| currency | string | ISO 4217 code (e.g. EUR, USD) |
| line_items[] | array | One entry per line item.{ "description": "Software License Q1/2024", "quantity": 1, "unit_price": 490.00, "total": 490.00, "tax_rate": 19 } |
| subtotal | number | Net total before tax |
| tax_breakdown[] | array | One entry per distinct VAT rate on the invoice.{ "rate": 19, "net_amount": 490.00, "tax_amount": 93.10 } |
| tax_amount | number | Total tax (sum of all tax_breakdown entries) |
| total | number | Gross total including tax |
| is_reverse_charge | bool | true if the recipient is liable for VAT instead of the vendor — common in cross-border EU B2B invoices ('reverse charge') |
| payment_terms | string | Payment conditions as written on the document (e.g. 'Net 30', '2% 10 Net 30') |
| bank_details.iban | string | IBAN for bank transfer |
| bank_details.bic | string | BIC / SWIFT code |
| bank_details.bank_name | string | Name of the bank |
| is_paid | bool | true if stamped/marked paid, false if marked unpaid, null if not indicated |
| items_truncated | bool | true if the invoice had >50 line items (only first 50 extracted) |
Receiptreceipt
| Field | Type | Description |
|---|---|---|
| merchant.name | string | Shop or business name |
| merchant.address | string | Shop address |
| merchant.phone | string | Shop phone number |
| merchant.tax_id | string | VAT / tax ID of the merchant |
| receipt_number | string | Receipt or transaction number |
| date | date | Date of purchase (ISO 8601) |
| time | string | Time of purchase in 24-hour format HH:MM |
| currency | string | ISO 4217 code |
| items[] | array | One entry per purchased item.{ "description": "Oat Milk 1L", "quantity": 2, "unit_price": 1.49, "total": 2.98, "tax_rate": 7 } |
| subtotal | number | Net total before tax |
| tax_breakdown[] | array | One entry per distinct VAT rate on the receipt. German receipts often show both 7 % and 19 %.{ "rate": 7, "net_amount": 2.80, "tax_amount": 0.20 } |
| tax_amount | number | Total tax amount |
| total | number | Amount paid including tax |
| payment_method | string | One of: cash, credit_card, debit_card, mobile_payment, check, gift_card, store_credit, other |
| card_last_four | string | Last 4 digits of the card used as a string (e.g. '4242'), never asterisks |
| cashier | string | Name or ID of the cashier if shown |
| notes | string | Any additional notes or remarks printed on the receipt |
Contractcontract
| Field | Type | Description |
|---|---|---|
| title | string | Title or heading of the contract |
| contract_number | string | Contract reference number if present |
| parties[] | array | One entry per contracting party.{ "role": "service_provider", "name": "ACME Ltd.", "address": "123 Main St, London EC1A 1BB", "representative": "Jane Smith" } |
| parties[].role | string | One of: buyer, seller, service_provider, service_recipient, lessor, lessee, employer, employee, licensor, licensee, other |
| parties[].name | string | Full legal name of the party |
| parties[].address | string | Address of the party |
| parties[].representative | string | Name of the person signing on behalf of the party |
| effective_date | date | Date the contract enters into force |
| expiry_date | date | End date; null for perpetual or indefinite contracts |
| termination_notice_days | number | Required notice period in days to terminate (longest value if multiple apply) |
| governing_law | string | ISO 3166-1 alpha-3 country code (e.g. DEU) or country name as written |
| subject_matter | string | One-sentence summary of what the contract is about (max 30 words) |
| key_obligations | string[] | Up to 5 concrete obligations as short strings (max 15 words each).["Provide IT consulting services 40 hours per week", "Pay monthly fee of €5,000 by the 15th"] |
| payment_terms | string | Payment schedule or conditions |
| contract_value | number | Total monetary value of the contract |
| currency | string | ISO 4217 code |
| signatures[] | array | One entry per signature block.{ "party": "ACME GmbH", "signed_date": "2024-01-15", "signed_by": "Max Müller" } |
| signatures[].party | string | Name of the signing party |
| signatures[].signed_date | date | Date of signature |
| signatures[].signed_by | string | Name of the individual who signed |
| notes | string | Additional observations or remarks about the contract |
ID Documentid_document
| Field | Type | Description |
|---|---|---|
| id_type | string | One of: passport, national_id, id_card, driver_license, residence_permit, travel_document, other |
| issuing_country | string | ISO 3166-1 alpha-3 code (e.g. DEU, AUT, CHE) |
| issuing_authority | string | Authority that issued the document |
| document_number | string | Document number exactly as printed |
| surname | string | Family name |
| given_names | string | Given name(s) |
| date_of_birth | date | Date of birth (ISO 8601) |
| nationality | string | Nationality as printed on the document |
| gender | string | M or F; null for X / Divers / non-binary |
| place_of_birth | string | Place of birth if shown |
| issue_date | date | Date of issue |
| expiry_date | date | Expiry date; null if the document has no expiry |
| mrz_line1 | string | First machine-readable zone line, copied character-for-character (typically 44 chars) |
| mrz_line2 | string | Second machine-readable zone line |
Delivery Notedelivery_note
| Field | Type | Description |
|---|---|---|
| delivery_note_number | string | Delivery note reference number |
| order_number | string | Corresponding purchase or sales order number |
| delivery_date | date | Date of delivery (ISO 8601) |
| sender.name | string | Sending company or person |
| sender.address | string | Full address of the sender |
| sender.contact | string | Contact person or department at the sender |
| recipient.name | string | Receiving company or person |
| recipient.address | string | Delivery address |
| recipient.contact | string | Contact person or department at the recipient |
| carrier | string | Shipping carrier (e.g. DHL, UPS) |
| tracking_number | string | Shipment tracking number, copied exactly as printed |
| items[].description | string | Description of the delivered item |
| items[].article_number | string | Article / SKU number |
| items[].quantity_ordered | number | Originally ordered quantity (null if not shown) |
| items[].quantity_delivered | number | Actually delivered quantity |
| items[].unit | string | Unit of measurement as written (e.g. pcs, Stück, kg) |
| total_packages | number | Total number of packages |
| total_weight_kg | number | Total shipment weight in kg (converted from lbs if needed) |
| is_partial_delivery | bool | true if explicitly marked as a partial shipment, false if marked as complete, null if not stated |
| delivery_sequence | string | Shipment sequence if shown (e.g. '1/3' for first of three) |
| notes | string | Additional remarks or instructions on the delivery note |
Bank Statementbank_statement
| Field | Type | Description |
|---|---|---|
| account_holder | string | Name of the account holder |
| account_number | string | Account number as printed |
| iban | string | IBAN |
| bic | string | BIC / SWIFT code |
| bank_name | string | Name of the bank |
| statement_date | date | Date the statement was generated |
| period_from | date | Start of the statement period |
| period_to | date | End of the statement period |
| currency | string | ISO 4217 code |
| opening_balance | number | Account balance at the start of the period |
| closing_balance | number | Account balance at the end of the period |
| transactions[] | array | One entry per transaction. Statements with more than 100 transactions: only the first 100 are extracted.{ "date": "2024-03-15", "value_date": "2024-03-15", "description": "Direct debit rent March", "reference": "INV-2024-03", "amount": -950.00, "type": "debit", "balance": 2340.12 } |
| transactions[].date | date | Booking date |
| transactions[].value_date | date | Value date — the date the amount actually affects the balance |
| transactions[].description | string | Full transaction description / purpose text |
| transactions[].reference | string | Transaction reference or booking text |
| transactions[].amount | number | Positive for credits (money in), negative for debits (money out) |
| transactions[].type | string | 'credit' if amount is positive, 'debit' if negative |
| transactions[].balance | number | Running account balance after this transaction, if shown |
Payslippayslip
| Field | Type | Description |
|---|---|---|
| employer.name | string | Employer company name |
| employer.address | string | Employer address |
| employer.tax_id | string | Employer tax ID |
| employee.name | string | Employee full name |
| employee.employee_number | string | Internal employee number |
| employee.tax_id | string | Employee tax identification number (TIN) |
| employee.social_security_number | string | Social security / national insurance number |
| employee.iban | string | IBAN of the employee's bank account for salary payment |
| period_from | date | Start of the pay period |
| period_to | date | End of the pay period |
| payment_date | date | Date the salary was / will be paid |
| currency | string | ISO 4217 code |
| earnings[] | array | Each positive pay component (base salary, bonuses, allowances, overtime, etc.).{ "description": "Base salary", "amount": 3500.00 } |
| deductions[] | array | Each amount subtracted (income tax, social security, pension, etc.). Amount is always a positive number.{ "description": "Income tax", "amount": 650.00 } |
| gross_salary | number | Total gross pay before any deductions |
| net_salary | number | Take-home pay after all deductions |
| tax_amount | number | Income tax portion of deductions if shown separately |
| social_security_amount | number | Total social security / national insurance contributions |
| notes | string | Additional remarks on the payslip |
Purchase Orderpurchase_order
| Field | Type | Description |
|---|---|---|
| po_number | string | Purchase order number |
| order_date | date | Date the order was placed |
| delivery_date_requested | date | Requested delivery date |
| buyer.name | string | Company or person placing the order |
| buyer.address | string | Buyer's address |
| buyer.contact | string | Buyer contact person or department |
| buyer.tax_id | string | Buyer's VAT / tax ID |
| supplier.name | string | Company or person receiving the order |
| supplier.address | string | Supplier's address |
| supplier.contact | string | Supplier contact person |
| supplier.tax_id | string | Supplier's VAT / tax ID |
| delivery_address | string | Delivery address if different from buyer address |
| currency | string | ISO 4217 code |
| line_items[] | array | One entry per ordered item.{ "position": 1, "description": "Laptop Dell XPS 15", "article_number": "DEL-XPS-15", "quantity": 2, "unit": "pcs", "unit_price": 1200.00, "total": 2400.00, "tax_rate": 19 } |
| line_items[].position | number | Line item position number (1, 2, 3, …) |
| line_items[].description | string | Description of the ordered item |
| line_items[].article_number | string | Article / SKU number |
| line_items[].quantity | number | Ordered quantity |
| line_items[].unit | string | Unit of measurement as written (e.g. pcs, Stück, kg) |
| line_items[].unit_price | number | Price per unit (net) |
| line_items[].total | number | Line total (net) |
| line_items[].tax_rate | number | VAT rate as a percentage (e.g. 19) |
| subtotal | number | Net total before tax |
| tax_amount | number | Total tax amount |
| total | number | Gross total including tax |
| payment_terms | string | Payment conditions |
| notes | string | Additional remarks or terms printed on the purchase order |
| items_truncated | bool | true if the PO had >50 line items (only first 50 extracted) |
Handwritinghandwriting
| Field | Type | Description |
|---|---|---|
| transcription | string | Full transcribed text. Unclear words marked with [?] (e.g. meetng[?]), single unclear characters as w[?]rd, illegible sections as [illegible – 2 lines] |
| confidence | string | Overall readability: 'high' (>90% clearly readable), 'medium' (50–90%), 'low' (<50%) |
| language | string | ISO 639-1 language code of the primary language (e.g. de, en, fr) |
| notes | string | Observations such as mixed print/cursive, multiple writing styles, or damage |
Genericgeneric
| Field | Type | Description |
|---|---|---|
| document_type | string | Model's best-guess label for the specific document kind (e.g. 'form', 'letter', 'report') — more specific than the top-level 'generic' |
| title | string | Document title or heading |
| date | date | Primary date found on the document |
| content | object | All extracted fields as a nested JSON object — structure adapts to the document. May contain tables (array of row objects), lists (array of strings), and any other relevant fields. |
Response Format
Every successful response is HTTP 200 with a JSON body. The top-level envelope is consistent across all document types.
| Field | Type | Description |
|---|---|---|
| filename | string | The sanitised name of the uploaded file. |
| document_type | string | The document_type value you passed in. |
| content | object | The extracted data — structure depends on document_type. |
| metadata.pages | number | Number of pages processed (PDF). |
| metadata.processing_time | number | End-to-end processing time in seconds. |
Example — Invoice Response
{
"filename": "invoice.pdf",
"document_type": "invoice",
"content": {
"vendor": {
"name": "ACME Solutions GmbH",
"address": "123 Example Street, 10115 Berlin",
"tax_id": "DE123456789",
"email": "billing@acme.de",
"phone": null
},
"customer": {
"name": "Your Company Ltd.",
"address": "42 High Street, 20354 Hamburg",
"customer_number": "CUS-0042"
},
"invoice_number": "RE-2024-0815",
"invoice_date": "2024-03-01",
"due_date": "2024-03-31",
"currency": "EUR",
"line_items": [
{
"description": "Software License Q1/2024",
"quantity": 1,
"unit_price": 490.00,
"total": 490.00,
"tax_rate": 19
}
],
"subtotal": 490.00,
"tax_breakdown": [
{ "rate": 19, "net_amount": 490.00, "tax_amount": 93.10 }
],
"tax_amount": 93.10,
"total": 583.10,
"is_reverse_charge": false,
"payment_terms": "14 days net",
"bank_details": {
"iban": "DE89370400440532013000",
"bic": "COBADEFFXXX",
"bank_name": "Commerzbank"
},
"is_paid": false,
"notes": null,
"items_truncated": false
},
"metadata": {
"pages": 1,
"processing_time": 1.84
}
}Error Codes
Error responses follow a consistent shape: { "detail": "Human-readable message" }
Rate Limits
Rate limits are enforced per API key. Exceeding the limit returns HTTP 429. Limits reset every minute.
| Plan | Requests / minute | Pages / month |
|---|---|---|
| Free Trial | 10 | 100 |
| Starter | 30 | 200 |
| Pro | 60 | 1,000 |
| Business | 120 | 5,000 |
Integrations
Use Deep-OCR with the tools you already know — from no-code automation to AI-assisted development.
n8n Community Node
Process documents inside n8n workflows without writing any code. Install the official community node:
Available on npmjs.com/package/n8n-nodes-deep-ocr
Postman Collection
Download the official Postman collection to explore and test every endpoint without writing any code. Includes pre-configured auth and example responses for all supported document types.
AI-ready — Vibe-code friendly
Building with Claude Code, Cursor, GitHub Copilot, or another AI assistant? We publish a machine-readable API summary at /llms.txt — a concise Markdown file containing everything your AI assistant needs to write a correct integration from scratch.
Paste into your AI assistant to get started instantly:
"Read https://deep-ocr.com/llms.txt and integrate Deep-OCR into my project"
The /llms.txt file follows the emerging llms.txt convention — a lightweight standard for making APIs and documentation easy for AI tools to consume.
Ready to start building?
Create a free account, grab your API key, and make your first request in under 5 minutes.
100 pages free · No credit card required