NumNum

Self-billing (aankoopborderel) via de API

Met deze endpoints maak je uitgegeven aankoopborderellen aan, in het Belgische btw-jargon self-billed invoices. Dat is een document dat jouw bedrijf opstelt namens een leverancier (bv. een melkgeldafrekening die een zuivelbedrijf opstelt voor een melkveehouder).

Typische gebruikers: producenten en coöperaties die periodiek afrekeningen opstellen voor hun leveranciers, of externe systemen die afrekeningen genereren en in NumNum willen aanleveren met behoud van hun eigen PDF-layout.

ℹ️ Authenticatie (persoonlijke API-token + X-Company-Id), limieten en algemene foutcodes staan in het API-overzicht voor ontwikkelaars. De headers en klant-matching zijn identiek aan de Facturen-API.

Endpoints

POST https://app.numnum.be/api/v1/webhooks/create-purchase-borderelle
POST https://app.numnum.be/api/v1/webhooks/create-purchase-borderelle-creditnote

Request body: aankoopborderel

Een JSON-array van borderellen (atomair verwerkt). De structuur lijkt op de Facturen-API, met enkele verschillen.

Veld Type Verplicht Beschrijving
language string Ja nl, fr, en of de
purchase_borderelle_date string Ja Documentdatum JJJJ-MM-DD
expire_days integer Ja Vervaldagen na de documentdatum (0–365)
reference string Nee Eigen referentie (bv. periode), max 255
intro string Nee Tekst boven de regels, max 255
remarks string Nee Tekst onder de regels, max 255
private_notes string Nee Interne notitie (niet zichtbaar voor de leverancier), max 255
payment_info string Nee yes (standaard), no of paid
vat_shifted integer Nee Zie de vat_shifted-tabel
attachment_pdf string Nee Base64-gecodeerde PDF (eigen layout, zie hieronder)
attachment_pdf_filename string Nee Bestandsnaam voor de bijlage; standaard <borderel-nr>.pdf
client object Ja De leverancier namens wie je opstelt (zelfde structuur als klant in de Facturen-API, inclusief iban, iban_country_code en bic; zie Bankgegevens)
lines array Ja Minstens 1 en maximaal 500 regels (let op: lines, niet invoice_lines)

Regels (lines)

"lines": [
  { "description": "Melklevering 1–15 mei (liter)", "unit_price": 0.45, "amount": 12500, "vat_percentage": 6 }
]

Zelfde velden als een factuurlijn: description, unit_price, amount, vat_percentage. amount mag decimaal zijn (bv. liter/kg). Totalen worden server-side berekend.

IBAN en BIC van de leverancier

De IBAN van de leverancier is nodig om het borderel via Peppol te versturen: een aankoopborderel is een self-billing document en de Peppol-UBL moet de rekening van de leverancier bevatten (regel BR-61). Zonder IBAN wordt het document wél aangemaakt, maar weigert NumNum de Peppol-verzending. Stuur daarom iban (en bij voorkeur bic) mee in het client-object.

Beide schrijfwijzen zijn geldig en geven hetzelfde resultaat:

"client": { "iban_country_code": "BE", "iban": "82103021737768", "bic": "GKCCBEBB" }
"client": { "iban": "BE82 1030 2173 7768", "bic": "GKCCBEBB" }
  • Spaties, punten en streepjes mogen; ze worden verwijderd.
  • Stuur je zowel iban_country_code als een iban die zelf al met een landcode begint, dan moeten die overeenkomen. Botsen ze (bv. NL bij BE82…), dan krijg je 400 invalid_body.
  • Een ongeldig IBAN- of BIC-formaat geeft eveneens 400 invalid_body; de hele batch wordt dan geweigerd.
  • Bestaat de leverancier al en heeft die al een IBAN, dan blijft die ongewijzigd: bestaande bankgegevens worden nooit door de API overschreven. Lege velden worden wél aangevuld.
  • Vergeten? Je kan de IBAN achteraf aanvullen op de leveranciersfiche onder Financiële gegevens (zie Self-billing: hoe werkt het?).

Eigen PDF meesturen (attachment_pdf)

Wil je je eigen PDF-layout behouden? Stuur een base64-gecodeerde PDF mee. Die wordt als bijlage bewaard bij het document en meegenomen bij Peppol-verzending. NumNum genereert daarnaast nog steeds een standaard-PDF op basis van de documentdata.

  • Max grootte ± 15 MB (base64). Blijf hier ruim onder.
  • Ontbreekt attachment_pdf_filename, dan wordt <borderel-nr>.pdf gebruikt.
  • Stuur enkel echte PDF’s; het content-type wordt geforceerd op application/pdf.
// Node.js
const fs = require('fs')
const pdfBase64 = fs.readFileSync('./melkgeld-mei-2026.pdf').toString('base64')

Request body: creditnota

Vrijwel identiek aan een borderel, met deze verschillen:

Veld Beschrijving
purchase_borderelle_creditnote_date Documentdatum (in plaats van purchase_borderelle_date)
purchase_borderelle_uuid Optioneel. UUID van een bestaand aankoopborderel binnen hetzelfde bedrijf; wordt als bron gekoppeld. Een UUID van een ander bedrijf geeft 404
expire_days, payment_info Niet van toepassing op creditnota’s

Alle andere velden gedragen zich identiek. Gebruik negatieve of corrigerende bedragen naargelang je correctie.

Voorbeeld: melkgeldafrekening

curl -X POST https://app.numnum.be/api/v1/webhooks/create-purchase-borderelle \
  -H "Authorization: Bearer <jouw-api-token>" \
  -H "X-Company-Id: 12345" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '[
    {
      "language": "nl",
      "purchase_borderelle_date": "2026-05-20",
      "expire_days": 30,
      "reference": "Melkgeld mei 2026",
      "payment_info": "no",
      "client": {
        "company_type": "company",
        "type": "onbekend",
        "email": "boer@example.be",
        "first_name": "Jan",
        "last_name": "De Boer",
        "vat_country_code": "BE",
        "vat_id": "0123456789",
        "address": "Boerderijstraat 1",
        "address_zip": "9800",
        "address_city": "Deinze",
        "address_country": "BE",
        "iban_country_code": "BE",
        "iban": "82103021737768",
        "bic": "GKCCBEBB"
      },
      "lines": [
        { "description": "Melklevering 1–15 mei (liter)", "unit_price": 0.45, "amount": 12500, "vat_percentage": 6 },
        { "description": "Melklevering 16–31 mei (liter)", "unit_price": 0.46, "amount": 13200, "vat_percentage": 6 }
      ]
    }
  ]'

Voorbeeld: creditnota op een borderel

curl -X POST https://app.numnum.be/api/v1/webhooks/create-purchase-borderelle-creditnote \
  -H "Authorization: Bearer <jouw-api-token>" \
  -H "X-Company-Id: 12345" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "language": "nl",
      "purchase_borderelle_creditnote_date": "2026-05-21",
      "purchase_borderelle_uuid": "9c1a2b3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
      "reference": "Correctie melkgeld mei",
      "client": { "company_type": "company", "type": "onbekend", "email": "boer@example.be", "first_name": "Jan", "last_name": "De Boer", "vat_country_code": "BE", "vat_id": "0123456789", "address": "Boerderijstraat 1", "address_zip": "9800", "address_city": "Deinze", "address_country": "BE", "iban_country_code": "BE", "iban": "82103021737768", "bic": "GKCCBEBB" },
      "lines": [
        { "description": "Correctie kwaliteitspremie", "unit_price": -50.00, "amount": 1, "vat_percentage": 6 }
      ]
    }
  ]'

Response

HTTP 201: Aangemaakt

Aankoopborderel:

{ "purchase_borderelles": [1234, 1235] }

Creditnota:

{ "purchase_borderelle_creditnotes": [987] }

De array bevat de interne database-ID’s in dezelfde volgorde als de input.

Fouten

Zie de foutentabel in het API-overzicht. Validatiefouten volgen hetzelfde invalid_body-formaat als de Facturen-API, geïndexeerd per positie (0.client.email, 1.lines.0.unit_price, …). Een purchase_borderelle_uuid van een ander bedrijf geeft 404.

Verschil met de Facturen-API

Onderwerp Facturen-API Aankoopborderel-API
Documenttype Verkoopfactuur (uitgaand) Uitgegeven aankoopborderel (namens leverancier)
Klant in payload Klant aan wie je factureert Leverancier namens wie je opstelt
Datumveld invoice_date purchase_borderelle_date
Regelveld invoice_lines lines
Eigen PDF-bijlage ❌ ✅ via attachment_pdf
Peppol InvoiceTypeCode 380 (factuur) 389 (self-billed)

Aandachtspunten

  • Nummering: het borderelnummer wordt automatisch gegenereerd (typisch met AB-prefix). Je kan geen eigen nummer meesturen.
  • Niet idempotent: dezelfde payload tweemaal versturen maakt tweemaal een document aan.
  • Peppol vereist een IBAN: zonder client.iban wordt het borderel aangemaakt maar niet via Peppol verzonden. Zie Bankgegevens.
  • Ontvangen aankoopborderellen (van een leverancier) komen binnen via Peppol; dat is geen use-case voor deze API.