Connect PeppolKit through the API
Does your webshop run on your own system, or on a platform we have no plugin for? Send every paid order to the API. PeppolKit makes the invoice, mails it to your customer and sends it over Peppol.
What you need
- An account. Make it for free on the start page and choose Own system (API). You get a sign-in link by e-mail; there is no password.
- Your company details. Fill them in in the dashboard under Settings: name, address, VAT number and company registration number. Without them the API refuses an order.
- A key. In the dashboard go to API and click Make a key. You see it once. Keep it on your server, like a password.
How to call the API
Every call goes to https://app.peppolkit.com/api/v1, over https, with your key in the Authorization header. You send and receive JSON. A first test:
curl https://app.peppolkit.com/api/v1/settings \
-H "Authorization: Bearer pk_your_key"
When something goes wrong you get an error code and an error field with the reason:
401the key is missing or wrong.409your company details are not filled in yet.422the order or refund is not valid;issuessays per field what is wrong.402the limit of your plan is reached. The order waits and gets its invoice after an upgrade or at the start of next month.
Send an order
Send an order as soon as it is paid, with POST /orders. The shape is that of a Shopify order, so existing code and examples can be reused. Save this as order.json:
{
"id": 1042,
"name": "#1042",
"currency": "EUR",
"taxes_included": true,
"created_at": "2026-11-13T10:15:00+01:00",
"email": "inkoop@klant.be",
"billing_address": {
"name": "An Peeters",
"company": "Klant BV",
"address1": "Kerkstraat 1",
"zip": "9000",
"city": "Gent",
"country_code": "BE"
},
"line_items": [
{
"id": 1,
"title": "Kettingset 11-speed",
"sku": "KS-11",
"quantity": 2,
"price": "39.00",
"tax_lines": [{ "rate": 0.21, "price": "13.54" }]
}
],
"shipping_lines": [
{ "title": "Verzending", "price": "6.95", "tax_lines": [{ "rate": 0.21, "price": "1.21" }] }
],
"note_attributes": [{ "name": "VAT number", "value": "BE0123456749" }],
"total_price": "84.95"
}
And send it:
curl -X POST https://app.peppolkit.com/api/v1/orders \
-H "Authorization: Bearer pk_your_key" \
-H "Content-Type: application/json" \
-d @order.json
The fields
idthe number of the order in your system, a whole number. Sending the sameidagain makes no second invoice: you get the existing one back withstatus: "exists".namethe order number as your customer sees it, for example#1042.currencythree letters, for exampleEUR.taxes_includedtruewhen prices include VAT,falsewhen they exclude it.created_atdate and time of the order (ISO 8601).emailthe address the invoice goes to.billing_addressname, company, address, postcode, city and country (country_code, two letters).shipping_addressmay be added, in the same shape.line_itemsat least one line, withid,title,quantity, the unit pricepriceand the VAT of the whole line intax_lines(rateas a fraction: 0.21 is 21%). A discount on a line goes indiscount_allocations, as[{"amount": "5.00"}].shipping_linesthe shipping costs, in the same shape.note_attributesthe VAT number of a business customer, under the nameVAT number. With that number it becomes a business invoice.total_pricethe total the customer paid.
Amounts are text with a dot as the decimal separator ("39.00"), never a rounded number. Fields PeppolKit does not know are ignored.
The answer holds the invoice, with links to the pdf and the UBL file that work for 30 days. The VAT number in this example does not exist; send it as it is and warnings says that VIES does not know it.
{
"ok": true,
"status": "issued",
"warnings": [],
"invoice": {
"number": "2026-00042",
"type": "invoice",
"orderId": "1042",
"issueDate": "2026-11-13",
"total": 84.95,
"currency": "EUR",
"peppolStatus": "sent",
"emailedAt": "2026-11-13T09:15:04.000Z",
"emailTo": "inkoop@klant.be",
"emailError": null,
"pdfUrl": "https://app.peppolkit.com/i/…",
"ublUrl": "https://app.peppolkit.com/i/…?format=xml",
"warnings": []
}
}
VAT and Peppol
From the customer's country, the VAT number and your settings, PeppolKit works out how the invoice is drawn up: normal VAT, reverse charge or OSS. The VAT number is checked in VIES. If the outcome differs from what your shop charged, or the number is not valid, you read that in warnings. If your customer has a Peppol address and sending is on, the invoice also goes over Peppol; peppolStatus says how that went (sent, pending, not_on_peppol or failed); when the invoice did not go over Peppol the field is empty (null).
Send a refund
When you pay a customer back, send that with POST /refunds. PeppolKit makes a credit note against the invoice of that order. line_item_id points at the id of the line in the order; the amount you paid back goes in transactions.
curl -X POST https://app.peppolkit.com/api/v1/refunds \
-H "Authorization: Bearer pk_your_key" \
-H "Content-Type: application/json" \
-d '{
"refund": {
"id": 7001,
"order_id": 1042,
"created_at": "2026-11-20T14:00:00+01:00",
"refund_line_items": [{ "line_item_id": 1, "quantity": 1 }],
"transactions": [{ "kind": "refund", "status": "success", "amount": "39.00" }]
}
}'
Sending the same id again makes no second credit note. If there is no invoice for the order, you get 404.
Fetch invoices
GET /invoices?orderId=… gives you the invoice and the credit notes of one order. Without orderId you get the latest 50 documents. lang (nl, fr or en) sets the language of the warnings. The answer is {"invoices": […]}, with the same fields per document as above; type is invoice or credit_note.
curl "https://app.peppolkit.com/api/v1/invoices?orderId=1042&lang=en" \
-H "Authorization: Bearer pk_your_key"
Company details through the API
The settings of the dashboard can also be read (GET /settings) and written (PUT /settings) through the API. Useful when you connect several shops.
curl -X PUT https://app.peppolkit.com/api/v1/settings \
-H "Authorization: Bearer pk_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Velo Atelier BV",
"street": "Dorpsstraat 1",
"postalCode": "9000",
"city": "Gent",
"country": "BE",
"vatNumber": "BE0123456749",
"registrationNumber": "0123456749",
"email": "info@veloatelier.be",
"language": "auto",
"emailCustomers": true,
"peppolSend": true
}'
Test first
Want to try without anything going over the real Peppol network? Make a second account with an address that ends in .test, for example myshop.test. Such an account makes real invoices and pdfs, but never sends over Peppol. Also switch off Email the invoice to the customer automatically in the settings, or use your own e-mail address in the test orders.
Frequently asked questions
What does the API cost?
Nothing extra. You use the same plan as any other shop: free up to 20 invoices a month, then from €9 a month. For Belgian shops Peppol is in every plan.
Can I replace the key later?
Yes, in the dashboard under API. The old key stops working at once, so have your system ready for the new one first.
What if my system sends an order twice?
Nothing is doubled. An order with the same id gets one invoice, and a refund with the same id one credit note.
My webshop runs on a platform that is not listed here. Does that work too?
Yes. The API is there for the platforms we have no plugin for. Your developer passes on every paid order; the rest follows automatically. For Magento 2 there is a module: see Install PeppolKit in Magento 2.
PeppolKit by platform: Shopify, WooCommerce, PrestaShop, Magento, Drupal Commerce, OpenCart, Shopware, Joomla, bol.com, Lightspeed, CCV Shop, Wix and Stripe. See how it works for your webshop.
Leave Peppol to PeppolKit.
Install PeppolKit and your business customers get their invoice over Peppol, without you having to deal with the network.
Choose your platform Start free with 20 invoices a month.An explanation for orientation, not tax advice.