Flowie
Guides

Send an invoice over Peppol

One REST call delivers a compliant e-invoice to any Peppol participant. This is the happy path in four steps, from a cold start to a document.delivered webhook.

1 · Register the sender

One-time per company. Creates the company, enriches it from the VAT number, and publishes it to the Peppol SMP so it can both send and receive.

curl -X POST …/v1/companies \
  -H "Authorization: Bearer $FLOWIE_KEY" \
  -d '{"vatNumber":"BE0123456789"}'

If the company already exists on another platform, use POST /v1/companies/import instead, then POST /v1/companies/{id}/register to activate it on Peppol.

2 · Verify the recipient

Always verify before sending. A recipient that is not registered for your document type will bounce, and the bounce arrives asynchronously — minutes after you thought the invoice was gone.

curl -X POST …/v1/directory/verify \
  -H "Authorization: Bearer $FLOWIE_KEY" \
  -d '{"peppolId":"0208:9876543210","documentType":"INVOICE"}'

Check canReceive in the response before continuing.

3 · Send the invoice

Describe the invoice as JSON and we render, sign and route the UBL for you. Pass a persistent Idempotency-Key — generate it before the first attempt, from your own database row id, so a crash between generation and the HTTP call is still recoverable.

curl -X POST …/v1/documents/send \
  -H "Authorization: Bearer $FLOWIE_KEY" \
  -H "Idempotency-Key: inv-2026-001" \
  -d '{
    "type": "invoice",
    "from": "comp_abc123",
    "to":   "0208:9876543210",
    "document": {
      "number":    "INV-2026-001",
      "issueDate": "2026-04-25",
      "dueDate":   "2026-05-25",
      "currency":  "EUR",
      "lines": [{
        "description": "Consulting, April 2026",
        "quantity": 10, "unit": "hours",
        "unitPrice": 150.00, "vatRate": 21
      }]
    }
  }'

Already have UBL XML or a Factur-X PDF? Send it as-is with the xml or file field instead of document — see the endpoint reference for the payload matrix.

4 · Watch the delivery

The response returns immediately with status: "sent"; delivery is asynchronous. A subscribed webhook receives document.delivered once the recipient's access point confirms, or document.failed with an error code if it does not.

Pre-flight checks before switching a customer live
Run the payload through POST /v1/documents/validate in CI. It catches BIS rule violations (BR-*), unreachable recipients and currency mismatches without touching Peppol.

Next