NumNum

Self-billing (purchase borderelle) via the API

These endpoints create issued purchase borderelles, known in Belgian VAT terms as self-billed invoices. This is a document your company draws up on behalf of a supplier (e.g. a milk-money settlement a dairy company issues for a dairy farmer).

Typical users: producers and cooperatives that periodically create settlements for their suppliers, or external systems that generate settlements and want to submit them to NumNum while keeping their own PDF layout.

ℹ️ Authentication (personal API token + X-Company-Id), limits and general error codes are in the Developer API overview. The headers and client matching are identical to the Invoice 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: purchase borderelle

A JSON array of borderelles (processed atomically). The structure resembles the Invoice API, with a few differences.

Field Type Required Description
language string Yes nl, fr, en or de
purchase_borderelle_date string Yes Document date YYYY-MM-DD
expire_days integer Yes Due days after the document date (0365)
reference string No Your own reference (e.g. period), max 255
intro string No Text above the lines, max 255
remarks string No Text below the lines, max 255
private_notes string No Internal note (not visible to the supplier), max 255
payment_info string No yes (default), no or paid
vat_shifted integer No See the vat_shifted table
attachment_pdf string No Base64-encoded PDF (your own layout, see below)
attachment_pdf_filename string No Filename for the attachment; default <borderelle-nr>.pdf
client object Yes The supplier you draw up the document for (same structure as the client in the Invoice API)
lines array Yes At least 1 line (note: lines, not invoice_lines)

Lines (lines)

"lines": [
  { "description": "Milk delivery 1–15 May (litre)", "unit_price": 0.45, "amount": 12500, "vat_percentage": 6 }
]

Same fields as an invoice line: description, unit_price, amount, vat_percentage. amount may be decimal (e.g. litre/kg). Totals are calculated server-side.

Attaching your own PDF (attachment_pdf)

Want to keep your own PDF layout? Send a base64-encoded PDF. It is stored as an attachment on the document and included in Peppol delivery. NumNum still generates a standard PDF from the document data as well.

  • Max size ± 15 MB (base64). Stay well below this.
  • If attachment_pdf_filename is missing, <borderelle-nr>.pdf is used.
  • Send only real PDFs; the content type is forced to application/pdf.
// Node.js
const fs = require('fs')
const pdfBase64 = fs.readFileSync('./milk-money-may-2026.pdf').toString('base64')

Request body: credit note

Almost identical to a borderelle, with these differences:

Field Description
purchase_borderelle_creditnote_date Document date (instead of purchase_borderelle_date)
purchase_borderelle_uuid Optional. UUID of an existing purchase borderelle within the same company, linked as the source. A UUID from another company returns 404
expire_days, payment_info Not applicable to credit notes

All other fields behave identically. Use negative or corrective amounts depending on your correction.

Example: milk-money settlement

curl -X POST https://app.numnum.be/api/v1/webhooks/create-purchase-borderelle \
  -H "Authorization: Bearer <your-api-token>" \
  -H "X-Company-Id: 12345" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '[
    {
      "language": "en",
      "purchase_borderelle_date": "2026-05-20",
      "expire_days": 30,
      "reference": "Milk money May 2026",
      "payment_info": "no",
      "client": {
        "company_type": "company",
        "type": "onbekend",
        "email": "farmer@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"
      },
      "lines": [
        { "description": "Milk delivery 1–15 May (litre)", "unit_price": 0.45, "amount": 12500, "vat_percentage": 6 },
        { "description": "Milk delivery 16–31 May (litre)", "unit_price": 0.46, "amount": 13200, "vat_percentage": 6 }
      ]
    }
  ]'

Example: credit note on a borderelle

curl -X POST https://app.numnum.be/api/v1/webhooks/create-purchase-borderelle-creditnote \
  -H "Authorization: Bearer <your-api-token>" \
  -H "X-Company-Id: 12345" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "language": "en",
      "purchase_borderelle_creditnote_date": "2026-05-21",
      "purchase_borderelle_uuid": "9c1a2b3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
      "reference": "Correction milk money May",
      "client": { "company_type": "company", "type": "onbekend", "email": "farmer@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" },
      "lines": [
        { "description": "Correction quality premium", "unit_price": -50.00, "amount": 1, "vat_percentage": 6 }
      ]
    }
  ]'

Response

HTTP 201: Created

Purchase borderelle:

{ "purchase_borderelles": [1234, 1235] }

Credit note:

{ "purchase_borderelle_creditnotes": [987] }

The array contains the internal database IDs in the same order as the input.

Errors

See the error table in the API overview. Validation errors follow the same invalid_body format as the Invoice API, indexed by position (0.client.email, 1.lines.0.unit_price, …). A purchase_borderelle_uuid from another company returns 404.

Difference from the Invoice API

Topic Invoice API Purchase borderelle API
Document type Sales invoice (outgoing) Issued purchase borderelle (on behalf of a supplier)
Client in payload The customer you invoice The supplier you draw up for
Date field invoice_date purchase_borderelle_date
Lines field invoice_lines lines
Own PDF attachment ✅ via attachment_pdf
Peppol InvoiceTypeCode 380 (invoice) 389 (self-billed)

Notes

  • Numbering: the borderelle number is generated automatically (typically with an AB prefix). You cannot supply your own number.
  • Not idempotent: sending the same payload twice creates two documents.
  • Received purchase borderelles (from a supplier) come in via Peppol; that is not a use case for this API.