Skip to content

HTTP Reference — Generation API

The generation API (apps/api) is a stateless HTTP service hosted on the same VPS as the other Kortilabs apps. It exposes generation, validation and parsing operations for electronic invoices.

Base URL: https://api.facturation.kortilabs.com


Authentication

All generation routes require an Authorization: Bearer <PORTAL_HMAC_SECRET> header. API keys are managed from the OPERAT portal (/api/portal).


POST /api/v1/generate

Generates a Factur-X file (PDF/A-3 + EN 16931 CII XML).

Request body

{
"invoice": {
"number": "INV-2026-0001",
"typeCode": "380",
"issueDate": "2026-06-01",
"currency": "EUR",
"seller": {
"name": "ACME SAS",
"siret": "12345678900012",
"vatNumber": "FR12345678900",
"address": { "street": "1 rue de la Paix", "city": "Paris", "postalCode": "75001", "country": "FR" }
},
"buyer": {
"name": "Client SAS",
"siret": "98765432100019",
"address": { "street": "5 avenue des Champs", "city": "Lyon", "postalCode": "69001", "country": "FR" }
},
"lines": [
{
"id": "1",
"description": "Consulting services",
"quantity": 2,
"unitCode": "HUR",
"unitPrice": 150,
"vatRate": 20
}
],
"paymentTerms": "Payment within 30 days"
}
}

Response 200

{
"xml": "<base64>…</base64>",
"pdf": "<base64>…</base64>",
"validation": { "valid": true, "errors": [], "warnings": [] }
}

Error codes

CodeCause
422Invalid invoice — validation.errors lists the failing BR-* rules
400Malformed JSON
401Missing or invalid API key

POST /api/v1/validate

Validates an invoice against EN 16931 rules and French BR-FR-* rules without generating any file.

Request body

Same structure as /generate, invoice field only.

Response 200

{
"valid": false,
"errors": [
{ "rule": "BR-01", "message": "Invoice number is required", "path": "invoice.number" }
],
"warnings": [
{ "rule": "BR-FR-09", "message": "Seller SIREN recommended for French invoices", "path": "invoice.seller.siret" }
]
}

POST /api/v1/parse

Parses a Factur-X file (CII XML or UBL) and returns the normalised JSON structure.

Request body

{ "xml": "<base64-encoded XML file>" }

Response 200

{
"format": "CII",
"invoice": { "number": "INV-2026-0001", "…": "" },
"validation": { "valid": true, "errors": [], "warnings": [] }
}

The format field is either "CII" (CrossIndustryInvoice — Factur-X) or "UBL" (Universal Business Language).


POST /check-xml

Validates the syntactic and structural conformity of an XML fragment without HMAC authentication. Useful for testing and PrestaShop integration.

Request body

{ "xml": "<raw XML content>" }

Response 200

{
"valid": true,
"format": "CII",
"errors": [],
"warnings": []
}

Webhooks — HMAC verification

The SDK exposes verifyWebhook to verify the signature of incoming webhooks (LemonSqueezy, PA, etc.).

import { verifyWebhook } from '@facturation/sdk';
// In your Next.js / Hono handler
const isValid = verifyWebhook({
payload: rawBody, // Buffer or string of the raw body
signature: req.headers['x-signature'],
secret: process.env.LEMONSQUEEZY_WEBHOOK_SECRET,
});
if (!isValid) return new Response('Unauthorized', { status: 401 });

Verification uses crypto.timingSafeEqual to prevent timing attacks.

LemonSqueezy events handled

EventAction
order_createdUpgrades user plan (SITE or MULTI)
subscription_cancelledDowngrades to FREE at end of period
subscription_expiredImmediate downgrade to FREE

Limits and quotas

LimitValue
Max request body size10 MB
Rate limiting100 req/min per IP
Batch invoicesNot available in v1 — 1 invoice per call