Fouten en limieten
Formaat van de fouten van de NovaFisko-API, HTTP-codes, machinecodes, snelheidslimieten per route en wat te doen na een 429.
De API gebruikt de standaard-HTTP-codes en geeft bij een fout altijd een JSON-body terug.
Formaat van een fout
{
"message": "Le plafond de 5 dossiers de votre licence est atteint.",
"code": "company_limit_reached",
"errors": {
"name": ["Le plafond de 5 dossiers de votre licence est atteint."]
}
}
| Veld | Aanwezigheid | Beschrijving |
|---|---|---|
message |
altijd | Leesbare tekst, vertaald in de taal van de gebruiker |
code |
bij een functionele fout | Stabiele identificator, in het Engels, te gebruiken in uw code |
errors |
validatiefouten | Object veld → lijst van berichten. Geneste velden gebruiken de puntnotatie: lines.0.account_id |
Sommige fouten voegen eigen velden toe, bijvoorbeeld required_ability, server_version en server_data, of blocker_codes voor Peppol.
Behandel eerst de HTTP-status, daarna code als die aanwezig is. Analyseer nooit de tekst van message.
HTTP-codes
| Status | Betekenis | Wat te doen |
|---|---|---|
200 |
Geslaagd | |
201 |
Resource aangemaakt | |
202 |
Aanvraag aanvaard, onmiddellijke of uitgestelde verwerking (webhooktest) | |
204 |
Geslaagd zonder body (verwijdering, afmelding) | |
401 |
Token afwezig, ongeldig, ingetrokken of vervallen | Opnieuw aanmelden of een ander token gebruiken |
403 |
Actie verboden voor dit token of deze rol | code lezen |
404 |
Onbekende resource, of dossier waartoe de gebruiker geen toegang heeft | De public_token en de rechten controleren |
409 |
Versieconflict (X-Base-Version) |
Herladen, samenvoegen, opnieuw versturen |
422 |
Gegevens geweigerd (validatie of boekhoudregel) | Corrigeren volgens errors en code |
429 |
Te veel requests | Retry-After seconden wachten |
500 |
Interne fout | Later opnieuw proberen met dezelfde idempotentiesleutel |
503 |
Dienst niet beschikbaar of in onderhoud, altijd met een code |
Opnieuw proberen met een oplopende wachttijd |
Een dossier dat bestaat maar waartoe u geen toegang hebt, antwoordt 404 en niet 403. Dat is bewust zo: de API geeft het bestaan van een dossier niet prijs aan wie er niet toe gemachtigd is.
Machinecodes
Authenticatie en toegang
code |
Status | Betekenis |
|---|---|---|
token_ability_missing |
403 | Het integratietoken heeft de bevoegdheid vermeld in required_ability niet |
session_token_required |
403 | Route voorbehouden aan sessietokens |
token_limit_reached |
422 | Maximaal 50 integratietokens per gebruiker |
webhook_limit_reached |
422 | Maximaal 20 eindpunten per kantoor |
webhook_url_refused |
422 | Webhook-URL geweigerd (HTTPS vereist, privéhost of niet-omgezette host) |
demo_mode |
403 | Extern effect geblokkeerd in het demokantoor |
demo_unavailable |
503 | Het demokantoor is niet beschikbaar |
service_unavailable |
503 | Algemene onbeschikbaarheid |
Licentie en plafonds
code |
Status | Betekenis |
|---|---|---|
company_limit_reached |
422 | Dossierplafond van de licentie of de formule bereikt |
user_limit_reached |
422 | Gebruikersplafond van de licentie bereikt |
invalid_key |
422 | Onbekende activeringssleutel |
expired_key |
422 | Vervallen activeringssleutel |
exhausted_key |
422 | Sleutel al het toegestane aantal keren gebruikt |
key_reserved |
422 | Sleutel voorbehouden aan een ander kantoor |
already_active |
422 | Deze sleutel is al actief op het kantoor |
Gelijktijdigheid en geschiedenis
code |
Status | Betekenis |
|---|---|---|
conflict |
409 of 422 | Het record is op de server gewijzigd sinds u het hebt gelezen |
period_locked |
422 | Vergrendelde periode of afgesloten boekjaar |
vat_locked |
422 | Btw-aangifte gevalideerd of ingediend |
entry_immutable |
422 | Een gevalideerde boeking kan niet worden gewijzigd: ze moet worden tegengeboekt |
already_reverted, already_reversed |
422 | Het terugdraaien of de tegenboeking heeft al plaatsgevonden |
in_use, booked |
422 | Verwijdering geweigerd: het record is in gebruik of geboekt |
code_taken |
422 | Herstel geweigerd: de code is intussen opnieuw in gebruik genomen |
not_revertible, nothing_to_revert, operation_not_found |
422 of 404 | Terugdraaien onmogelijk |
force_forbidden, read_only |
403 | Onvoldoende rol |
Synchronisatie
Deze codes verschijnen in het resultaat van elke mutatie van sync/push, niet als HTTP-status.
code |
Betekenis |
|---|---|
locked |
Boekhoudkundig gegeven gevalideerd of vergrendeld aan serverzijde |
validation |
Gegevens geweigerd, details in errors |
not_supported_offline |
Deze bewerking verloopt niet via sync/push |
not_found, forbidden, invalid_mutation, unknown_temp_id, unprocessable |
Mutatie definitief geweigerd |
server_error |
Tijdelijke fout, retryable: true |
conflict_already_resolved, conflict_choice_unavailable |
Conflictoplossing geweigerd (422) |
Peppol
De Peppol-weigeringen geven blocker_codes terug, een lijst uit: provider_not_configured, vat_number_missing, address_missing, email_missing, already_registered, managed_by_novadesko, registered_elsewhere, not_registered, provider_error.
{
"message": "Le dossier ne peut pas être inscrit sur Peppol.",
"errors": {"peppol": ["Le dossier ne peut pas être inscrit sur Peppol."]},
"blockers": ["L'adresse e-mail de contact est manquante."],
"blocker_codes": ["email_missing"],
"state": {"status": "none", "can_register": false}
}
Niet alle 422-fouten hebben een code. Een eenvoudige validatiefout bevat alleen message en errors. Houd rekening met dat geval.
Validatiefout
{
"message": "Le champ entry date est obligatoire. (et 1 erreur supplémentaire)",
"errors": {
"entry_date": ["Le champ entry date est obligatoire."],
"lines.1.account_id": ["Le champ lines.1.account_id est obligatoire quand lines.1.account n'est pas présent."]
}
}
Snelheidslimieten
De limieten gelden per minuut. Ze worden geteld per gebruiker voor de geauthenticeerde routes en per IP-adres voor de publieke routes. De routes die niet in deze tabel staan, hebben geen eigen limiet.
| Route | Limiet per minuut |
|---|---|
POST auth/login |
20 |
POST auth/demo |
10 |
POST auth/tokens |
20 |
POST firms/{firm}/webhooks/{id}/test |
12 |
GET pricing, GET pricing/simulate |
120 |
POST firms/{firm}/licence/activate |
10 |
POST firms/{firm}/sync |
6 |
GET lookup/search, lookup/companies/{identifier}, lookup/vat |
60 |
GET lookup/cities, lookup/streets |
120 |
POST companies/{company}/apply-sheet, third-parties/{id}/apply-sheet |
30 |
POST document-imports |
30 |
POST document-imports/{id}/process, .../validate |
120 |
POST document-imports/{id}/retry |
60 |
POST documents/book-all |
5 |
POST bank-transactions/match |
10 |
POST bank-transactions/book-matched |
5 |
POST payments/sepa |
20 |
GET vies, POST third-parties/{id}/vies |
30 |
POST sync/novadesko |
10 |
POST integrations/{id}/test, .../sync |
12 |
POST peppol/register |
6 |
POST peppol/refresh |
12 |
GET peppol/lookup |
30 |
GET third-parties/{id}/peppol |
60 |
POST third-parties/peppol/check-all |
6 |
GET exports/{type} |
30 |
GET exports/{type}/preview-url |
60 |
GET exports/full-dossier/{fiscalYear} |
10 |
POST fiscal-years/{id}/year-end |
5 |
GET history/export |
30 |
Elk antwoord van een gelimiteerde route vermeldt uw verbruik:
HTTP/1.1 200 OK
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 27
Antwoord 429
HTTP/1.1 429 Too Many Requests
Retry-After: 41
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1791188421
Content-Type: application/json
{"message": "Too Many Attempts."}
Wacht het aantal seconden dat Retry-After aangeeft voordat u het opnieuw probeert. X-RateLimit-Reset geeft het tijdstip van de reset in Unix-seconden.
import time
import requests
def call(method, url, **kwargs):
for attempt in range(5):
response = requests.request(method, url, timeout=60, **kwargs)
if response.status_code == 429:
# Honour the server delay, never hammer the API
time.sleep(int(response.headers.get("Retry-After", "5")) + 1)
continue
if response.status_code in (500, 503):
time.sleep(2 ** attempt)
continue
return response
raise RuntimeError("NovaFisko API unavailable")
Wanneer u een schrijfbewerking opnieuw probeert na een netwerkfout, een 500 of een 503, stuur dan dezelfde X-Client-Mutation-Id mee. Anders riskeert u een dubbel record aan te maken. Zie Idempotentie.
Andere limieten
| Limiet | Waarde |
|---|---|
| Bestanden per upload in de importmodule | 20 |
| Grootte van een geüpload bestand | 25 MB |
| Bestanden uitgepakt uit een ZIP-archief | 50 |
Mutaties per aanroep sync/push |
200 |
Wijzigingen per aanroep sync/pull |
standaard 500, maximaal 1000 |
| Elementen per pagina | standaard 50, maximaal 200 (500 voor de bankverrichtingen) |
| Geldigheidsduur van een ondertekende URL voor een exportvoorbeeld | 15 minuten |