Skip to content

Latest commit

 

History

History
1026 lines (860 loc) · 29.3 KB

File metadata and controls

1026 lines (860 loc) · 29.3 KB

API Reference - invoice-api.xhub

Complete API documentation for the invoice-api.xhub E-Invoice API.

Table of Contents


Authentication

All API requests require a Bearer Token in the Authorization header.

Header Format

Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxx

API Key Types

Type Prefix Usage
Production sk_live_ Live environment, real invoices
Test/Sandbox sk_test_ Development and testing

Example Request

curl -X POST https://service.invoice-api.xhub.io/api/v1/invoice/DE/xrechnung/generate \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"invoice": {...}}'

Base URL

Environment URL
Production https://service.invoice-api.xhub.io
Sandbox https://sandbox.api.invoice-api.xhub.io

Endpoints

Generate Invoice

Creates an e-invoice in the desired format.

POST /api/v1/invoice/{countryCode}/{format}/generate

Path Parameters

Parameter Type Description
countryCode string ISO 3166-1 Alpha-2 country code (DE, AT, CH, etc.)
format string Target format (xrechnung, zugferd, pdf, etc.)

Request Body

{
  "invoice": {
    "type": "string (required: invoice, credit_note, proforma, correction, partial, partial_construction, partial_final_construction, final_construction, self_billed)",
    "invoiceNumber": "string (required)",
    "issueDate": "string (YYYY-MM-DD, required)",
    "dueDate": "string (YYYY-MM-DD, required)",
    "currency": "string (ISO 4217, required)",
    "seller": {
      "name": "string (required)",
      "tradingName": "string (optional)",
      "street": "string (required)",
      "additionalStreet": "string (optional)",
      "city": "string (required)",
      "postalCode": "string (required)",
      "countryCode": "string (ISO 3166-1 alpha-2, required)",
      "state": "string (ISO 3166-2, optional)",
      "vatId": "string (optional)",
      "taxId": "string (optional)",
      "email": "string (optional)",
      "phone": "string (optional)",
      "website": "string (optional)",
      "bankAccount": {
        "iban": "string (required)",
        "bic": "string (optional)",
        "bankName": "string (optional)",
        "accountHolder": "string (optional)"
      }
    },
    "buyer": {
      "name": "string (required)",
      "street": "string (required)",
      "city": "string (required)",
      "postalCode": "string (required)",
      "countryCode": "string (required)",
      "vatId": "string (optional)",
      "email": "string (optional)"
    },
    "items": [
      {
        "position": "number (required, integer > 0)",
        "description": "string (required)",
        "quantity": "number (required, > 0)",
        "unit": "string (UN/ECE Rec. 20, required)",
        "unitPrice": "number (required)",
        "netAmount": "number (required)",
        "taxRate": "number (required, 0-100)",
        "taxCategoryCode": "string (optional, EN 16931)",
        "taxAmount": "number (required)",
        "grossAmount": "number (required)",
        "articleNumber": "string (optional)"
      }
    ],
    "taxSummary": [
      {
        "taxRate": "number (required)",
        "taxCategoryCode": "string (optional)",
        "netAmount": "number (required)",
        "taxAmount": "number (required)"
      }
    ],
    "subtotal": "number (required)",
    "total": "number (required)",
    "paymentTerms": {
      "dueDays": "number (required)",
      "description": "string (optional)",
      "earlyPaymentDiscount": {
        "days": "number (required)",
        "discountPercent": "number (required)"
      }
    },
    "deliveryDate": "string (YYYY-MM-DD, optional)",
    "servicePeriod": {
      "start": "string (YYYY-MM-DD, required)",
      "end": "string (YYYY-MM-DD, required)"
    },
    "paymentMethods": [
      {
        "type": "string (required: bank_transfer, direct_debit, credit_card, paypal, cash, other)",
        "details": "string (optional)"
      }
    ],
    "orderNumber": "string (optional)",
    "customerNumber": "string (optional)",
    "contractNumber": "string (optional)",
    "countrySpecific": {
      "countryCode": "string (required, discriminator)",
      "leitwegId": "string (optional, DE — B2G routing ID)",
      "buyerReference": "string (optional, DE — BT-10)",
      "paymentMeansCode": "string (optional, DE — UNTDID 4461)",
      "isKleinunternehmer": "boolean (optional, DE — §19 UStG)"
    },
    "notes": "string (optional)"
  },
  "templateId": "string (optional, UUID — reference saved PDF template)",
  "formatOptions": {
    "profile": "string (optional: EN16931 (default), BASIC, EXTENDED — for zugferd / facturx)",
    "version": "string (optional: ZUGFeRD 2.3 / 2.4 (default) / 2.5, Factur-X 1.0 / 1.07 / 1.08 (default) / 1.09)",
    "zugferdProfile": "string (legacy alias of profile)",
    "template": "object (optional, inline BlockTemplate for PDF layout)"
  }
}

Response (200 OK)

{
  "success": true,
  "format": "xrechnung",
  "filename": "invoice-INV-2025-001.xml",
  "mimeType": "application/xml",
  "hash": "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
  "data": "PD94bWwgdmVyc2lvbj0iMS4wIi4uLg==",
  "warnings": [
    {
      "code": "W001",
      "message": "Payment terms recommended",
      "field": "paymentTerms"
    }
  ]
}

Response Fields

Field Type Description
success boolean Whether generation was successful
format string Format used
filename string Recommended filename
mimeType string MIME type of the document
hash string Hex-encoded SHA-256 of the returned document bytes (the base64-decoded data). Empty when no document was produced (422). Not byte-stable across calls for PDF outputs — the PDF carries a creation timestamp, so the same payload hashes differently each time. For idempotency or duplicate detection hash your own request payload instead.
data string Base64-encoded document
embeddedXml string The XML embedded in a hybrid PDF (ZUGFeRD / Factur-X), when applicable
warnings array List of warnings

Response (422 Unprocessable Entity)

Two kinds of failure share the status code. Missing data the generator needs (errors[], with the field path) and business-rule violations found on the generated XML (complianceErrors[], Schematron rule IDs such as BR-DE-1, PEPPOL-EN16931-R008). Both can carry warnings[] alongside.

{
  "success": false,
  "format": "zugferd",
  "filename": "",
  "mimeType": "",
  "hash": "",
  "errors": [
    {
      "code": "PDF_GENERATION_ERROR",
      "message": "Missing required data: seller.bankAccount.iban",
      "field": "seller.bankAccount.iban"
    }
  ],
  "warnings": []
}
{
  "success": false,
  "format": "xrechnung",
  "complianceErrors": [
    {
      "code": "BR-DE-1",
      "message": "[BR-DE-1] Eine Rechnung (INVOICE) muss Angaben zu \"PAYMENT INSTRUCTIONS\" (BG-16) enthalten.",
      "field": "/Invoice[1]"
    }
  ],
  "warnings": []
}

Schema violations (wrong enum value, missing required property) come back as 400 with error as an array of issues, each with a JSON path:

{
  "success": false,
  "error": [
    {
      "code": "invalid_value",
      "path": ["invoice", "type"],
      "message": "Invalid option: expected one of \"invoice\"|\"credit_note\"|\"proforma\"|\"correction\"|…"
    }
  ]
}

Since node v1.2.0 all three shapes surface in the node error message and, with Continue (using error output), as errors, complianceErrors, warnings and schemaIssues on the failed item.


Parse Invoice

Extracts invoice data from an e-invoice document.

POST /api/v1/invoice/{countryCode}/{format}/parse

Path Parameters

Parameter Type Description
countryCode string Expected country code
format string Expected format

Request Body

{
  "data": "PD94bWwgdmVyc2lvbj0iMS4wIi4uLg==",
  "filename": "invoice.xml"
}
Field Type Required Description
data string Yes Base64-encoded document
filename string No Filename hint

Response (200 OK)

{
  "success": true,
  "format": "xrechnung",
  "hash": "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
  "invoice": {
    "type": "invoice",
    "invoiceNumber": "INV-2025-001",
    "issueDate": "2025-01-15",
    "dueDate": "2025-02-14",
    "currency": "EUR",
    "seller": {
      "name": "ACME GmbH",
      "street": "Hauptstraße 1",
      "city": "Berlin",
      "postalCode": "10115",
      "countryCode": "DE",
      "vatId": "DE123456789"
    },
    "buyer": {
      "name": "Customer AG",
      "street": "Nebenstraße 2",
      "city": "München",
      "postalCode": "80331",
      "countryCode": "DE",
      "vatId": "DE987654321"
    },
    "items": [
      {
        "position": 1,
        "description": "Consulting Services",
        "quantity": 10,
        "unit": "HUR",
        "unitPrice": 150.00,
        "netAmount": 1500.00,
        "taxRate": 19,
        "taxAmount": 285.00,
        "grossAmount": 1785.00
      }
    ],
    "taxSummary": [
      {
        "taxRate": 19,
        "netAmount": 1500.00,
        "taxAmount": 285.00
      }
    ],
    "subtotal": 1500.00,
    "total": 1785.00,
    "paymentTerms": {
      "dueDays": 30
    }
  },
  "warnings": []
}

Parse Auto-Detect

Parses an invoice document with automatic country and format detection.

POST /api/v1/invoice/parse

Request Body

{
  "data": "PD94bWwgdmVyc2lvbj0iMS4wIi4uLg==",
  "filename": "invoice.xml"
}
Field Type Required Description
data string Yes Base64-encoded document
filename string No Filename hint for format detection

Response (200 OK)

{
  "success": true,
  "format": "xrechnung",
  "hash": "3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b",
  "invoice": { ... },
  "detection": {
    "format": "xrechnung",
    "formatVersion": "2.3.0",
    "countryCode": "DE",
    "confidence": 0.95,
    "formatMethod": "xml-analysis",
    "countrySource": "vatId",
    "isAmbiguous": false
  }
}

Detection Fields

Field Type Description
detection.format string Detected format identifier
detection.formatVersion string Detected format version (if available)
detection.countryCode string Detected country code
detection.confidence number Confidence score (0-1)
detection.formatMethod string How format was detected
detection.countrySource string How country was determined
detection.isAmbiguous boolean Whether detection was ambiguous
detection.alternativeCountries string[] Other possible countries (if ambiguous)

Validate Invoice

Validates invoice data against country-specific rules.

POST /api/v1/invoice/{countryCode}/validate

Path Parameters

Parameter Type Description
countryCode string Country code for validation rules

Request Body

{
  "invoice": {
    "type": "invoice",
    "invoiceNumber": "INV-2025-001",
    "issueDate": "2025-01-15",
    "dueDate": "2025-02-14",
    "currency": "EUR",
    "seller": { ... },
    "buyer": { ... },
    "items": [ ... ],
    "taxSummary": [ ... ],
    "subtotal": 6300.00,
    "total": 7497.00,
    "paymentTerms": { "dueDays": 30 }
  }
}

Response (200 OK) - Valid

{
  "success": true,
  "errors": [],
  "warnings": []
}

Response (200 OK) - With Errors

{
  "success": false,
  "errors": [
    {
      "code": "E001",
      "message": "Invalid VAT ID format",
      "field": "seller.vatId",
      "severity": "error"
    },
    {
      "code": "E002",
      "message": "Invoice total does not match line items",
      "field": "total",
      "severity": "error"
    }
  ],
  "warnings": [
    {
      "code": "W001",
      "message": "Due date is missing",
      "field": "dueDate",
      "severity": "warning"
    }
  ]
}

valid vs. results[] — two different verdicts

  • valid reflects the object-level country rules only (required fields, totals, VAT IDs).
  • results[] has one entry per e-invoice format: the generated XML checked against XSD + Schematron, each with its own valid and errors[].
  • An invoice can be valid: true while results[n].valid is false — enable Fail on Errors and check results when you need format-level conformance (BR-DE-, PEPPOL-).
{
  "success": true,
  "valid": true,
  "errors": [],
  "warnings": [],
  "results": [
    {
      "format": "xrechnung",
      "valid": false,
      "errors": [
        { "code": "BR-DE-1", "message": "[BR-DE-1] Eine Rechnung (INVOICE) muss Angaben zu \"PAYMENT INSTRUCTIONS\" (BG-16) enthalten." }
      ]
    }
  ]
}

Convert Invoice

Converts an e-invoice document into another format. The source format and country are auto-detected (same detection as Parse Auto-Detect), the document is parsed and regenerated in the target format. Requires the source :parse and the target :create entitlement; billed once against the target :create quota (like Generate).

POST /api/v1/invoice/convert

Request Body

{
  "source": "string (required, base64-encoded XML or PDF)",
  "targetFormat": "string (required: zugferd, facturx, xrechnung)",
  "filename": "string (optional, detection hint)",
  "formatOptions": {
    "profile": "string (optional: EN16931, BASIC, EXTENDED)",
    "version": "string (optional, e.g. 2.5 for ZUGFeRD, 1.09 for Factur-X)"
  }
}
  • XRechnung → ZUGFeRD is loss-free (CIUS → EN 16931). ZUGFeRD / Factur-X → XRechnung only succeeds when the XRechnung obligations (BT-10, BR-DE-*) are met — otherwise 422 with the offending rule codes.
  • zugferd and facturx are the same hybrid PDF/A-3 standard; the seller country picks the flavour (FR/BE → Factur-X, otherwise ZUGFeRD), so both yield a PDF with embedded CII XML.
  • The retired profiles MINIMUM and BASIC WL are rejected with 400.

Response (200 OK)

{
  "success": true,
  "sourceFormat": "XRECHNUNG_UBL",
  "targetFormat": "zugferd",
  "mimeType": "application/pdf",
  "filename": "RE-2025-001.pdf",
  "hash": "c002a71aaa80f80be4d3ccc3bc5f86a0effe25bfdeca3f07f4257f99117f9417",
  "data": "JVBERi0xLjcKJYGBgYEK...",
  "conversionWarnings": []
}
Field Type Description
sourceFormat string Detected source format, e.g. XRECHNUNG_UBL
targetFormat string Requested target format
filename / mimeType / hash string As for Generate (hash = hex SHA-256 of the returned bytes)
data string Base64-encoded converted document
conversionWarnings array Source fields that could not be carried into the target format

Errors

Status error Meaning
400 Bad Request source / targetFormat missing, unsupported targetFormat (Supported: zugferd, facturx, xrechnung) or a retired profile
400 FORMAT_NOT_DETECTED Source format/country not detectable — the body carries a detection object
403 Missing :parse (source) or :create (target) entitlement
422 Source cannot be converted into a conformant target document (rule codes in the body)
429 QUOTA_EXCEEDED Quota exhausted

In the node this is the Convert operation: binary or base64 input, binary output by default (or base64 data), plus sourceFormat and conversionWarnings on the item.


Get Formats

Retrieves all supported countries and formats.

GET /api/v1/invoice/formats

Response (200 OK)

{
  "countries": [
    {
      "code": "DE",
      "name": "Germany",
      "label": "Germany (DE)",
      "formats": ["pdf", "xrechnung", "zugferd"],
      "formatDetails": [
        { "code": "pdf", "label": "PDF", "kind": "pdf" },
        { "code": "zugferd", "label": "ZUGFeRD 2.3/2.4/2.5", "kind": "einvoice" },
        { "code": "xrechnung", "label": "XRechnung 3.0/3.0.2", "kind": "einvoice" }
      ]
    },
    {
      "code": "CH",
      "name": "Switzerland",
      "label": "Switzerland (CH)",
      "formats": ["pdf", "zugferd", "qr-bill"],
      "formatDetails": [
        { "code": "pdf", "label": "PDF", "kind": "pdf" },
        { "code": "zugferd", "label": "ZUGFeRD (CH)", "kind": "einvoice" },
        { "code": "qr-bill", "label": "QR-Bill", "kind": "einvoice", "parse": false }
      ]
    }
  ]
}

Response Fields

Field Type Description
countries[].code string ISO 3166-1 alpha-2 country code (uppercase)
countries[].label string Display label, e.g. Germany (DE)
countries[].formats string[] Generate format tokens, as used in the URL path (/{countryCode}/{format}/generate)
countries[].formatDetails[] object[] Per-token display metadata: code, label, kind (pdf / einvoice) and optional parse: false for generate-only formats without a parse route (qr-bill)

Since API v1.4.0 (formats used to be an array of { id, name, mimeType } objects). The node reads formatDetails[].label for its Country/Format pickers and hides parse: false formats in the Parse operation.


Get Country Formats

Retrieves supported formats for a specific country.

GET /api/v1/invoice/{countryCode}/formats

Path Parameters

Parameter Type Description
countryCode string ISO 3166-1 Alpha-2 country code

Response (200 OK)

{
  "code": "DE",
  "name": "Germany",
  "label": "Germany (DE)",
  "formats": ["pdf", "xrechnung", "zugferd"],
  "formatDetails": [
    { "code": "pdf", "label": "PDF", "kind": "pdf" },
    { "code": "zugferd", "label": "ZUGFeRD 2.3/2.4/2.5", "kind": "einvoice" },
    { "code": "xrechnung", "label": "XRechnung 3.0/3.0.2", "kind": "einvoice" }
  ]
}

Same entry shape as one element of GET /formatscountries[] (no wrapper object).


Request/Response Schemas

Invoice Schema

type InvoiceType =
  | 'invoice' | 'credit_note' | 'proforma' | 'correction'
  | 'partial' | 'partial_construction' | 'partial_final_construction' | 'final_construction' | 'self_billed';

interface Invoice {
  // Required fields
  type: InvoiceType;
  invoiceNumber: string;
  issueDate: string;          // YYYY-MM-DD
  dueDate: string;            // YYYY-MM-DD
  currency: string;           // ISO 4217
  seller: Party;
  buyer: Party;
  items: Item[];
  taxSummary: TaxSummaryEntry[];
  subtotal: number;
  total: number;
  paymentTerms: PaymentTerms;

  // Optional fields
  deliveryDate?: string;
  servicePeriod?: ServicePeriod;
  paymentMethods?: PaymentMethod[];
  orderNumber?: string;
  customerNumber?: string;
  contractNumber?: string;
  countrySpecific?: CountrySpecific;  // DE: leitwegId, buyerReference, …; any country: invoiceTypeCode (explicit BT-3)
  notes?: string;
  prepaidAmount?: number;     // BT-113, amount already paid (v1.4)
}

interface Party {
  name: string;
  tradingName?: string;
  street: string;
  additionalStreet?: string;
  city: string;
  postalCode: string;
  countryCode: string;        // ISO 3166-1 Alpha-2
  state?: string;             // ISO 3166-2
  vatId?: string;
  taxId?: string;
  email?: string;
  phone?: string;
  website?: string;
  bankAccount?: BankAccount;
}

interface BankAccount {
  iban: string;
  bic?: string;               // 8-11 chars
  bankName?: string;
  accountHolder?: string;
}

interface Item {
  position: number;           // required, integer > 0
  description: string;
  quantity: number;
  unit: string;               // UN/ECE Rec. 20
  unitPrice: number;
  netAmount: number;
  taxRate: number;            // 0-100
  taxCategoryCode?: string;   // EN 16931
  taxAmount: number;
  grossAmount: number;
  articleNumber?: string;
}

interface TaxSummaryEntry {
  taxRate: number;
  taxCategoryCode?: string;
  netAmount: number;
  taxAmount: number;
}

interface PaymentTerms {
  dueDays: number;
  description?: string;
  earlyPaymentDiscount?: {
    days: number;
    discountPercent: number;
  };
}

interface ServicePeriod {
  start: string;              // YYYY-MM-DD
  end: string;
}

interface PaymentMethod {
  type: 'bank_transfer' | 'direct_debit' | 'credit_card' | 'paypal' | 'cash' | 'other';
  details?: string;
}

// Country-specific (DE example)
interface CountrySpecificDE {
  countryCode: 'DE';
  leitwegId?: string;         // B2G routing ID
  buyerReference?: string;    // BT-10
  paymentMeansCode?: string;  // UNTDID 4461, default "58"
  isKleinunternehmer?: boolean; // §19 UStG exemption
}

Error Schema

interface ErrorResponse {
  success: false;
  error: string;
  message?: string;
  errors?: ValidationError[];
}

interface ValidationError {
  code: string;
  message: string;
  field?: string;
  severity: 'error' | 'warning';
}

Error Codes

HTTP Status Codes

Code Meaning Description
200 OK Request successful
400 Bad Request Invalid request/validation error
401 Unauthorized API key missing or invalid
403 Forbidden No permission for this resource
404 Not Found Resource not found
422 Unprocessable Entity Semantic errors in data
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Server error

Validation Error Codes

Errors

Code Description Field
E001 Invalid VAT ID format seller.vatId, buyer.vatId
E002 Invoice total does not match total
E003 Required field missing various
E004 Invalid date format invoiceDate, dueDate
E005 Negative amounts not allowed lineItems[].unitPrice
E006 Invalid VAT rate lineItems[].vatRate
E007 Invalid currency code currency
E008 Invalid country code seller.address.country
E009 Invalid unit code lineItems[].unit
E010 Invoice number already used invoiceNumber

Warnings

Code Description Field
W001 Due date is missing dueDate
W002 Payment terms are missing paymentTerms
W003 Bank account is missing seller.bankAccount
W004 Email address is missing seller.email, buyer.email
W005 Position number is missing lineItems[].position
W006 Leitweg-ID recommended for B2G buyerReference

API Error Codes

Code Description
AUTH_MISSING Authorization header is missing
AUTH_INVALID API key is invalid
AUTH_EXPIRED API key has expired
RATE_LIMIT Rate limit exceeded
FORMAT_UNSUPPORTED Format not supported for country
COUNTRY_UNSUPPORTED Country not supported
PARSE_ERROR Document could not be parsed
GENERATION_ERROR Document could not be generated

Rate Limits

Standard Limits

Plan Requests/Minute Requests/Day
Free 10 100
Starter 60 1,000
Professional 300 10,000
Enterprise 1,000 100,000

Rate Limit Headers

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1705312800
Header Description
X-RateLimit-Limit Maximum requests per minute
X-RateLimit-Remaining Remaining requests
X-RateLimit-Reset Unix timestamp for reset

Rate Limit Exceeded

{
  "success": false,
  "error": "RATE_LIMIT",
  "message": "Rate limit exceeded. Try again in 45 seconds.",
  "retryAfter": 45
}

Webhooks (optional)

Webhook Events

Event Description
invoice.generated Invoice was generated
invoice.validated Invoice was validated
invoice.parsed Invoice was parsed
invoice.error Error during processing

Webhook Payload

{
  "event": "invoice.generated",
  "timestamp": "2025-01-15T10:30:00Z",
  "data": {
    "requestId": "req_abc123",
    "invoiceNumber": "INV-2025-001",
    "format": "xrechnung",
    "countryCode": "DE",
    "success": true
  }
}

Webhook Signature

Webhooks are signed with HMAC-SHA256:

X-Webhook-Signature: sha256=abc123...

SDK Support

n8n Community Node

npm install n8n-nodes-invoice-api-xhub

JavaScript/TypeScript

import { InvoiceXhubClient } from 'invoice-xhub-sdk';

const client = new InvoiceXhubClient({
  apiKey: 'sk_live_...'
});

const result = await client.generate({
  countryCode: 'DE',
  format: 'xrechnung',
  invoice: { ... }
});

cURL

curl -X POST https://service.invoice-api.xhub.io/api/v1/invoice/DE/xrechnung/generate \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d @invoice.json

Changelog

v1.4.0 (2026-06-10)

Vendored spec synced 2026-08-29 via pnpm sync:openapi (81 paths; the previous vendored copy was a key-filtered /openapi.json with 61 paths and only the entitled countries in its enums). Field-level changes: git diff of openapi/openapi.json at that commit.

  • Coverage expanded to 37 countries (added AE, AU, HR, IS, JP, LI, NZ, OM, SK — the first non-European ones)
  • Generate formats: BE gains facturx; LI generates pdf, qr-bill, ubl; new token hr-fisk (HR-FISK 2.0 CIUS, validate only)
  • GET /formats response shape: countries[].formats is now a string[] of tokens, display metadata moved to countries[].formatDetails[] { code, label, kind, parse? }, countries gained label; qr-bill is flagged parse: false
  • invoice.type gained partial, partial_construction, partial_final_construction, final_construction, self_billed (UNTDID 1001 mapping; DOCUMENT_TYPE_FALLBACK warning where the format has no code)
  • New invoice fields: prepaidAmount (BT-113), countrySpecific.invoiceTypeCode (explicit BT-3 code, takes precedence over type)
  • formatOptions.profile (EN16931 / BASIC / EXTENDED) and formatOptions.version (ZUGFeRD 2.3 / 2.4 / 2.5, Factur-X 1.0 / 1.07 / 1.08 / 1.09); zugferdProfile is a legacy alias; MINIMUM and BASIC WL profiles are retired (400)
  • 13 parse routes added: be/facturx, ch/zugferd, li|is|ae|om|jp|au|nz/ubl, hr|sk/ubl, hr|sk/peppol-ubl; removed: POST /api/v1/invoice/ch/qr-bill/parse
  • New endpoints: POST /api/v1/invoice/convert (node operation Convert, see above), POST /api/v1/invoice/attachments, POST /api/v1/pdf/attachments
  • Peppol (not exposed by the node): POST /api/v1/peppol/registration, POST /api/v1/peppol/send, GET /api/v1/peppol/receivers/{peppolId}, GET /api/v1/peppol/transmissions, POST /api/v1/peppol/transmissions/{messageId}/refresh

v1.3.0 (2026-05-24)

  • Expanded coverage to 28 European countries (added CY, DK, EE, FI, GB, GR, IE, LT, LU, LV, MT, NO, SE, SI)
  • New formats: mydata (GR), qr-bill (CH), peppol-ubl (PL/PT/RO), cii (parse)
  • Generate response now includes embeddedXml for hybrid formats (ZUGFeRD/Factur-X)
  • Validate response now includes per-format results (XSD + Schematron validation)
  • New invoice fields: profile, serviceCategory, roundingAmount, referencedInvoiceNumber/referencedInvoiceDate, delivery, deliveryNote, directDebitMandate, constructionTax, allowancesCharges, thirdPartyPayments, attachments, projectNumber
  • New API endpoints: POST /api/v1/pdf/generate, POST /api/v1/invoice/{country}/{format}/validate, GET /api/v1/invoice/es/verifactu-qr

v1.1.0 (2026-04)

  • Extended party schema: tradingName, additionalStreet, state, website, bankAccount.accountHolder
  • position now required on items, taxCategoryCode now optional
  • paymentTerms now required (object with dueDays, optional earlyPaymentDiscount)
  • type field required with lowercase enum: invoice, credit_note, proforma, correction
  • New fields: servicePeriod, paymentMethods, orderNumber, customerNumber, contractNumber
  • Country-specific fields: countrySpecific object (DE: leitwegId, buyerReference, paymentMeansCode, isKleinunternehmer)
  • templateId for referencing saved PDF templates
  • Field renames: invoiceDateissueDate, lineItemsitems, seller.address.*seller.* (flat), countrycountryCode

v1.0.x (2025-06)

  • Added Parse Auto-Detect endpoint (POST /api/v1/invoice/parse)
  • Automatic country and format detection with confidence scoring
  • All endpoints use /api/v1/invoice/ prefix

v1.0.0 (2025-01)

  • Initial API release
  • Support for 14 countries
  • 18 formats available
  • Generate, Parse, Validate, Get Formats endpoints