Hoe kunnen we helpen?
< Alle onderwerpen

API – 5. Fouten (Errors)

De API retourneert fouten consistente JSON met een vaste structuur. Gebruik deze informatie om snel te begrijpen wat er mis ging en hoe je het oplost.

Standaard foutformaat

{
  "error": {
    "code": "validation_error",
    "message": "Controleer de velden.",
    "details": {
      "invoice.date": "Verplicht (JJJJ-MM-DD).",
      "lines.0.unit_price": "Moet ≥ 0 zijn."
    }
  }
}

Velden

  • code — korte, machine-lezbare foutcode (stabiel).
  • message — menselijke samenvatting (kan vertaald worden).
  • details — object met veldspecifieke fouten (dot-notatie), alleen aanwezig bij validatieproblemen.

HTTP-statuscodes & betekenissen

StatusCodeWanneerExtra headers (indien van toepassing)
400invalid_jsonBody is geen geldige JSON
401unauthorizedOntbrekende of ongeldige API keyWWW-Authenticate: Bearer realm="Facturalia"
403forbiddenKey geldig, maar vereiste scope ontbreekt
404not_foundResource of route bestaat niet
405method_not_allowedVerkeerde HTTP-methode (bv. GET i.p.v. POST)Allow: POST
409idempotency_conflictZelfde external_id/Idempotency-Key/invoice.number met andere data
415unsupported_media_typeContent-Type niet application/json
422validation_errorData valideert niet
429rate_limitedTe veel requests binnen het vensterRetry-After, X-RateLimit-*
500server_errorOnverwachte fout aan serverzijde(optioneel) X-Request-Id

Tip: stuur altijd Content-Type: application/json; charset=utf-8 mee in je request.

Voorbeelden

400 – Ongeldige JSON

{
  "error": {
    "code": "invalid_json",
    "message": "Body is geen geldige JSON."
  }
}

401 – Geen of ongeldige key

{
  "error": {
    "code": "unauthorized",
    "message": "Authorization header ontbreekt of ongeldig."
  }
}

Header:
WWW-Authenticate: Bearer realm="Facturalia", error="invalid_token"

403 – Scope ontbreekt

{
  "error": {
    "code": "forbidden",
    "message": "Scope ontbreekt: invoices:create"
  }
}

405 – Methode niet toegestaan

{
  "error": {
    "code": "method_not_allowed",
    "message": "Gebruik POST op dit endpoint."
  }
}

Header: Allow: POST

409 – Idempotency-conflict

{
  "error": {
    "code": "idempotency_conflict",
    "message": "Identifier reeds gebruikt voor andere payload."
  }
}

Treedt op bij hergebruik van dezelfde external_id, Idempotency-Key of invoice.number met afwijkende inhoud.

415 – Verkeerde Content-Type

{
  "error": {
    "code": "unsupported_media_type",
    "message": "Gebruik Content-Type: application/json."
  }
}

422 – Validatiefout (met veldfouten)

{
  "error": {
    "code": "validation_error",
    "message": "Controleer de velden.",
    "details": {
      "invoice.date": "Verplicht (JJJJ-MM-DD).",
      "customer.email": "Ongeldig e-mailadres.",
      "lines.1.vat_rate": "Toegestaan: 0, 6, 12, 21."
    }
  }
}

429 – Te veel requests

Headers:

Retry-After: 30
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 2025-10-26T12:34:56Z

Body:

{
  "error": {
    "code": "rate_limited",
    "message": "Te veel requests. Probeer later opnieuw."
  }
}

500 – Serverfout

{
  "error": {
    "code": "server_error",
    "message": "Onverwachte fout",
    "details": {
      "hint": "Reference: 9f1c2a14"   // bv. request-id voor support
    }
  }
}

Idempotency-headers in responses (indien gebruikt)

  • Eerste creatie: Idempotency-Status: stored
  • Herspeelde creatie: Idempotency-Status: replayed

Beste praktijken voor clients

  • Lees HTTP-status én error.code om te beslissen wat te doen.
  • Bij 422 toon de inhoud van details direct aan de gebruiker of log ze per veld.
  • Respecteer Retry-After bij 429.
  • Hergebruik dezelfde idempotency-identifier bij retries van dezelfde creatie (zie hoofdstuk 3).
Go to Top