API Documentation

Quickstart

Upload an invoice, get a request ID, then poll for results. Your API key determines which add-ons are enabled.

1. Upload Invoice

curl -X POST https://invoicesengine.com/invoice-api/v3.0/extract?pretty=1 \
-H 'Authorization: Bearer YOUR_API_KEY' \
-F 'file=@/path/to/invoice.pdf'

Example Response:

{
  "status": "queued",
  "request_id": "inv_12345"
}

Tip: append ?pretty=1 to pretty-print JSON.

2. Check Status

curl -X GET https://invoicesengine.com/invoice-api/v3.0/result/inv_12345?pretty=1 \
-H 'Authorization: Bearer YOUR_API_KEY'

Example (pending):

{
  "status": "queued"
}

Example (completed):

{
  "status": "success",
  "data": {
    "InvoiceNumber": "INV-2025-0456",
    "InvoiceType": "invoice",
    "InvoiceDate": "2025-08-15",
    "TaxPointDate": null,
    "DueDate": "2025-09-15",
    "Currency": "EUR",
    "SupplierTaxId": "123456",
    "SupplierVatNumber": "DE123456789",
    "CustomerVatNumber": "FR987654321",
    "SupplierName": "Example Consulting GmbH",
    "CustomerName": "Acme Industries SA",
    "SupplierCountryCode": "DE",
    "CustomerCountryCode": "FR",
    "TotalAmountExclTax": 500.00,
    "TotalVATAmount": 105.00,
    "TotalAmountIncTax": 605.00,
    "RoundingAmount": null,
    "AmountDue": 605.00,
    "IsPaid": null,
    "PaymentStatusText": null,
    "IsReverseCharged": null,
    "IsSelfBilling": null,
    "PurchaseOrderNumber": null,
    "CustomerReference": null,
    "OriginalInvoiceNumber": null,
    "PaymentMethod": null
  },
  "warnings": [],
  "errors": []
}

Use the warnings array to flag data for manual review. If parsing fails, data may be null and explanations appear in errors.

Example (delivered with warnings):

{
  "status": "succeeded",
  "request_id": "inv_12345",
  "data": { ... },
  "warnings": [
    "Totals mismatch: Excl+VAT+Rounding=606.00 vs Inc=605.00 (Δ=+1.00).",
    "DueDate 2025-08-10 is earlier than InvoiceDate 2025-08-15."
  ],
  "errors": []
}

In this case the request succeeded, but warnings were returned. These warnings are useful for afterwards checks to detect possible inconsistencies or mistakes made by the API, while still providing the parsed data.

Example (early rejection):

{
  "status": "error",
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or missing API key."
  }
}

Polling must use the same API key that created the request.

Base URL & Versioning

All endpoints are served under a single versioned base URL. Versioning is path-based (e.g. /v3.0), so new breaking releases ship under a new path.

Current Base URL

https://invoicesengine.com/invoice-api/v3.0

Building Endpoint URLs


// Base URL for all endpoints
EXTRACTOR_BASE = "https://cronengine.com/invoice-api/v3.0"

// Upload (POST /extract)
EXTRACTOR_BASE + /extract

// Poll (GET /result/{request_id})
EXTRACTOR_BASE + /result/{request_id}

// Optional pretty printing for debugging
EXTRACTOR_BASE + /extract?pretty=1
EXTRACTOR_BASE + /result/{request_id}?pretty=1
            

Endpoints (at a glance)

Method Path Description
POST /extract Upload an invoice file and receive a request_id.
GET /result/{request_id} Poll for processing status and extract results.

Full request/response details are covered in the next sections.

Authentication

Authenticate every request with a Bearer token. The same token that created a request must be used to fetch its result. If the token is missing or invalid, the API returns an error envelope. If the token doesn’t own the request, the poll request is rejected.

HTTP Header

Authorization: Bearer YOUR_API_KEY

Replace YOUR_API_KEY with the key issued for your account. Rotate compromised keys immediately.

End-to-end Flow (pseudocode)

// Constants
API_KEY = "YOUR_API_KEY"
BASE    = "https://cronengine.com/invoice-api/v3.0"

// 1) Upload (multipart/form-data)
// - field name must be "file"
// - include Authorization: Bearer header
resp = HTTP.POST(
  url = BASE + "/extract",
  headers = { "Authorization": "Bearer " + API_KEY },
  formData = { "file": FILE_FROM_DISK("/absolute/path/to/invoice.pdf") }
)

// Example queued response:
// { "status": "queued", "request_id": "inv_12345" }

// Normalize request id (API may return request_id)
request_id = resp.request_id

// 2) Poll for result until finished
do {
  sleep(1500ms)
  result = HTTP.GET(
    url = BASE + "/result/" + URL_ENCODE(request_id),
    headers = { "Authorization": "Bearer " + API_KEY }
  )

  // result may look like:
  // {
  //   "status": "queued" | "success" | "error",
  //   "data": { ... },            // when succeeded/success
  //   "warnings": [ ... ],        // non-fatal checks (useful for post-validation)
  //   "errors": [ ... ]           // fatal issues (parsing/validation failed)
  // }
} while (result.status == "queued")

// 3) Handle outcome
if (result.status == "success") {
  DATA = result.data        // parsed invoice fields
  WARN = result.warnings    // review to catch possible inconsistencies later
} else if (result.status == "error") {
  ERR = result.errors       // show/log errors
}

Use the Authorization: Bearer header with the same API key for both upload and polling requests.

Request & Response Models

This section describes the shapes you can expect from the API. The service uses a consistent envelope: {"status": "...", ...}. Successful extractions use status: "success". Early rejections (e.g., bad auth, unsupported file) use status: "error".

Queued (upload accepted)

{
  "status": "queued",
  "request_id": "inv_12345"
}

Polling (in progress)

{
  "status": "queued"
}
// or
{
  "status": "processing"
}

Succeeded (result delivered)

{
  "status": "succeeded",
  "data": { /* InvoiceData */ },
  "warnings": [ /* ValidationWarning */ ],
  "errors": [ /* string */ ]
}

When parsing fails, data may be null and an explanation appears in errors.

Error (early rejection)

{
  "status": "error",
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or missing API key."
  }
}

We’ll cover the full list of error codes and troubleshooting steps in a later Errors section. Common codes include FILE_INVALID, FORBIDDEN, JOB_NOT_FOUND, JOB_NOT_AVAILABLE, and PROCESSING_ERROR.

Example - Full Success Payload

{
  "status": "success",
  "data": {
    "InvoiceNumber": "INV-2025-0456",
    "InvoiceType": "invoice",
    "InvoiceDate": "2025-08-15",
    "TaxPointDate": null,
    "DueDate": "2025-09-15",
    "Currency": "EUR",
    "SupplierTaxId": "123456",
    "SupplierVatNumber": "DE123456789",
    "CustomerVatNumber": "FR987654321",
    "SupplierName": "Example Consulting GmbH",
    "CustomerName": "Acme Industries SA",
    "SupplierCountryCode": "DE",
    "CustomerCountryCode": "FR",
    "TotalAmountExclTax": 500.00,
    "TotalVATAmount": 105.00,
    "TotalAmountIncTax": 605.00,
    "RoundingAmount": null,
    "AmountDue": 605.00,
    "IsPaid": null,
    "PaymentStatusText": null,
    "IsReverseCharged": null,
    "IsSelfBilling": null,
    "PurchaseOrderNumber": null,
    "CustomerReference": null,
    "OriginalInvoiceNumber": null,
    "PaymentMethod": null
  },
  "warnings": [],
  "errors": []
}

Add-ons

Add-ons extend the base invoice schema with optional, namespaced fields. Which add-ons are active is determined by your API key settings. When enabled, each add-on contributes additional top-level keys in the JSON result. Validation and light post-processing checks run per add-on and may append human-readable messages to the global warnings array.

How add-ons are enabled

  • Your API key carries an addons list.
  • Only enabled add-ons appear in data. Disabled ones are omitted entirely.

Result shape (with add-ons)

{
  "status": "success",
  "data": {
    /* base fields ... */
    "LineItems": [ ... ],        // lineitems
    "Supplier": { ... },         // parties
    "Customer": { ... },         // parties
    "Banking": { ... },          // banking
    "VAT": { ... },              // vat_tax
    "Logistics": { ... },        // logistics
    "Compliance": { ... },       // compliance
    "Adjustments": { ... },      // adjustments
    "References": { ... },       // references
    "Categorization": { ... },   // categorization
    "LocalizationFX": { ... }    // localization_fx
  },
  "warnings": [ /* strings */ ],
  "errors": [ /* validation errors (strings) */ ]
}

Absent sections are either disabled or not present on the document.

Line Items (lineitems)

Adds LineItems: an array of item rows exactly as printed. Preserves order and (if shown) the printed line numbers.

"LineItems": [
  {
    "LineNumber": 1,
    "Description": "Consulting services - August",
    "Quantity": 8.0,
    "UnitOfMeasure": "h",
    "UnitPrice": 100.0,
    "LineDiscountAmount": null,
    "LineDiscountPercent": null,
    "TaxCategory": "S",
    "VatPercentage": 21.0,
    "LineTotalExclTax": 800.0,
    "LineVATAmount": 168.0,
    "LineTotalInclTax": 968.0,
    "SKU": null,
    "HSCode": null,
    "CountryOfOrigin": null,
    "ServicePeriodStart": "2025-08-01",
    "ServicePeriodEnd": "2025-08-31",
    "ProjectCode": null,
    "CostCenter": null
  }
]

Post-checks may warn about discount/VAT math or incl≠excl+VAT inconsistencies.

Parties (parties)

Adds structured supplier and customer blocks: Supplier and Customer, including addresses and contacts.

"Supplier": {
  "RegistrationNumber": "HRB 123456",
  "EORI": null,
  "Address": {
    "StreetName": "Musterstraße",
    "StreetNumber": "12B",
    "Postbox": null,
    "PostalCode": "10115",
    "City": "Berlin",
    "CountryName": "Deutschland",
    "CountryCode": "DE"
  },
  "Contact": {
    "ContactName": "Anna Schmidt",
    "Email": "billing@example.com",
    "Phone": "+49 30 123456",
    "Website": "www.example.com"
  }
},
"Customer": {
  "CustomerId": "ACME-001",
  "BillingAddress": { /* PostalAddress */ },
  "ShippingAddress": null,
  "Contact": null
}

Post-checks can flag country code/address shape issues (e.g., “Dublin 4” in PostalCode vs City).

Banking (banking)

Adds Banking with payment rails, references, and terms. Values are copied verbatim where applicable.

"Banking": {
  "PaymentIBAN": "DE44500105175407324931",
  "PaymentBIC": "INGDDEFFXXX",
  "BankName": "ING Bank",
  "StructuredPaymentReferenceRF": null,
  "StructuredPaymentReferenceBE": null,
  "UnstructuredPaymentReference": "Invoice INV-2025-0456",
  "SEPAMandateReference": null,
  "PaymentTerms": "Net 30",
  "LatePaymentFeeTerms": null,
  "PaymentInstructionsText": null
}

Post-checks may validate IBAN checksum/BIC shape and coherence with PaymentTerms/DueDate.

VAT & Other Taxes (vat_tax)

Adds VAT with per-rate VAT breakdown and other (non-VAT) taxes, plus legal notes for reverse charge/ICS.

"VAT": {
  "VatBreakdown": [
    { "RatePercent": 21.0, "TaxableBase": 500.0, "VatAmount": 105.0, "TaxCategory": "S", "ExemptionReason": null }
  ],
  "OtherTaxes": null,
  "ReverseChargeNote": null,
  "IntraCommunitySupplyNote": null
}

Post-checks compare totals vs breakdown and validate zero-rating/exemption coherence.

Logistics (logistics)

Adds Logistics with delivery and shipment details, including service period at document level.

"Logistics": {
  "DeliveryNoteNumber": "DN-7788",
  "DeliveryDate": "2025-08-16",
  "ServicePeriodStart": null,
  "ServicePeriodEnd": null,
  "Incoterms": null,
  "CarrierName": "DHL",
  "TrackingNumber": "JVGL9999999999",
  "FreightCostAsLine": true
}

Compliance (compliance)

Adds Compliance with legal statements, e-invoicing profile/IDs, signature hashes, QR payloads, and archive IDs. All text is preserved verbatim.

"Compliance": {
  "LegalStatements": [
    "According to Article 196 VAT Directive: VAT reverse charge."
  ],
  "EInvoicingProfile": "PEPPOL BIS",
  "EInvoiceMessageId": null,
  "ElectronicSignatureHash": null,
  "QRCodeData": null,
  "ArchiveId": null
}

Adjustments (adjustments)

Adds Adjustments for document-level discounts/surcharges, prepayments, balances, and correction metadata.

"Adjustments": {
  "GlobalDiscountAmount": null,
  "GlobalDiscountPercent": null,
  "GlobalSurchargeAmount": null,
  "GlobalSurchargePercent": null,
  "PrepaymentAmount": null,
  "OutstandingBalance": 605.0,
  "CorrectionReason": null,
  "CreditedInvoiceDate": null
}

References (references)

Adds References for contract/framework numbers, delivery orders, document-level project/cost center, salesperson, account numbers, and printed external URLs.

"References": {
  "ContractNumber": "C-2025-014",
  "FrameworkAgreement": null,
  "DeliveryOrderNumber": "DO-5566",
  "ProjectCode": "PRJ-ALPHA",
  "CostCenter": "CC-200",
  "Salesperson": "J. Smith",
  "CustomerAccountNumber": "ACCT-9981",
  "ExternalDocumentURL": "https://portal.example.com/doc/INV-2025-0456"
}

Categorization (categorization)

Adds Categorization with a high-level expense category, free-form tags, a one-line summary, and optional OCR confidence metrics.

"Categorization": {
  "Category": "cloud",
  "ShortSummary": "Cloud hosting for August 2025",
}

Confidence fields are optional; they may be null when unavailable.

Localization & FX (localization_fx)

Adds LocalizationFX for document language and currency conversion context when present.

"LocalizationFX": {
  "DocumentLanguage": "de",
  "ExchangeRate": null,
  "ExchangeRateDate": null,
  "SourceCurrency": "EUR",
  "FunctionalCurrency": null
}

Notes

  • Field names and casing are strict. Unknown values should be null (never invented).
  • Totals must reflect the document exactly. The service prefers verbatim values over recomputation.
  • Warnings are informational and non-blocking. Your UI can surface them for manual review.
  • If an enabled add-on has no matching content on the document, its section may be present with nulls or omitted entirely.

Field Reference

All fields follow strict formats (ISO dates/currency/country/language). If a value isn’t clearly on the document, it may be null.

Legend

  • string text
  • number decimal or integer
  • boolean true / false
  • object nested fields
  • array<T> list of T
  • | null field may be null
Formats: Dates YYYY-MM-DD • Currency ISO 4217 • Country ISO 3166-1 alpha-2 • Language ISO 639-1

Base (always present)

InvoiceNumber string | null
Supplier’s invoice/reference number exactly as printed (keep punctuation and casing). Use null if missing or illegible.
InvoiceType enum | null
Canonical document type from explicit labels. Allowed: invoice, credit_note, debit_note, proforma, receipt, corrective.
InvoiceDate string | null
Issue date in YYYY-MM-DD; if only MM-YYYY is shown, use the first day (YYYY-MM-01). Never infer from filenames/metadata.
TaxPointDate string | null
Supply/tax point date in YYYY-MM-DD when printed and different from InvoiceDate.
DueDate string | null
Payment due date in YYYY-MM-DD, derived from printed terms (e.g., “Net 30”) when unambiguous; otherwise null.
Currency string | null
Three-letter ISO 4217 code (e.g., EUR, USD) taken from the document near totals.
SupplierTaxId string | null
Supplier’s national tax/registration ID exactly as printed; use this when a VAT number isn’t applicable.
SupplierVatNumber string | null
Supplier’s EU VAT ID with country prefix, normalized without spaces (e.g., BE0123456789).
CustomerVatNumber string | null
Customer’s EU VAT ID (with prefix) for intra-EU B2B; null for consumers or when absent.
SupplierName string | null
Supplier’s legal/trading name exactly as printed (exclude address lines unless part of the name).
CustomerName string | null
Buyer/customer name exactly as printed (omit attention lines unless clearly part of the name).
SupplierCountryCode string | null
Supplier country as ISO 3166-1 alpha-2 (e.g., BE, DE), derived from address/VAT prefix when clear.
CustomerCountryCode string | null
Customer country as ISO 3166-1 alpha-2, based on billing/ship-to address or VAT prefix when clear.
TotalAmountExclTax number | null
Grand total excluding tax exactly as printed (often “Subtotal/Net”). Do not recompute if absent.
TotalVATAmount number | null
Sum of VAT across all rates as printed; use 0.0 only when the document explicitly shows zero or a valid reverse-charge note.
TotalAmountIncTax number | null
Grand total including tax exactly as printed (often “Total” or “Amount Due”).
RoundingAmount number | null
Explicit rounding line; positive for upward rounding, negative for downward.
AmountDue number | null
Balance due after payments/credits as printed; typically equals TotalAmountIncTax when unpaid.
IsPaid boolean | null
true only if “PAID” (or equivalent) is printed or payments cover the total; false if marked due; null if unclear.
PaymentStatusText string | null
Verbatim payment status (e.g., “Paid on 2025-06-15”, “Overdue”). Preserve exact wording and dates.
IsReverseCharged boolean | null
true if reverse-charge wording appears (e.g., “Art. 196”); false if standard VAT; null if unclear.
IsSelfBilling boolean | null
true if the document explicitly states self-billing; false if not mentioned; null if ambiguous.
PurchaseOrderNumber string | null
Buyer’s PO/order number exactly as labeled (keep letters, digits, and hyphens).
CustomerReference string | null
Buyer’s reference or attention line (e.g., “Attn: Jane Doe”, “Your ref: 1234”).
OriginalInvoiceNumber string | null
Original invoice reference for credit/debit/corrective documents; null for standard invoices.
PaymentMethod string | null
Explicit payment method (e.g., SEPA transfer, Credit Card, Cash, PayPal); do not infer from IBAN alone.

Add-on: Line Items

array<LineItem> | null
LineNumber number
Printed row number; if absent, assign sequentially by visual order (1, 2, 3…).
Description string | null
Verbatim description of goods/services; preserve wording and punctuation.
Quantity number | null
Numeric quantity or duration; convert hh:mm to decimal hours if needed.
UnitOfMeasure string | null
Unit exactly as shown (e.g., pcs, h, kg, m²).
UnitPrice number | null
Net price per unit (no currency symbol); keep all visible decimals.
LineDiscountAmount number | null
Absolute discount on the line; use negative value if printed as negative.
LineDiscountPercent number | null
Percentage discount (0–100) when explicitly provided.
TaxCategory string | null
Printed category code if present (e.g., S=standard, R=reduced, Z=zero, E=exempt).
VatPercentage number | null
VAT rate (%) applied to the line when shown.
LineTotalExclTax number | null
Net line total before VAT, exactly as printed (use negatives for negative lines).
LineVATAmount number | null
VAT amount for the line if explicitly printed; otherwise null.
LineTotalInclTax number | null
Gross line total including VAT, when printed.
SKU string | null
Supplier SKU / product code / article number as shown.
HSCode string | null
Customs HS/commodity code for the goods, if provided.
CountryOfOrigin string | null
ISO 3166-1 alpha-2 country of origin if printed.
ServicePeriodStart string | null
Line-level service period start (YYYY-MM-DD).
ServicePeriodEnd string | null
Line-level service period end (YYYY-MM-DD).
ProjectCode string | null
Line project reference exactly as printed.
CostCenter string | null
Line cost center code as printed.

Add-on: Parties

PostalAddress

object | null
StreetName string | null
Street name only; exclude house numbers and districts.
StreetNumber string | null
House/building/unit number; include suffixes (e.g., 12B).
Postbox string | null
PO Box line exactly as printed.
PostalCode string | null
Postal/ZIP exactly as printed; include districts like “Dublin 4”.
City string | null
City/town/locality name only.
CountryName string | null
Country name exactly as printed (e.g., “Deutschland”).
CountryCode string | null
ISO 3166-1 alpha-2 country code (e.g., IE, DE).

PartyContact

object | null
ContactName string | null
Full name of the contact person if listed.
Email string | null
Email address exactly as written.
Phone string | null
Phone number as printed; may include country code.
Website string | null
Website URL if present.

SupplierDetails

object | null
RegistrationNumber string | null
Company register / Chamber of Commerce identifier.
EORI string | null
Economic Operators Registration and Identification number (customs).
Address PostalAddress | null
Structured supplier address block.
Contact PartyContact | null
Supplier contact details (person / email / phone / website).

CustomerDetails

object | null
CustomerId string | null
Identifier assigned to the customer in the supplier’s system.
BillingAddress PostalAddress | null
Structured billing address block.
ShippingAddress PostalAddress | null
Structured delivery/shipping address if separate.
Contact PartyContact | null
Customer contact details (person / email / phone / website).

Add-on: Banking

object | null
PaymentIBAN string | null
Supplier’s IBAN exactly as printed (letters/digits; keep visible grouping only if it appears on the document).
PaymentBIC string | null
Bank BIC/SWIFT code as written.
BankName string | null
Bank name exactly as printed (e.g., “ING Bank NV”).
StructuredPaymentReferenceRF string | null
ISO 11649 RF creditor reference (e.g., RF18 5390 0754 7034) when provided.
StructuredPaymentReferenceBE string | null
Belgian structured reference +++000/0000/00000+++ exactly as shown.
UnstructuredPaymentReference string | null
Free-text payment reference or communication line.
SEPAMandateReference string | null
SEPA direct debit mandate reference if applicable.
PaymentTerms string | null
Textual terms (e.g., “Net 30”, “2/10 Net 30”). Don’t compute here; see DueDate for resolution.
LatePaymentFeeTerms string | null
Late-payment penalties or interest wording as printed.
PaymentInstructionsText string | null
Full payment instructions block, verbatim (preserve formatting if you render it).

Add-on: VAT & Other Taxes

object | null

VatBreakdown

array<VatBreakdownRow> | null
RatePercent number
VAT rate as a percentage (0–100) exactly as printed, e.g., 21, 9, 0.
TaxableBase number
Net amount the rate applies to; copy from the totals/breakdown table.
VatAmount number
VAT charged for this rate, exactly as shown (no recomputation).
TaxCategory string | null
If printed, the category code (e.g., S=standard, R=reduced, Z=zero, E=exempt).
ExemptionReason string | null
Verbatim legal text explaining exemption or zero-rating (e.g., “Article 44”).

OtherTaxes

array<OtherTaxRow> | null
Type string
Label of non-VAT tax, e.g., withholding, excise duty, eco tax.
Base number
Net base amount used to calculate this tax, as printed.
Amount number
Total tax amount for this type; use 0.0 only when explicitly shown.

Document-level

VatBreakdown array<VatBreakdownRow> | null
Array of per-rate VAT rows if a breakdown is shown; otherwise null.
OtherTaxes array<OtherTaxRow> | null
List of non-VAT taxes if present; otherwise null.
ReverseChargeNote string | null
Exact reverse-charge wording (e.g., “VAT reverse charge, Article 196”).
IntraCommunitySupplyNote string | null
Verbatim note about intra-community supply or export, if printed.

Add-on: Logistics

object | null
DeliveryNoteNumber string | null
Reference of the delivery note / packing slip exactly as printed.
DeliveryDate string | null
Date of delivery/supply in YYYY-MM-DD if shown on the invoice or note.
ServicePeriodStart string | null
Document-level service period start (YYYY-MM-DD) when printed.
ServicePeriodEnd string | null
Document-level service period end (YYYY-MM-DD) when printed.
Incoterms string | null
Trade term exactly as printed (e.g., EXW, DDP).
CarrierName string | null
Name of the carrier or logistics provider, as shown.
TrackingNumber string | null
Shipment/tracking reference exactly as printed.
FreightCostAsLine boolean | null
true if freight/shipping is a separate line item; false if included in totals.

Add-on: Compliance

object | null
LegalStatements array<string> | null
List of mandatory legal/regulatory texts as printed (keep exact wording).
EInvoicingProfile string | null
E-invoicing profile/format (e.g., PEPPOL BIS, Factur-X, ZUGFeRD).
EInvoiceMessageId string | null
Unique network/message identifier for electronic invoice exchange.
ElectronicSignatureHash string | null
Hash/signature used to authenticate a signed e-invoice (verbatim).
QRCodeData string | null
Raw payload from a payment QR (e.g., EPC QR, Swiss QR), exactly as read.
ArchiveId string | null
Internal archive or document management identifier, if printed.

Add-on: Compliance

object | null
LegalStatements array<string> | null
List of mandatory legal/regulatory texts exactly as printed; keep original wording and line breaks.
EInvoicingProfile string | null
E-invoicing profile/format identifier (e.g., PEPPOL BIS, Factur-X, ZUGFeRD).
EInvoiceMessageId string | null
Unique network/message identifier used in electronic invoice exchange.
ElectronicSignatureHash string | null
Digital signature or hash that authenticates a signed e-invoice (verbatim value).
QRCodeData string | null
Raw payload from a payment QR (e.g., EPC QR, Swiss QR), captured exactly as encoded.
ArchiveId string | null
Internal archive/document management identifier, if present on the document.

Add-on: Adjustments

object | null
GlobalDiscountAmount number | null
Total document-level discount as a single absolute amount (not per-line).
GlobalDiscountPercent number | null
Document-level discount expressed as a percentage (0–100) when printed as a percent.
GlobalSurchargeAmount number | null
Total document-level surcharge/markup as a single absolute amount.
GlobalSurchargePercent number | null
Document-level surcharge expressed as a percentage (0–100) when printed as a percent.
PrepaymentAmount number | null
Total prepayments/deposits already applied to the invoice total.
OutstandingBalance number | null
Remaining balance due after discounts, surcharges, and prepayments, exactly as printed.
CorrectionReason string | null
Verbatim reason for issuing a correction/credit/debit note (e.g., “Returned goods”).
CreditedInvoiceDate string | null
Date of the original invoice being credited in YYYY-MM-DD, when printed.

Add-on: References

object | null
ContractNumber string | null
Specific contract number exactly as printed; keep punctuation and casing.
FrameworkAgreement string | null
Identifier for a framework/master agreement if cited, verbatim from the document.
DeliveryOrderNumber string | null
Delivery order / dispatch note reference number as printed.
ProjectCode string | null
Document-level project code exactly as printed; may differ from line-level project codes.
CostCenter string | null
Document-level cost center code/label used for accounting; keep formatting.
Salesperson string | null
Name or identifier of the salesperson/account manager as printed.
CustomerAccountNumber string | null
Customer’s account number in the supplier’s system; copy verbatim.
ExternalDocumentURL string | null
Full external URL printed on the document (e.g., portal link); keep scheme, host, and path exactly.

Add-on: Categorization

object | null
Category values
  • utilities
  • telecom
  • rent
  • software
  • cloud
  • travel
  • hospitality
  • office_supplies
  • fuel
  • maintenance
  • professional_services
  • insurance
  • logistics
  • advertising
  • taxes_fees
  • other
Category enum | null
High-level expense class from the list above; use null if the document doesn’t clearly fit.
ShortSummary string | null
One-line description of context (e.g., “Cloud hosting for July 2025”); keep verbatim if printed.

Add-on: Localization & FX

object | null
Formats: ISO 639-1 (language), ISO 4217 (currency), dates in YYYY-MM-DD.
DocumentLanguage string | null
Language of the document as ISO 639-1 (e.g., nl, fr, de, en), when determinable.
ExchangeRate number | null
Rate used to convert the source currency into the functional/system currency, if printed on the document.
ExchangeRateDate string | null
Date of the applied exchange rate (YYYY-MM-DD) if shown alongside the rate.
SourceCurrency string | null
Currency used on the invoice (ISO 4217), if different from your system/base currency.
FunctionalCurrency string | null
Internal/accounting base currency (ISO 4217) used by your system, when applicable.

File Constraints & Supported Formats

The extractor accepts common invoice document types. Upload the original PDF when available, scans and photos are also supported.

Supported

  • PDF - native or scanned (multi-page supported)
  • PNG - single image per request
  • JPEG/JPG - single image per request

Not Supported

  • Password-protected or encrypted PDFs
  • HEIC/WEBP/TIFF or raw camera formats
  • Archives (.zip, .rar, …)
  • Spreadsheets/Word docs (.xlsx, .docx, …)

Quality Recommendations (Images/Scans)

  • Keep the document flat, well-lit, and in focus. Avoid skew and heavy shadows.
  • Crop out backgrounds, rotate to upright orientation, and include all pages for best results.
  • Prefer black text on light background, extreme compression can reduce accuracy.

Optional Upload Widget (PHP + HTML)

This helper shows a drag-and-drop input, performs basic client checks, and posts directly to https://invoicesengine.com/invoice-api/v3.0. Adjust limits as needed.

Optional Upload Widget (pseudocode)

This is an optional, language-agnostic outline of a client-side flow. It’s not required by the API.

# Pseudocode for a simple client upload → poll flow
BASE    = "https://cronengine.com/invoice-api/v3.0"
API_KEY = "YOUR_API_KEY"

# 1) User picks a file (PDF/PNG/JPEG)
file = PICK_FILE(accept = [".pdf", ".png", ".jpg", ".jpeg"])
IF file == NONE:
  SHOW("Please select a file")
  STOP

# 2) Upload (multipart/form-data with Bearer auth)
resp = HTTP.POST(
  url     = BASE + "/extract?pretty=1",
  headers = {"Authorization": "Bearer " + API_KEY},
  formData= {"file": FILE_FROM_DISK(file)}
)

# 3) Get request id (request_id)
request_id = resp.request_id ?? resp.request_id

# 4) Poll until finished
REPEAT EVERY 1500ms:
  result = HTTP.GET(
    url     = BASE + "/result/" + URL_ENCODE(request_id) + "?pretty=1",
    headers = {"Authorization": "Bearer " + API_KEY}
  )
  IF result.status IN ["queued","processing"]:
    CONTINUE
  BREAK

# 5) Handle outcome
IF result.status IN ["succeeded","success"]:
  DATA     = result.data       # parsed fields
  WARNINGS = result.warnings   # useful for follow-up checks
ELSE:
  ERROR = result.error         # { code, message }

If you don’t need this helper, you can omit this entire section.

Server-Side Preflight (pseudocode)

Optional sanity checks before proxying to the extractor. Keep your API key server-side. The extractor still performs final validation.

# Constants
BASE        = "https://cronengine.com/invoice-api/v3.0"
API_KEY     = "YOUR_API_KEY"
MAX_SIZE_B  = 25 * MB
ALLOWED_MIME = ["application/pdf", "image/png", "image/jpeg"]

# Endpoint: POST /proxy/extract
file = REQUEST.FILE("file")
IF file IS NONE OR file.error:
  RETURN 400, { "status": "error", "error": { "code": "INVALID_UPLOAD", "message": "No file or upload error." } }

# Basic preflight (advisory; extractor will re-validate)
IF file.size > MAX_SIZE_B:
  RETURN 400, { "status": "error", "error": { "code": "FILE_TOO_LARGE", "message": "Reduce file size." } }

mime = SNIFF_MIME(file.stream_or_path)
IF mime NOT IN ALLOWED_MIME:
  RETURN 400, { "status": "error", "error": { "code": "FILE_INVALID", "message": "Upload PDF, PNG, or JPEG." } }

# Forward to extractor (multipart/form-data with Bearer auth)
upstream = HTTP.POST(
  url     = BASE + "/extract",
  headers = { "Authorization": "Bearer " + API_KEY },
  formData= { "file": STREAM(file) }
  # optional: append ?pretty=1 for pretty JSON
)

# Pass through extractor response and status code
RETURN upstream.status, upstream.json

Tip: also proxy GET /result/{request_id} with the same server-side key to keep credentials out of the client.

Warnings & Validation

During extraction, the service runs lightweight consistency checks. These checks are non-blocking: results are delivered even if something looks off. Potential issues are surfaced as human-readable strings in the top-level warnings array, which you can use to flag items in your UI and prompt users to manually review specific fields (e.g., totals, dates, VAT).

Warning Format

Warnings are plain strings (no nested objects or codes):

{
  "status": "success",
  "data": { ... },
  "warnings": [
    "Totals mismatch: Excl+VAT+Rounding=606.00 vs Inc=605.00 (Δ=+1.00).",
    "DueDate 2025-08-10 is earlier than InvoiceDate 2025-08-15."
  ],
  "errors": []
}

What Gets Checked

  • Totals math - TotalAmountExclTax + TotalVATAmount (+ RoundingAmount) ≈ TotalAmountIncTax.
  • Amount due - AmountDue plausibility vs totals and IsPaid.
  • Date sanity - e.g., DueDate should not be earlier than InvoiceDate.
  • Currency format - uppercase 3-letter ISO 4217.
  • Line items - numbering/order, qty/unit presence, discount math, VAT math, incl = excl + VAT.
  • VAT breakdown - per-rate math and coherence with document totals; reverse-charge/ICS hints.
  • Parties & addresses - country code shape, “Dublin 4” postal hints, street vs number separation.
  • Banking - IBAN checksum, BIC shape, structured references (RF / Belgian), terms vs due date.
  • Compliance & logistics - reverse-charge/intra-community notes, e-invoicing profile, QR payload, service period ordering.
  • Categorization & localization - category/text signals, OCR confidence bounds, language code shape, FX coherence.

The exact set of checks can evolve; treat unknown or new warning texts as informational guidance.

Example - Success with Warnings

{
  "status": "success",
  "data": { ... },
  "warnings": [
    "Totals mismatch: Excl+VAT+Rounding=606.00 vs Inc=605.00 (Δ=+1.00).",
    "Line 1: LineTotalInclTax 121.00 ≠ Excl + VAT (121.50).",
    "Currency 'eur' is not a valid ISO 4217 uppercase code."
  ],
  "errors": []
}

Warnings help you catch possible inconsistencies while still receiving the parsed data.

Handling Warnings (pseudocode)

result = HTTP.GET(BASE + "/result/{request_id}", headers = { Authorization: "Bearer <key>" })
if result.status == "success":
  data     = result.data
  warnings = result.warnings or []
  for w in warnings:
    LOG("invoice warning: " + w)   # surface in UI or flag for review
# Errors are covered in the next section.

Errors

The API returns a consistent error envelope for early rejections (authentication, file validation, ownership, etc.). These are not parsing failures; they mean the request could not be accepted or authorized. Parsing failures after a file is accepted are delivered as status: "success" with data: null and reasons in errors[].

Error Envelope

When an early error occurs, you receive:

{
  "status": "error",
  "error": {
    "code": "<ERROR_CODE>",
    "message": "<Human-readable explanation>"
  }
}

Tip: append ?pretty=1 to pretty-print JSON.

Error Codes

Code When It Happens Example Message What To Do
UNAUTHORIZED Missing/invalid Authorization: Bearer header Invalid or missing API key. Send a valid Bearer token for every request.
FORBIDDEN Polling a request created by a different API key You do not have access to this request. Use the same key you used for POST /extract.
JOB_NOT_FOUND Unknown request ID (never existed) Request not found Verify the request_id or re-upload.
JOB_NOT_AVAILABLE Request owner exists, but in-memory metadata expired Request metadata unavailable (expired). Re-upload or query your persistence (if any) for archived results.
FILE_INVALID Upload validation failed (type/empty/corrupt) Unsupported file type. Upload PDF, PNG, or JPEG. Send a supported file and ensure the form field is file.
PROCESSING_ERROR Unexpected exception during parsing Unexpected parsing failure … Retry later; if persistent, contact support with the request ID.
NO_RESULT Request claims finished but no payload is available (edge case) No result Re-upload; report if reproducible.

UNAUTHORIZED

{
  "status": "error",
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or missing API key."
  }
}

FILE_INVALID

{
  "status": "error",
  "error": {
    "code": "FILE_INVALID",
    "message": "Unsupported file type. Upload PDF, PNG, or JPEG."
  }
}

Handling Error Envelopes (pseudocode)

resp = HTTP.POST(BASE + "/extract", headers = { Authorization: "Bearer " + API_KEY }, formData = { file: FILE(...) })
if resp.status == "error":
  code = resp.error.code
  msg  = resp.error.message
  SWITCH code:
    CASE "UNAUTHORIZED":      SHOW("Check API key"); 
    CASE "FORBIDDEN":         SHOW("Use the same key as upload");
    CASE "FILE_INVALID":      SHOW("Send PDF/PNG/JPEG and ensure field name is 'file'");
    CASE "JOB_NOT_FOUND":     SHOW("Verify request_id or re-upload");
    CASE "JOB_NOT_AVAILABLE": SHOW("Request expired; re-upload");
    CASE "PROCESSING_ERROR":  SHOW("Retry later or contact support");
    CASE "NO_RESULT":         SHOW("Re-upload; unexpected condition");
    DEFAULT:                  SHOW("Unhandled error: " + code + " - " + msg)
else:
  // proceed with queued → poll

Network/transport failures from your HTTP client (timeouts, TLS) are not API error envelopes; handle them separately.

Code Examples

Ready-to-use snippets for direct polling (simple) and cron-based processing (scalable). Replace YOUR_API_KEY and make sure your runtime can reach https://invoicesengine.com/invoice-api/v3.0. The flow is always: POST /extract → get ID → GET /result/{id} until status is "success" or "error".

const fetch = require("node-fetch");
const fs = require("fs");
const FormData = require("form-data");

const API_BASE = 'https://invoicesengine.com/invoice-api/v3.0';
const API_KEY  = process.env.INVOICE_API_KEY || "YOUR_API_KEY";

async function upload(filePath) {
  const form = new FormData();
  form.append("file", fs.createReadStream(filePath)); // field name must be "file"
  const res = await fetch(`${API_BASE}/extract`, {
    method: "POST",
    headers: { Authorization: `Bearer ${API_KEY}` },
    body: form
  });
  const json = await res.json();
  if (json.status === "error") throw new Error(`${json.error.code}: ${json.error.message}`);
  // Accept either request_id (service may use either)
  return json.request_id;
}

async function poll(id, intervalMs = 1500) {
  for (;;) {
    const res  = await fetch(`${API_BASE}/result/${encodeURIComponent(id)}`, {
      headers: { Authorization: `Bearer ${API_KEY}` }
    });
    const json = await res.json();
    const s = json.status;
    if (s === "queued" || s === "processing") {
      await new Promise(r => setTimeout(r, intervalMs));
      continue;
    }
    // Finished: either success (data + warnings/errors arrays) or error envelope
    return json;
  }
}

(async () => {
  const id  = await upload("invoice.pdf");
  console.log("Queued:", id);
  const out = await poll(id);
  console.log("Final:", JSON.stringify(out, null, 2));
})();

Notes: the upload field name must be file. Pending statuses are "queued" and "processing". Completion returns either status: "success" (with data, warnings[], errors[]) or an early status: "error" envelope. Prefer env vars for secrets, exponential backoff for polling, and durable storage for request tracking.

Usage Limits & Fair Policy

The extractor is designed to scale with your workload. There are no hard per-minute throttles for normal use. However, to protect the platform, abusive traffic patterns may trigger protective rate limiting or temporary key suspension.

Soft Guidelines

  • Concurrent jobs: hundreds to thousands per account are supported.
  • Throughput: burst uploads are accepted, but steady pacing helps avoid retries.
  • Job expiry: results remain retrievable for at default 1 day (default retention policy).
  • Storage: raw uploaded files are deleted immediately after parsing.

Protective Measures

To ensure fair use and stability, requests may be rejected with 429 Too Many Requests or 403 Forbidden in the following case:

  • Flooding the API with malformed or unsupported files.

Example - Rate Limited Response

{
  "status": "error",
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests from this API key. Slow down and retry later."
  }
}

Need Help?

Questions, feedback, or support requests? Reach us at info@invoicesengine.com.