4invoices ontwikkelaars-API

REST over HTTPS, JSON, publieke OpenAPI-specificatie. Facturatie, klanten, reeksen en de volledige nationale e-factureringsroute (ANAF e-Factura in Roemenië) — vanuit je ERP, webshop of CRM.

De publieke 4invoices-API stuurt factuurgegevens vanuit je systeem naar 4invoices en brengt de factuur volledig door het nationale e-factureringssysteem (in Roemenië: het SPV van ANAF). Één productiehost, één client_credentials-flow, idempotente fiscale writes en één foutenvelop op elke route.

https://api.4invoices.net/v1 · OpenAPI-specificatie (zonder sleutel)

Wat de 4invoices-API is

  • De publieke API van 4invoices is REST over HTTPS, met JSON als invoer en JSON als uitvoer.
  • Eén productiehost: https://api.4invoices.net/v1. Er is geen aparte testhost.
  • De OpenAPI 3.1-specificatie is openbaar en vereist geen sleutel — importeer haar rechtstreeks in Postman of in een clientgenerator.
  • Elke respons bevat een X-Request-Id-header; vermeld die wanneer u om ondersteuning vraagt.
  • Elke fiscale schrijfbewerking is idempotent: een nieuwe poging na een time-out geeft nooit een tweede document uit.
Alleen server-to-server. Roep de API nooit aan vanuit browser-JavaScript: het client_secret zou bij de bezoeker terechtkomen, en CORS blokkeert elke origin toch al.
  • De volledige cyclus van het nationale e-factureringssysteem via de API (in Roemenië: ANAF e-Factura): precontrole, indiening, opvolging, ondertekend antwoord en de inkomende inbox. Geen enkele Roemeense concurrent biedt dit.
  • SmartBill heeft geen enkel endpoint voor indiening bij het nationale e-factureringssysteem (ANAF, in Roemenië) — verzending is een accountinstelling die alleen in de interface bestaat — en helemaal geen endpoint om facturen op te vragen.
  • Oblio kan klanten en producten alleen aanmaken als neveneffect van het uitgeven van een document, niet als volwaardige bronnen.
  • Generatie van UBL / CIUS-RO-XML (Roemenië) zonder indiening: u krijgt het wettelijke document als bestand zonder het nationale e-factureringssysteem aan te raken.
  • Idempotentie bij fiscale schrijfbewerkingen: een nieuwe poging na een time-out levert geen tweede factuur op en verbruikt geen tweede nummer.
  • Een programmatisch leesbare inbox met leveranciersfacturen — de basis voor geautomatiseerde afstemming.

Je eerste factuur in 6 stappen

Voor je eerste call
  1. Maak een credential aan in het paneel, onder Facturatie → Instellingen → API-toegang, en kopieer het client_secret — het wordt één keer getoond.
  2. Vul het bedrijfsprofiel aan en activeer minstens één reeks van het type fiscale, anders geeft het uitgeven issuer_profile_incomplete of no_series_configured terug.
  1. Maak een credential aan in het paneel, onder Facturatie → Instellingen → API-toegang, en kopieer het client_secret — het wordt één keer getoond.
  2. Vul het bedrijfsprofiel aan en activeer minstens één reeks van het type fiscale, anders geeft het uitgeven issuer_profile_incomplete of no_series_configured terug.
  3. Wissel het credential in voor een token: POST /v1/auth/token met grant_type client_credentials. Het token geldt één uur — cache het, vraag er niet één per request aan.
  4. Geef de factuur uit: POST /v1/invoices met een Idempotency-Key-header en vat_rate als percentage (21, niet 0.21).
  5. Voer de preflight (CIUS-RO voor Roemenië) uit met POST /v1/invoices/{id}/efactura/validate en stuur de factuur daarna naar het nationale e-factureringssysteem (in Roemenië: ANAF) met POST /v1/invoices/{id}/efactura/submit.
  6. Volg de status met GET /v1/efactura/submissions/{id} tot die accepted of rejected bereikt.
bash
# 1 — token (1 uur, cache het)
ACCESS_TOKEN=$(curl -sS -X POST https://api.4invoices.net/v1/auth/token \
  -H 'Content-Type: application/json' \
  -d '{"grant_type":"client_credentials","client_id":"cli_XXX","client_secret":"sec_XXX"}' \
  | python3 -c 'import sys,json; print(json.load(sys.stdin)["access_token"])')

# 2 — de factuur uitgeven (Idempotency-Key is VERPLICHT)
curl -sS -X POST https://api.4invoices.net/v1/invoices \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-10457-invoice' \
  -d '{"buyer":{"name":"Exemplu Comert SRL","tax_id":"RO12345678","county":"Cluj","city":"Cluj-Napoca","country":"RO"},
       "lines":[{"description":"Abonament SaaS","quantity":1,"unit_price":400,"vat_rate":21}]}'

# 3 — preflight CIUS-RO, then send to ANAF
curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/validate \
  -H "Authorization: Bearer $ACCESS_TOKEN"

curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/submit \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Idempotency-Key: efactura-inv_01J7ABC-1'
javascript
const BASE = "https://api.4invoices.net/v1";

const token = await fetch(`${BASE}/auth/token`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    grant_type: "client_credentials",
    client_id: process.env.FOURINVOICES_CLIENT_ID,
    client_secret: process.env.FOURINVOICES_CLIENT_SECRET,
  }),
}).then((r) => r.json()).then((d) => d.access_token);

const invoice = await fetch(`${BASE}/invoices`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
    "Content-Type": "application/json",
    "Idempotency-Key": `order-${orderId}-invoice`,
  },
  body: JSON.stringify({
    buyer: { name: "Exemplu Comert SRL", tax_id: "RO12345678", county: "Cluj", city: "Cluj-Napoca", country: "RO" },
    lines: [{ description: "Abonament SaaS", quantity: 1, unit_price: 400, vat_rate: 21 }],
    currency: "RON",
    metadata: { order_id: String(orderId) },
  }),
}).then((r) => r.json());

console.log(invoice.number, invoice.totals); // "FCT-000123" { net, vat, gross }
python
import os, uuid, requests

BASE = "https://api.4invoices.net/v1"

token = requests.post(f"{BASE}/auth/token", json={
    "grant_type": "client_credentials",
    "client_id": os.environ["FOURINVOICES_CLIENT_ID"],
    "client_secret": os.environ["FOURINVOICES_CLIENT_SECRET"],
}, timeout=30).json()["access_token"]

headers = {
    "Authorization": f"Bearer {token}",
    # Eén sleutel per LOGISCHE bewerking — hergebruik die bij een retry, genereer nooit een nieuwe.
    "Idempotency-Key": f"order-{order_id}-invoice",
}

invoice = requests.post(f"{BASE}/invoices", headers=headers, json={
    "buyer": {"name": "Exemplu Comert SRL", "tax_id": "RO12345678",
              "county": "Cluj", "city": "Cluj-Napoca", "country": "RO"},
    "lines": [{"description": "Abonament SaaS", "quantity": 1,
               "unit_price": 400, "vat_rate": 21}],   # percentage, niet 0.21
    "currency": "RON",
}, timeout=60).json()

print(invoice["number"], invoice["totals"])

Authenticatie

  • De flow is client_credentials: u wisselt client_id + client_secret in voor een Bearer-access_token.
  • Het token verloopt na 3600 seconden. Vernieuw het vóór het verloopt, niet bij elke aanroep — POST /auth/token heeft een eigen rate limit per IP.
  • Het client_secret wordt alleen als hash opgeslagen en kan niet worden hersteld. Raakt u het kwijt, dan maakt u een nieuwe credential aan en trekt u de oude in.
  • Uitsluitend server-to-server. CORS laat geen enkele browser-origin toe: vanuit JavaScript op een pagina zou het secret uitlekken naar de bezoeker.
  • Scopes worden per credential toegekend. Geef elk systeem een aparte credential, met alleen de minimale scopes die het nodig heeft.

Facturatie → Instellingen → API-toegang

bash
curl -sS -X POST https://api.4invoices.net/v1/auth/token \
  -H 'Content-Type: application/json' \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "cli_XXXXXXXXXXXX",
    "client_secret": "sec_XXXXXXXXXXXXXXXXXXXX"
  }'

# → {"access_token":"eyJ...","token_type":"Bearer","expires_in":3600,
#    "scope":"invoices:read invoices:write efactura:submit"}
javascript
// Cache het token; vraag niet bij elk request een nieuw aan.
let cached = { token: "", expiresAt: 0 };

async function getToken() {
  if (cached.token && Date.now() < cached.expiresAt - 60_000) return cached.token;

  const res = await fetch("https://api.4invoices.net/v1/auth/token", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      grant_type: "client_credentials",
      client_id: process.env.FOURINVOICES_CLIENT_ID,
      client_secret: process.env.FOURINVOICES_CLIENT_SECRET,
    }),
  });
  if (!res.ok) throw new Error(`token ${res.status}`);

  const data = await res.json();
  cached = { token: data.access_token, expiresAt: Date.now() + data.expires_in * 1000 };
  return cached.token;
}

Btw-tarieven zijn percentages

vat_rate: 21 ✓  ·  vat_rate: 0.19 ✗  ·  vat_rate: 1 ✗
  • vat_rate is een PERCENTAGE: 21 betekent 21%.
  • Waarden in (0, 1] worden geweigerd — 0.19 is een breuk, en 1 is dubbelzinnig tussen 1% en 100%.
  • 0 is geldig en betekent vrijgesteld of verlegd; zet de wettelijke vermelding in notes.
  • unit_price is de NETTO-eenheidsprijs wanneer de uitgever btw-plichtig is.
  • De totalen nodig vóór u vastlegt? POST /v1/invoices/preview-totals voert dezelfde berekening uit zonder een fiscaal nummer te verbruiken.

Idempotentie bij fiscale schrijfacties

  • De Idempotency-Key-header is VERPLICHT op POST /invoices, POST /invoices/{id}/storno en POST /invoices/{id}/efactura/submit.
  • Sleutels worden 24 uur onthouden. Dezelfde sleutel opnieuw sturen met dezelfde body geeft het oorspronkelijke resultaat terug en zet Idempotency-Replayed: true.
  • Dezelfde sleutel met een andere body geeft 409 idempotency_key_reuse terug — een reeds uitgegeven fiscaal document wordt nooit overschreven.
  • Eén sleutel per LOGISCHE bewerking, niet per HTTP-poging: order-10457-invoice, geen nieuwe UUID bij elke nieuwe poging.
  • De reden is juridisch, niet technisch: een verbruikt fiscaal nummer en een bij het nationale e-factureringssysteem ingediende factuur kunnen niet worden ingetrokken.
bash
curl -sS -X POST https://api.4invoices.net/v1/invoices \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-10457-invoice' \
  -d '{
    "buyer": {
      "name": "Exemplu Comert SRL",
      "tax_id": "RO12345678",
      "address": "Str. Fabricii 12",
      "city": "Cluj-Napoca",
      "county": "Cluj",
      "country": "RO",
      "email": "[email protected]"
    },
    "lines": [
      { "description": "Abonament SaaS, iulie", "quantity": 1, "unit_price": 400, "vat_rate": 21, "unit": "buc" },
      { "description": "Implementare", "quantity": 6, "unit_price": 250, "vat_rate": 21, "unit": "ora" }
    ],
    "currency": "RON",
    "document_kind": "factura",
    "due_date": "2026-08-15",
    "metadata": { "order_id": "10457" }
  }'

Alle endpoints

MethodeEndpointScopeIdempotency-KeyVerzoeken / minuut
POST/auth/token
Inloggegevens ruilen voor een toegangstoken
——120
GET/me
Tenant, scopes en huidige limieten
invoices:read—120
POST/invoices
Een factuur of proforma uitgeven
invoices:writeverplicht30
GET/invoices
Facturen weergeven (cursorpaginering)
invoices:read—120
POST/invoices/preview-totals
Totalen berekenen zonder iets aan te maken
invoices:read—120
GET/invoices/{invoice_id}
Eén factuur ophalen
invoices:read—120
GET/invoices/{invoice_id}/pdf
De PDF van de factuur downloaden
invoices:read—120
GET/invoices/{invoice_id}/xml
De UBL / CIUS-RO-XML (Roemenië) downloaden
invoices:read—120
POST/invoices/{invoice_id}/storno
Een creditnota uitgeven die deze factuur tenietdoet
invoices:writeverplicht30
POST/invoices/{invoice_id}/payments
De factuur als betaald markeren
invoices:write—30
DELETE/invoices/{invoice_id}/payments
De factuur als onbetaald markeren
invoices:write—30
GET/clients
Klanten weergeven
clients:read—120
POST/clients
Een klant aanmaken of bijwerken
clients:write—30
GET/lookup/company/{tax_id}
Een CUI controleren in het ANAF-register (Roemenië)
clients:read—120
GET/series
Nummerreeksen weergeven
invoices:read—120
POST/invoices/{invoice_id}/efactura/validate
Precontrole (CIUS-RO voor Roemenië) — valideren zonder verzenden
efactura:read—120
POST/invoices/{invoice_id}/efactura/submit
De factuur naar ANAF (SPV, Roemenië) sturen
efactura:submitverplicht10
GET/efactura/submissions
Inzendingen bij ANAF (Roemenië) weergeven
efactura:read—120
GET/efactura/submissions/{submission_id}
Eén inzending ophalen
efactura:read—120
POST/efactura/submissions/{submission_id}/refresh
De huidige status opvragen bij ANAF (Roemenië)
efactura:read—10
GET/efactura/submissions/{submission_id}/download
Het archief van het ondertekende antwoord downloaden
efactura:read—120
GET/efactura/inbox
Via het SPV (Roemenië) ontvangen leveranciersfacturen
efactura:read—120
GET/efactura/inbox/{inbound_id}
Eén inkomende factuur ophalen
efactura:read—120
GET/efactura/inbox/{inbound_id}/download
Het archief van de inkomende factuur downloaden
efactura:read—120
POST/efactura/inbox/sync
Nieuwe berichten uit het SPV (Roemenië) naar de inbox halen
efactura:read—10

25 endpoints · https://api.4invoices.net/v1/openapi.json

Scopes

  • invoices:read
  • invoices:write
  • clients:read
  • clients:write
  • efactura:read
  • efactura:submit

Nationale e-facturering (ANAF e-Factura, Roemenië)

not_sentvalidatingqueuedsentprocessingacceptedrejectederror
  • Het echte onderscheidende punt: de volledige cyclus van het nationale e-factureringssysteem (in Roemenië: ANAF e-Factura) verloopt via de API, niet alleen het genereren van het document.
  • POST /invoices/{id}/efactura/validate voert de precontrole uit (CIUS-RO voor Roemenië) en geeft precies de velden terug die het nationale e-factureringssysteem zou weigeren, zonder iets te versturen.
  • GET /invoices/{id}/xml genereert de UBL / CIUS-RO-XML (Roemenië) zonder indiening — handig voor uw eigen archief of een interne audit.
  • POST /invoices/{id}/efactura/submit dient de factuur in bij het nationale e-factureringssysteem (in Roemenië: het SPV van ANAF). Dit is onomkeerbaar: een tweede exemplaar van dezelfde factuur kan niet meer worden ingetrokken.
  • De levenscyclus is genormaliseerd: not_sent → validating → queued → sent → processing → accepted | rejected | error. accepted betekent wettelijk verzonden; error is een transportfout aan onze kant en mag veilig opnieuw worden geprobeerd.
  • GET /efactura/submissions/{id}/download haalt het archief met het ondertekende antwoord van ANAF (Roemenië) op.
  • Ook de inkomende kant bestaat: POST /efactura/inbox/sync haalt nieuwe berichten uit het SPV (Roemenië) op en GET /efactura/inbox toont de facturen die uw leveranciers u hebben gestuurd.
bash
# CIUS-RO preflight. Sends NOTHING to ANAF.
curl -sS -X POST "https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/validate?include_xml=true" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# → {"invoice_id":"inv_01J7ABC","valid":false,
#    "errors":["buyer.county is required for RO buyers"],
#    "xml_base64":"PD94bWwg..."}
bash
curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/submit \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Idempotency-Key: efactura-inv_01J7ABC-1'

# → {"submission_id":"sub_01J7XYZ","status":"queued"}
python
import time, requests

BASE = "https://api.4invoices.net/v1"
TERMINAL = {"accepted", "rejected"}
H = {"Authorization": f"Bearer {token}"}

def wait_for_anaf(submission_id, timeout=900):
    deadline = time.time() + timeout
    delay = 15
    while time.time() < deadline:
        r = requests.get(f"{BASE}/efactura/submissions/{submission_id}", headers=H, timeout=30)
        r.raise_for_status()
        status = r.json()["status"]
        if status in TERMINAL:
            return r.json()
        # /refresh asks ANAF directly and shares the 10/min submit bucket.
        requests.post(f"{BASE}/efactura/submissions/{submission_id}/refresh", headers=H, timeout=30)
        time.sleep(delay)
        delay = min(delay * 2, 120)
    raise TimeoutError(submission_id)

Fouten

  • Elke 4xx en 5xx gebruikt dezelfde envelop: { "error": { type, code, message, param?, doc_url, request_id, errors? } }.
  • type is de grove categorie waarop u vertakt („kan ik het opnieuw proberen?”), en code is de stabiele reden die u in uw eigen systeem mapt.
  • param is het pad met punten naar het foutieve veld, bijvoorbeeld lines.0.vat_rate.
  • errors[] verschijnt wanneer één request problemen heeft in meer dan één veld.
  • request_id wordt aan onze kant gelogd. Vermeld het in elk supportticket — het identificeert het exacte request.
  • Ook voor een id die bij een andere tenant hoort, wordt een 404 teruggegeven: we bevestigen nooit dat gegevens van iemand anders bestaan.
json
{
  "error": {
    "type": "invalid_request_error",
    "code": "validation_failed",
    "message": "Datele trimise nu sunt valide.",
    "param": "lines.0.vat_rate",
    "doc_url": "https://4invoices.net/ro/api-dezvoltatori#errors",
    "request_id": "req_8a893f2f33d4472da8d6e144",
    "errors": [
      { "param": "lines.0.vat_rate", "message": "VAT rate must be a percent (21), not a fraction", "type": "value_error" }
    ]
  }
}
StatusTypeCode
401authentication_errormissing_bearer_token
401authentication_errorinvalid_client
401authentication_errortoken_expired
401authentication_errorinvalid_token
401authentication_errorunauthorized
403permission_errorinsufficient_scope
403permission_errorforbidden
404not_found_errornot_found
409conflict_erroridempotency_key_reuse
409conflict_erroridempotency_in_progress
409conflict_errorno_series_configured
422invalid_request_errorvalidation_failed
422invalid_request_errorissuer_profile_incomplete
422invalid_request_errorcius_ro_incomplete
422invalid_request_errorcannot_storno_draft
422invalid_request_errornothing_to_storno
422invalid_request_errorinvalid_json_number
429rate_limit_errorrate_limit_exceeded
502upstream_errorupstream_error
503service_unavailable_errorservice_unavailable

Snelheidslimieten

BucketVerzoeken / minuutBetekenis
read120GET *, POST /invoices/preview-totals, POST /invoices/{id}/efactura/validate
write30POST /invoices, POST /invoices/{id}/storno, POST|DELETE /invoices/{id}/payments, POST /clients
submit10POST /invoices/{id}/efactura/submit, POST /efactura/submissions/{id}/refresh, POST /efactura/inbox/sync
  • Limieten gelden per credential, per minuut: 120 voor leesbewerkingen, 30 voor schrijfbewerkingen, 10 voor e-factureringsbewerkingen (submit, refresh, inbox/sync).
  • X-RateLimit-Limit, X-RateLimit-Remaining en X-RateLimit-Reset staan op ELKE respons, ook op de 429.
  • Een 429 bevat ook Retry-After in seconden. Respecteer die waarde; probeer het niet opnieuw in een strakke lus.
  • De bucket van 10/min bestaat omdat ANAF in Roemenië zelf ongeveer één aanroep voor het ophalen van de berichtenlijst per minuut per CIF toestaat.
  • Plan /efactura/inbox/sync in een cronjob, niet met agressief opvragen.
  • Hogere limieten nodig? Vraag ze aan via het contactformulier, met uw verwachte dagvolume.

X-RateLimit-Limit · X-RateLimit-Remaining · X-RateLimit-Reset · Retry-After

http
HTTP/2 429
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1785312000
Retry-After: 17
Content-Type: application/json

{"error":{"type":"rate_limit_error","code":"rate_limit_exceeded",
 "message":"...","doc_url":"https://4invoices.net/ro/api-dezvoltatori#errors",
 "request_id":"req_..."}}
javascript
// Respecteer Retry-After; probeer nooit een 4xx anders dan 429 opnieuw.
async function call(url, init, attempt = 0) {
  const res = await fetch(url, init);
  if (res.status === 429 || res.status >= 500) {
    if (attempt >= 5) return res;
    const retryAfter = Number(res.headers.get("Retry-After")) || 2 ** attempt;
    await new Promise((r) => setTimeout(r, retryAfter * 1000));
    return call(url, init, attempt + 1);
  }
  return res;
}

// Een schrijfretry MOET dezelfde Idempotency-Key hergebruiken, anders geef je
// een tweede fiscaal document uit.

Gidsen per onderwerp

Elk onderwerp heeft een eigen pagina met de bijbehorende endpoints, voorbeelden en fouten.

Veelgemaakte fouten

  • De btw als breuk (0.19) of als 1 sturen. Beide worden geweigerd; stuur 19 of 21.
  • Een token per request aanvragen. Het token is een uur geldig; sla het op in de cache, anders loopt u tegen de limiet per IP van het token-endpoint aan.
  • Bij elke nieuwe poging een nieuwe idempotentiesleutel genereren — precies het scenario dat dubbele facturen oplevert.
  • Aanroepen vanuit JavaScript in de browser. CORS blokkeert elke origin, en het secret zou hoe dan ook worden blootgesteld.
  • Indienen bij het nationale e-factureringssysteem zonder precontrole (in Roemenië: CIUS-RO). Een verkeerde indiening kan niet worden ingetrokken.
  • /efactura/submissions/{id}/refresh vaker dan 10 keer per minuut pollen — die bucket wordt gedeeld met submit.
  • Uitgeven voordat het bedrijfsprofiel volledig is en er een actieve fiscale reeks bestaat.

Vragen en antwoorden voor ontwikkelaars

Hoe krijg ik credentials voor de 4invoices-API?

In het paneel, onder Facturatie → Instellingen → API-toegang. Je krijgt een client_id en een client_secret; het secret wordt één keer getoond en alleen als hash bewaard.

Hoe lang is het access_token geldig?

3600 seconden, dus één uur. Cache het en vernieuw voor het verloopt — het token-endpoint heeft een eigen limiet per IP.

Hoe stuur ik het btw-tarief?

Als percentage: 21 voor 21%. Waarden in (0, 1] worden geweigerd, dus 0.19 en 1 falen op validatie.

Welke calls vereisen een Idempotency-Key?

POST /invoices, POST /invoices/{id}/storno en POST /invoices/{id}/efactura/submit. Keys blijven 24 uur bekend en een replay geeft het originele document terug met Idempotency-Replayed: true.

Kan ik een factuur direct via de API bij ANAF e-Factura (Roemenië) indienen?

Ja, voor Roemenië: CIUS-RO-preflight met /efactura/validate, indienen met /efactura/submit, de genormaliseerde status volgen op /efactura/submissions/{id} en het ondertekende ANAF-antwoord downloaden.

Wat zijn de snelheidslimieten?

Per inloggegeven, per minuut: 120 lezingen, 30 schrijfacties en 10 e-factureringsbewerkingen. Elk antwoord bevat X-RateLimit-*-headers, en een 429 voegt Retry-After toe.

Kan ik de API vanuit mijn frontend aanroepen?

Nee. Het is uitsluitend server-to-server: geen browser-origin komt door CORS, en een client_secret hoort niet in code die de bezoeker bereikt.

Waarom krijg ik issuer_profile_incomplete bij mijn eerste factuur?

Het bedrijfsprofiel is onvolledig of er is geen actieve reeks van het type fiscale. Vul beide in het paneel aan; de API weigert een ongeldig fiscaal document te maken.