Factuurgeneratie-API

Genereer programmatisch professionele factuur-PDF's vanaf uw eigen server — geschikt voor interne systemen, marktplaatsen of uw eigen SaaS-product.

1. Authenticatie#

Maak een API-sleutel aan op app.invosend.com/settings/api-keys. Een betaald werkruimteplan en eigenaarsrol zijn vereist.

Verstuur de sleutel als Bearer-token in de Authorization-header bij elk verzoek:

Authorization: Bearer isk_live_xxxxxxxxxxxxxxxxxxxxxxxx
Ontbrekende, verkeerd opgemaakte, ongeldige of ingetrokken API-sleutels worden geweigerd met 403. Sleutels worden ook geweigerd als de werkruimte een gratis plan heeft, is opgeschort of is verlopen.

2. Endpoint#

POST/api/invoices/generate-external

Basis-URL: https://app.invosend.com

Machineleesbare API-beschrijving: OpenAPI 3.1 en Postman collection. Importeer een van beide in Postman, Insomnia of een SDK-generator.

3. Aanvraagbody#

VeldTypeVerplichtBeschrijving
customer_namestringJaNaam van de klant of factuurontvanger.
customer_emailstringNeeGeldig e-mailadres. De met deze aanroep aangemaakte factuur wordt niet per e-mail verstuurd (deze API verstuurt geen e-mails). Verplicht voor terugkerende facturen: elke daarna gegenereerde factuur wordt naar dit adres gestuurd.
customer_tax_idstringNeeBelastingnummer van de klant (NPWP in Indonesië, maximaal 40 tekens). Wordt op de factuur onder het adres van de klant afgedrukt.
itemsarrayJaMinstens 1 geldig item met beschrijving, quantity > 0, en price >= 0.
items[].descriptionstringNeeNaam van het product of de dienst. Indien leeg wordt Item gebruikt.
items[].quantitynumberJaAantal eenheden, met maximaal 2 decimalen (bijvoorbeeld 1.5 uur), van 0.01 tot 999.999.
items[].pricenumberJaPrijs per eenheid.
items[].discountnumberNeeKortingsbedrag per item. Standaard 0.
currencystringNeeValutacode zoals IDR of USD. Standaard IDR.
tax_ratenumberNeeBelastingpercentage berekend over het subtotaal na korting. Standaard 0.
due_datestringNeeFormaat YYYY-MM-DD. Standaard 14 dagen na aanmaak.
notesstringNeeAanvullende notities die op de factuur worden getoond.
items[].unitstringNeeEenheidslabel naast de hoeveelheid, zoals pcs of hour.
items[].tax_ratenumberNeeItem-specifieke belastingpercentage-override (0-100). Weglaten om het factuurbrede tax_rate voor dat item te gebruiken.
discount_totalnumberNeeFactuurbrede korting. Wordt vóór belasting in mindering gebracht, dus de belasting wordt berekend over het bedrag na korting (naar waarde verdeeld over de regels). Standaard 0.
templatestringNeeID van het te gebruiken factuursjabloon. De beschikbare sjablonen vind je met GET /api/invoices/external/templates. Zonder deze waarde wordt het in Instellingen gekozen standaardsjabloon gebruikt, daarna dat van Invosend.
document_languagestringNeeTaal van de woorden in het factuurdocument (pdf en e-mail): en (standaard), id, es, fr, de, nl, it, pt, zh, ja, hi, ar (Indonesisch, Spaans, Frans, Duits, Nederlands, Italiaans, Braziliaans Portugees, vereenvoudigd Chinees, Japans, Hindi, Arabisch). Elke andere waarde wordt met een foutmelding geweigerd. De eenvoudige ingebouwde opmaak, die alleen wordt gebruikt als er geen sjabloon bestaat, is altijd Engels.
custom_payment_notesstringNeeExtra betalingsinstructies die op de PDF worden getoond.
footer_textstringNeeKorte tekst onderaan de PDF.
is_recurringbooleanNeeMaakt een terugkerende reeks. Deze factuur is de eerste; de volgende worden automatisch volgens schema gegenereerd en naar customer_email gestuurd, elk met 1 factuurtegoed. Vereist een abonnement met de functie voor terugkerende facturen, plus recurring_interval en customer_email.
recurring_intervalstringNeeHoe vaak de reeks zich herhaalt: een van weekly, fortnightly, monthly, quarterly, semi-annually, yearly. Verplicht wanneer is_recurring true is.
recurring_countintegerNeeTotaal aantal facturen in de reeks, inclusief deze eerste: een geheel getal van 2 tot 121. Standaard 4. Gebruik dit veld of recurring_end_date, niet beide.
recurring_end_datestringNeeDatum waarna er geen facturen meer worden gegenereerd, YYYY-MM-DD, in de toekomst. Gebruik dit veld of recurring_count, niet beide.
payment_gatewaystringNeeEen van midtrans, xendit, stripe, paypal, razorpay, mollie. De gateway moet al zijn verbonden in de werkruimte.
payment_accountstringNeeID van een bestaand betaalaccount (bankgegevens) om aan de factuur te koppelen.

Volledig verzoekvoorbeeld:

curl -X POST https://app.invosend.com/api/invoices/generate-external \
  -H "Authorization: Bearer isk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_name": "Acme Corp",
    "customer_email": "billing@acme.com",
    "items": [
      { "description": "Consulting Services", "quantity": 2, "price": 500, "tax_rate": 11 }
    ],
    "discount_total": 50,
    "currency": "EUR",
    "notes": "Thank you for your business."
  }'

Voorbeeld van een terugkerende factuur (de eerste nu, daarna elke maand één, in totaal 6):

curl -X POST https://app.invosend.com/api/invoices/generate-external \
  -H "Authorization: Bearer isk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_name": "Acme Corp",
    "customer_email": "billing@acme.com",
    "items": [
      { "description": "Monthly retainer", "quantity": 1, "price": 2500 }
    ],
    "currency": "EUR",
    "recurring_interval": "monthly",
    "recurring_count": 6
  }'
Om veilig opnieuw te proberen na een time-out of netwerkfout, voegt u een Idempotency-Key-header toe (1-255 tekens, bijvoorbeeld een UUID die u per factuur genereert). Als het eerste verzoek is gelukt, geeft de nieuwe poging hetzelfde antwoord terug met de header Idempotent-Replayed: true, zonder nog een factuur te maken of nog een tegoed te gebruiken (credits_remaining is de waarde van de eerste aanroep). Sleutels worden 24 uur per werkruimte bewaard. Alleen geslaagde antwoorden worden opgeslagen, dus een mislukt verzoek kunt u met dezelfde sleutel opnieuw proberen.

4. Antwoord#

200 OK betekent dat de factuur is aangemaakt en de PDF is gegenereerd:

{
  "data": {
    "id": "cjld2cjxh0000qzrmn831i7rn",
    "invoice_number": "INV-1-202609-0016",
    "pdf_url": "https://cdn.invosend.com/company/1/pdf/Invoice_INV_1_202609_0016_UNPAID_0da2beeabb.pdf",
    "credits_remaining": 24,
    "is_recurring": false,
    "template": {
      "id": "k3p9x2m7c0000abcd1234efgh",
      "name": "Classic",
      "source": "system_default"
    }
  }
}
credits_remaining is null wanneer de werkruimte een onbeperkt quotum heeft. id identificeert deze factuur voor de onderstaande aanvullende endpoints. Facturen die via deze API zijn aangemaakt, verschijnen ook in de factuurlijst van de werkruimte en gebruiken dezelfde factuurnummerreeks als handmatig aangemaakte facturen. Factuurnummers hebben de vorm INV-{workspace-id}-{JJJJMM}-{volgnummer}. Bij een terugkerende factuur bevat het antwoord ook een recurring-object: schedule_id, interval, occurrences, next_issue_date, end_date. recurring.schedule_id is de id die u met de terugkerende endpoints hieronder gebruikt.

5. Foutcodes#

StatusOorzaak
400Verplichte velden ontbreken of zijn ongeldig: customer_name, lege items, geen geldig item, een onbekende payment_gateway, een payment_gateway die niet is gekoppeld voor deze workspace of, bij een terugkerende factuur, een ontbrekende recurring_interval of customer_email, of een ongeldige recurring_count / recurring_end_date. Deze status wordt ook teruggegeven als de pdf niet kon worden gemaakt: probeer het verzoek opnieuw (er wordt geen tegoed afgeschreven).
402Het invoice_credits-saldo van de werkruimte is op. Laad tegoed op om door te gaan.
403De Authorization-header ontbreekt of is verkeerd opgemaakt, de API-sleutel is ongeldig of ingetrokken, of het werkruimteplan bevat geen API-toegang.
403 (terugkerend)is_recurring was ingesteld, maar het werkruimteplan bevat geen terugkerende facturen.
409Een verzoek met dezelfde Idempotency-Key wordt nog verwerkt. Probeer het zo meteen opnieuw.
422De Idempotency-Key is al gebruikt met een andere verzoekbody. Gebruik een nieuwe sleutel voor een nieuwe factuur.
429Rate limit overschreden. Zie de sectie Rate limit.

6. Rate limit#

BereikLimiet
Per workspace (alle API-verzoeken samen)Professional 10/min · Specialist 20/min · Business 30/min · Enterprise 60/min
Per IP-adres (alle API-verzoeken samen)30 aanvragen/minuut
Actieve API-sleutels per workspaceProfessional 3 · Specialist 5 · Business 10 · Enterprise 20
Facturen genereren en de lees-/beheerendpoints delen dezelfde limiet. Succesvolle antwoorden bevatten de headers X-RateLimit-Limit en X-RateLimit-Remaining. API-quota van de workspace worden per lidmaatschapsabonnement in Invosend ingesteld. Meer productievolume nodig? Neem contact met ons op via uw workspace-account. Ingetrokken sleutels tellen niet mee voor de sleutellimiet.

7. Aanvullende endpoints#

Dezelfde API-sleutel kan ook facturen lezen en beheren die via generate-external zijn aangemaakt:

MethodePadBeschrijving
GET/api/invoices/externalLijst facturen voor deze werkruimte. Ondersteunt ?status= en ?page=/?pageSize= queryparameters.
GET/api/invoices/external/templatesToont de factuursjablonen die je in template kunt opgeven, of je abonnement ze toestaat en welke de standaard is.
GET/api/invoices/external/:idHaal één factuur op via de id (de waarde die door generate-external wordt geretourneerd).
PUT/api/invoices/external/:id/statusWerk de factuurstatus bij. Body: { "status": "paid" } (een van unpaid, paid, overdue, cancelled).
PUT/api/invoices/external/:id/archiveArchiveer of dearchiveer een factuur. Body: { "is_archived": true }.
POST/api/invoices/external/:id/pdfHaal de PDF-URL opnieuw op en genereer deze indien nodig opnieuw. Body: { "force": true } om regeneratie te forceren.
GET/api/invoices/external/recurringToont terugkerende reeksen. Ondersteunt ?status= (active, paused, completed) en ?page=/?pageSize=.
GET/api/invoices/external/recurring/:idHaalt één reeks op (de recurring.schedule_id die generate-external teruggeeft) met alle herhalingen: datum, status en de id van de factuur die elke herhaling heeft opgeleverd.
PUT/api/invoices/external/recurring/:id/statusPauzeert of hervat een reeks. Body: { "status": "paused" } of { "status": "active" }. Hervatten vereist een abonnement met terugkerende facturen.
PUT/api/invoices/external/recurring/:id/extendVoegt herhalingen toe na de laatste. Body: { "count": 3 } of { "end_date": "2027-12-31" }.
PUT/api/invoices/external/recurring/:id/frequencyWijzigt hoe vaak de reeks zich herhaalt; komende herhalingen die nog niet zijn aangemaakt worden vervangen. Body: { "frequency": "monthly", "start_date": "2027-01-01", "count": 6 } (gebruik eventueel end_date in plaats van count; start_date moet in de toekomst liggen).
POST/api/invoices/external/recurring/:id/skipVerwijdert één komende herhaling. Body: { "date": "2027-01-01" }. Herhalingen die al een factuur hebben opgeleverd kunnen niet worden verwijderd.
Om een online betaling te ontvangen, stelt u payment_gateway (en optioneel payment_account) in bij generate-external en stuurt u uw klant de openbare betaalpagina van de factuur: https://app.invosend.com/p/invoice/{id}, met de id die de API teruggeeft. Daar betaalt de klant via de gekoppelde gateway en wordt de factuur automatisch als betaald gemarkeerd. De checkout wordt door die pagina afgehandeld; er is geen apart openbaar checkout-endpoint om aan te roepen.

8. Webhooks#

Registreer in plaats van te pollen een HTTPS-URL: Invosend stuurt er een POST-verzoek met JSON-body naartoe wanneer een factuur verandert. Voeg endpoints toe via Instellingen > Webhooks (eigenaar van de werkruimte, abonnement met API-toegang, maximaal 5 endpoints). Elk endpoint heeft een eigen handtekeninggeheim, dat maar één keer wordt getoond.

Gebeurtenissen worden verstuurd voor facturen die in het dashboard en via deze API zijn gemaakt. Sjablonen van terugkerende reeksen worden nooit verstuurd.

GebeurtenisVerstuurd wanneer
invoice.createdEr wordt een factuur gemaakt. De pdf is mogelijk nog niet klaar, dus pdf_url kan null zijn.
invoice.paidDe status verandert in paid (door u, via de API of door een online betaling).
invoice.overdueDe status verandert in overdue (automatisch na de vervaldatum, of handmatig).
invoice.cancelledDe status verandert in cancelled.

Elke gebeurtenis heeft dezelfde envelop. data.object is de factuur, in dezelfde vorm als GET /api/invoices/external/:id; statusgebeurtenissen bevatten ook data.previous_status:

{
  "id": "evt_9f2c1b7a4e3d5c6b8a1f0e2d",
  "object": "event",
  "type": "invoice.paid",
  "created": "2026-10-01T09:30:12.000Z",
  "data": {
    "object": {
      "id": "cjld2cjxh0000qzrmn831i7rn",
      "invoice_number": "INV-1-202610-0007",
      "customer_name": "Acme Corp",
      "customer_email": "billing@acme.com",
      "currency": "USD",
      "subtotal": 500,
      "discount_total": 0,
      "tax_rate": 0,
      "tax_amount": 0,
      "amount": 500,
      "amount_paid": 500,
      "amount_credited": 0,
      "amount_received": 500,
      "invoice_status": "paid",
      "is_archived": false,
      "is_recurring": false,
      "recurring_interval": "none",
      "issue_date": "2026-10-01T02:15:40.000Z",
      "due_date": "2026-10-15",
      "paid_at": "2026-10-01T09:30:11.000Z",
      "pdf_url": "https://cdn.invosend.com/company/1/pdf/Invoice_INV_1_202610_0007_PAID.pdf",
      "pdf_status": "ready"
    },
    "previous_status": "unpaid"
  }
}

Elk verzoek bevat deze headers. Om het te controleren berekent u een HMAC-SHA256 van {t}.{ruwe body} met het geheim van het endpoint en vergelijkt u dat met v1; weiger het verzoek als t ouder is dan 5 minuten:

POST /your/webhook/url
Content-Type: application/json
Invosend-Event: invoice.paid
Invosend-Delivery: evt_9f2c1b7a4e3d5c6b8a1f0e2d
Invosend-Signature: t=1790847012,v1=5b1d...e9a2

// Node.js
import crypto from "crypto";

function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(parts.t + "." + rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}
Antwoord binnen 10 seconden met een willekeurige 2xx-status. Anders wordt het tot 7 keer opnieuw geprobeerd (na 1 minuut, 5 minuten, 30 minuten, 2 uur, 6 uur, 12 uur en 24 uur). Een endpoint dat blijft falen wordt uitgeschakeld en u krijgt een melding. Een gebeurtenis kan meer dan eens of in andere volgorde binnenkomen: negeer duplicaten via de id van de gebeurtenis en beschouw invoice_status als leidend. Bezorglogboeken worden 30 dagen bewaard en elke gebeurtenis kunt u opnieuw versturen via Instellingen > Webhooks.

9. Beperkingen#

Deze API is bewust beperkt tot factuurgeneratie en lichte factuurbeheer. Het volgende is nog niet beschikbaar:

  • Webhooks omvatten alleen aangemaakte, betaalde, achterstallige en geannuleerde facturen. Andere wijzigingen, zoals bewerken of archiveren, worden niet verstuurd: lees de huidige status met GET /invoices/external/:id.
  • De factuur die met elk verzoek wordt aangemaakt, wordt niet per e-mail verstuurd: deze API genereert alleen de pdf, dus het bezorgen bij uw klant is aan u (of gebruik het dashboard). Uitzondering zijn terugkerende reeksen: elke vervolgfactuur die de planner genereert, wordt automatisch naar customer_email gestuurd.
  • Geen bewerking van een factuur na aanmaak — alleen de status en archiveringsstatus kunnen via deze API worden gewijzigd.
  • Ondersteuning voor betaalgateways vereist dat de gateway al is verbonden in het dashboard; deze API koppelt deze alleen aan de factuur, het verbindt geen gateway op zichzelf.
  • Een terugkerende reeks kan via de API worden gepauzeerd, hervat, verlengd, anders gepland en komende herhalingen kunnen worden overgeslagen, maar de inhoud (regels, klant, bedragen) kan niet worden bewerkt en de reeks kan niet via de API worden verwijderd; doe dat in het dashboard.

Veelgestelde vragen#

Hoe krijg ik een Invosend API-sleutel?

Maak een account aan op app.invosend.com, upgrade de werkruimte naar een betaald plan, open dan Settings > API Keys en klik op Generate key. De ruwe sleutel wordt slechts één keer getoond bij het aanmaken.

Hoeveel kost elke aanroep van de factuurgeneratie-API?

Elke succesvolle aanvraag trekt 1 factuurtegoed af van uw werkruimtesaldo. Het gebruikt dezelfde factuurtegoedpool als facturen die via het dashboard zijn aangemaakt.

Wat is de rate limit voor deze API?

De rate limit van de workspace volgt de configuratie van uw betaalde abonnement. In de sectie Rate Limit hierboven staat de actuele limiet per abonnement.