Factuur verzenden via de API

Een e-factuur verzenden via het SalesInvoice endpoint: upload in elk ondersteund formaat, automatische transformatie, routering en statustracking.

Het verzenden van een e-factuur via de PSB API is het meest gebruikte endpoint. Je stuurt een XML-document naar de API in het formaat dat jouw software produceert, en de PSB zorgt voor validatie, automatische transformatie naar het formaat dat de ontvanger verwacht, routering en aflevering via het juiste netwerk.

Endpoint
POST /api/v1/{partyId}/salesInvoice/send

De {partyId} in de URL is de Peppol-identifier van de verzendende organisatie (de leverancier). Het request bevat het XML-document als body (content-type application/xml). De PSB detecteert automatisch het documentformaat en valideert het document. Je kunt aanleveren in elk ondersteund formaat: UBL 2.1, NLCIUS, BIS Billing V3, PINT, CII, XRechnung, Factur-X, FatturaPA, ebInterface, Svefaktura, DICO, SETU en meer. De PSB transformeert het document automatisch naar het formaat dat de ontvanger verwacht.

Basisflow
  1. Upload: stuur het XML-document naar het endpoint
  2. Validatie: de PSB valideert het document op XSD-schema en business rules
  3. Routering: de PSB zoekt via SML/SMP op hoe de ontvanger bereikbaar is
  4. Aflevering: het document wordt via het juiste kanaal (Peppol, e-mail, of ander netwerk) afgeleverd
  5. Statusupdate: je ontvangt een webhook-notificatie met de afleveringsstatus

Let op: de PSB bepaalt de ontvanger op basis van het EndpointID in je XML-document. Als dit element ontbreekt of een onjuiste identifier bevat, mislukt de verzending met de status InvoiceSentError. Zorg dat je bronsysteem het correcte EndpointID invult. Meer over identifiers en routering lees je in het artikel over Peppol-identifiers.

Idempotency: dubbele uploads voorkomen

De PSB ondersteunt idempotency via de X-EConnect-DocumentId request header. Door bij elk upload-request een eigen UUID mee te sturen, voorkom je dubbele verwerking:

X-EConnect-DocumentId: 550e8400-e29b-41d4-a716-446655440000

Als je hetzelfde documentId nogmaals stuurt, retourneert de API 409 Conflict, de zender weet dan dat het document al verwerkt is.

Let op: Gebruik altijd een UUID/GUID als documentId. Gebruik nooit het factuurnummer, dat veroorzaakt problemen als je een gecorrigeerde versie van dezelfde factuur wilt herverzenden.

Routering controleren

Voordat je een factuur verstuurt, kun je via queryRecipientParty controleren of en hoe de ontvanger bereikbaar is:

POST /api/v1/{partyId}/salesInvoice/queryRecipientParty

In de request body geef je een lijst van identifiers mee, bijvoorbeeld ["0106:12345678"], of een object met partyIds en metaAttributes. Optionele queryparameters zijn ?preferredDocumentTypeId en ?includeOptions.

De response bevat informatie over:

  • Of de ontvanger geregistreerd is op Peppol
  • Welke documenttypen de ontvanger kan ontvangen
  • Via welk Access Point de ontvanger bereikbaar is
  • Welk kanaal de PSB zal gebruiken voor aflevering

Voor geavanceerde lookups inclusief de Access Point-URL en het AP-certificaat is een aparte route beschikbaar:

GET /api/v1/peppol/deliveryOption?partyIds={id}&documentFamily=Invoice&isCredit=false
Foutafhandeling

Bij een mislukte aflevering past de PSB automatisch een retry-mechanisme toe:

  • Maximaal 8 pogingen verspreid over circa 35 uur
  • Alleen bij 5xx server errors (tijdelijke fouten aan de ontvangende kant)
  • Per poging wordt een InvoiceSentRetry-event gepubliceerd
  • Bij definitief falen ontvang je een InvoiceSentError-event via je webhook

Veelvoorkomende fouten bij verzending:

FoutOorzaakOplossingValidatiefout (4xx)Document voldoet niet aan de standaardControleer het document met de Validate API. Let op: 4xx-fouten worden niet geretried; het document blijft in InvoiceSentError als eindstatus.Invalid payload — '{waarde}' is geen geldige xs:decimal op een bedragveldHet bronsysteem serialiseert een bedrag (bijvoorbeeld cbc:TaxInclusiveAmount, cbc:PriceAmount, cbc:LineExtensionAmount) in wetenschappelijke notatie, zoals -1.336061E6 in plaats van -1336061.00. UBL-bedragvelden zijn van type xs:decimal en het XML Schema-type staat geen exponent-notatie toe; alleen vaste decimale notatie met maximaal 2 decimalen is geldig. Komt typisch voor bij grote of negatieve bedragen die intern als double worden geserialiseerd.Pas het bronsysteem aan zodat bedragen als gewone decimale getallen worden weggeschreven (geen E-notatie, geen duizendseparators). Meld het issue bij de leverancier van het verzendende softwarepakket; eConnect kan dit niet bijregelen omdat de waarde in de aangeleverde XML staat.Ontvanger niet gevondenIdentifier niet geregistreerd in PeppolControleer via queryRecipientParty409 ConflictDocument met dit documentId is al verwerktGeen actie nodig, het document is al verstuurdHTTP 500 bij grote payloadRequest overschrijdt de 24 MB webserver-limiet (inclusief overhead)Verklein embedded PDF-bijlagen; houd rekening met circa 33% base64-overhead

Let op: SI-UBL 1.2 (Simpler Invoicing 1.2) is per 1 januari 2024 niet meer toegestaan op het Peppol-netwerk. Facturen in dit formaat resulteren in een InvoiceSentError. Gebruik NLCIUS (SI-UBL 2.0) of Peppol BIS Billing V3. Controleer het CustomizationID in je XML-document als je deze fout tegenkomt.

Response

Een succesvolle upload retourneert een 200 OK met de document-ID in de PSB. Gebruik deze ID om de status van het document te volgen via de API of via webhooks.

Geen DELETE op salesInvoice: eindstatus na 4xx-fout

In tegenstelling tot purchaseInvoice kent het salesInvoice-endpoint geen DELETE. Dit is een bewuste keuze, omdat een verstuurde of afgekeurde verkoopfactuur een audit-relevante levensgebeurtenis is: het document blijft in de audittrail traceerbaar, ook nadat de verzending is mislukt.

Klanten vragen soms of een afgekeurde sales invoice gestopt of verwijderd kan worden, bijvoorbeeld nadat ze de factuur intern al hebben gecrediteerd. Het antwoord is:

  • Validatiefout (4xx, bijvoorbeeld Invalid payload): de PSB plaatst het document in eindstatus InvoiceSentError. Er wordt geen retry uitgevoerd (alleen 5xx-fouten worden geretried). Het document wordt niet alsnog uitgeleverd aan de ontvanger. Er is geen actie nodig op de PSB; het document staat in eindstatus en blijft 90 dagen bewaard voor audit.
  • Geen DELETE-endpoint nodig: omdat het document niet meer actief is en niet wordt geretried, hoeft het niet expliciet verwijderd te worden om verzending te stoppen.
  • Correctie sturen via een nieuw document: als de oorspronkelijke factuur onjuist was en al (gedeeltelijk) was uitgeleverd, gebruik dan een credit note of correctiefactuur volgens de standaard boekhoudkundige flow. Het oorspronkelijke documentId blijft als referentie staan in de audittrail.

Dit verschil in lifecycle tussen salesInvoice (geen DELETE) en purchaseInvoice (wel DELETE) komt voort uit de rol: een uitgaande factuur is een door de verzender vastgelegde commerciële handeling die juridisch traceerbaar moet zijn; een ontvangen factuur kan na succesvolle download uit het eigen systeem worden opgeschoond.

ViDA en CTC-rapportage

Bij het verzenden van een factuur handelt de PSB ook de fiscale rapportage af. In het kader van de ViDA-richtlijn (VAT in the Digital Age) genereert de PSB automatisch een DRR (Digital Reporting Requirement) op basis van de factuurgegevens en stuurt deze naar de relevante belastingdienst. Je hoeft hier als integrator niets voor te doen: de DRR wordt afgeleid uit dezelfde factuur die je via het reguliere endpoint verstuurt. Statusberichten en CTC-rapportageberichten zijn inbegrepen in de documentprijs.

Geavanceerde opties
Kanaal forceren

Standaard kiest de PSB automatisch het beste kanaal. Met de ?channel={hookId} queryparameter kun je een specifiek afleverkanaal forceren (bijv. een specifiek netwerk of e-mail fallback).

Bijlagen meesturen

Bijlagen (PDF, afbeeldingen) kun je als AdditionalDocumentReference in het UBL-document embedden als base64. De PSB verwerkt embedded bijlagen correct en levert ze samen met de factuur af.

Let op: het send endpoint accepteert maximaal 24 MB per request (inclusief HTTP-overhead). Bij base64-gecodeerde bijlagen groeit de payload met circa 33%, dus een PDF van 18 MB resulteert in een request van circa 24 MB. Payloads die de limiet overschrijden worden door de webserver afgewezen met HTTP 500 (niet 413), nog vóór de applicatievalidatie plaatsvindt. Verklein grote bijlagen of verzend ze via een apart kanaal.

Tip: de huidige Peppol BIS Billing 3.0-standaard ondersteunt maximaal één OrderReference per factuur. Heeft een factuur betrekking op meerdere orders, dan moeten er meerdere facturen worden verstuurd.

Tip: sommige ontvangers melden fouten bij facturen met een XML namespace prefix (bijv. <urn:Invoice> in plaats van <Invoice>). Beide vormen zijn technisch correcte XML volgens de W3C-specificatie. Als een ontvanger dit als reden voor afwijzing opgeeft, is dat geen geldige weigering binnen het Peppol-netwerk. De ontvanger moet een XML-parser gebruiken die zowel prefixed als default namespaces correct verwerkt.

Veelgestelde vragen
In welk formaat lever ik mijn factuur aan?

Je kunt aanleveren in elk formaat dat de PSB ondersteunt: UBL 2.1, NLCIUS, BIS Billing V3, PINT, CII, XRechnung, Factur-X, FatturaPA, ebInterface, Svefaktura, DICO, SETU en meer. Post het XML-document als body naar POST /api/v1/{partyId}/salesInvoice/send met Content-Type: application/xml. De PSB detecteert het formaat automatisch, valideert het en transformeert het naar het formaat dat de ontvanger verwacht. De ontvanger wordt bepaald via het EndpointID in je XML.

Hoe voorkom ik dubbele verzending en wat betekent 409 Conflict?

Stuur bij elke upload de header X-EConnect-DocumentId met een eigen UUID. Herhaal je hetzelfde documentId, dan antwoordt de API met 409 Conflict en weet je dat het document al is verwerkt. Gebruik nooit het factuurnummer als documentId, want bij een gecorrigeerde herverzending moet je een nieuw id kunnen gebruiken.

Hoe volg ik de afleverstatus en wat gebeurt bij tijdelijke fouten?

Na een succesvolle upload retourneert de API een document-ID in de PSB waarmee je de status via API of webhooks kunt volgen. Bij tijdelijke 5xx-fouten aan de ontvangende kant publiceert de PSB per poging een InvoiceSentRetry-event en probeert ze tot 8 keer over circa 35 uur; bij definitief falen ontvang je een InvoiceSentError-event.


Wil je eerst testen of je document valide is? Gebruik de Validate API.

Probeer het in de API

Gerelateerd