Platform in Active Development
You can already use certain features, but functionality and design are actively evolving. Expect regular updates, changes, and new features to be added.
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
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; otherwisenull
. -
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
Supplier
Customer
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
-
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
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 andIsPaid
. - Date sanity - e.g.,
DueDate
should not be earlier thanInvoiceDate
. - 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.