Fehler und Limits
Fehlerformat der NovaFisko-API, HTTP-Codes, Maschinencodes, Rate-Limits pro Route und das richtige Verhalten nach einem 429.
Die API verwendet die Standard-HTTP-Codes und liefert im Fehlerfall immer einen JSON-Body.
Format eines Fehlers
{
"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."]
}
}
| Feld | Vorhanden | Beschreibung |
|---|---|---|
message |
immer | Lesbarer Text, in die Sprache des Benutzers übersetzt |
code |
bei fachlichen Fehlern | Stabile Kennung auf Englisch, zur Verwendung in Ihrem Code |
errors |
bei Validierungsfehlern | Objekt Feld → Liste von Meldungen. Verschachtelte Felder verwenden die Punktnotation: lines.0.account_id |
Einige Fehler fügen eigene Felder hinzu, zum Beispiel required_ability, server_version und server_data oder blocker_codes für Peppol.
Werten Sie zuerst den HTTP-Status aus, dann code, sofern vorhanden. Analysieren Sie niemals den Text von message.
HTTP-Codes
| Status | Bedeutung | Vorgehen |
|---|---|---|
200 |
Erfolg | |
201 |
Ressource erstellt | |
202 |
Anfrage angenommen, sofortige oder verzögerte Verarbeitung (Webhook-Test) | |
204 |
Erfolg ohne Body (Löschung, Abmeldung) | |
401 |
Token fehlt, ist ungültig, widerrufen oder abgelaufen | Neu anmelden oder das Token wechseln |
403 |
Aktion für dieses Token oder diese Rolle nicht erlaubt | code lesen |
404 |
Unbekannte Ressource oder Mandat, auf das der Benutzer keinen Zugriff hat | public_token und Rechte prüfen |
409 |
Versionskonflikt (X-Base-Version) |
Neu laden, zusammenführen, erneut senden |
422 |
Daten abgelehnt (Validierung oder Buchhaltungsregel) | Anhand von errors und code korrigieren |
429 |
Zu viele Requests | Retry-After Sekunden warten |
500 |
Interner Fehler | Später mit demselben Idempotenzschlüssel erneut versuchen |
503 |
Dienst nicht verfügbar oder Wartung, immer mit einem code |
Mit wachsendem Abstand erneut versuchen |
Ein Mandat, das existiert, auf das Sie aber keinen Zugriff haben, antwortet mit 404 und nicht mit 403. Das ist beabsichtigt: Die API gibt die Existenz eines Mandats nicht an Unbefugte preis.
Maschinencodes
Authentifizierung und Zugriff
code |
Status | Bedeutung |
|---|---|---|
token_ability_missing |
403 | Dem Integrationstoken fehlt die in required_ability genannte Berechtigung |
session_token_required |
403 | Route ist Sitzungstokens vorbehalten |
token_limit_reached |
422 | Höchstens 50 Integrationstokens pro Benutzer |
webhook_limit_reached |
422 | Höchstens 20 Endpunkte pro Kanzlei |
webhook_url_refused |
422 | Webhook-URL abgelehnt (HTTPS erforderlich, privater oder nicht auflösbarer Host) |
demo_mode |
403 | Externe Wirkung in der Demo-Kanzlei blockiert |
demo_unavailable |
503 | Die Demo-Kanzlei ist nicht verfügbar |
service_unavailable |
503 | Allgemeine Nichtverfügbarkeit |
Lizenz und Obergrenzen
code |
Status | Bedeutung |
|---|---|---|
company_limit_reached |
422 | Mandatsobergrenze der Lizenz oder des Plans erreicht |
user_limit_reached |
422 | Benutzerobergrenze der Lizenz erreicht |
invalid_key |
422 | Unbekannter Aktivierungsschlüssel |
expired_key |
422 | Aktivierungsschlüssel abgelaufen |
exhausted_key |
422 | Schlüssel wurde bereits so oft verwendet wie erlaubt |
key_reserved |
422 | Schlüssel ist einer anderen Kanzlei vorbehalten |
already_active |
422 | Dieser Schlüssel ist in der Kanzlei bereits aktiv |
Gleichzeitige Zugriffe und Verlauf
code |
Status | Bedeutung |
|---|---|---|
conflict |
409 oder 422 | Der Datensatz hat sich seit Ihrem Lesezugriff auf dem Server geändert |
period_locked |
422 | Periode gesperrt oder Geschäftsjahr abgeschlossen |
vat_locked |
422 | MwSt.-Erklärung validiert oder eingereicht |
entry_immutable |
422 | Eine gebuchte Buchung lässt sich nicht ändern: Sie muss storniert werden |
already_reverted, already_reversed |
422 | Das Rückgängigmachen oder die Stornierung ist bereits erfolgt |
in_use, booked |
422 | Löschung abgelehnt: Der Datensatz wird verwendet oder ist gebucht |
code_taken |
422 | Wiederherstellung abgelehnt: Der Code wurde inzwischen neu vergeben |
not_revertible, nothing_to_revert, operation_not_found |
422 oder 404 | Rückgängigmachen nicht möglich |
force_forbidden, read_only |
403 | Rolle nicht ausreichend |
Synchronisierung
Diese Codes erscheinen im Ergebnis jeder Mutation von sync/push, nicht als HTTP-Status.
code |
Bedeutung |
|---|---|
locked |
Buchhaltungsdaten auf dem Server gebucht oder gesperrt |
validation |
Daten abgelehnt, Einzelheiten in errors |
not_supported_offline |
Dieser Vorgang läuft nicht über sync/push |
not_found, forbidden, invalid_mutation, unknown_temp_id, unprocessable |
Mutation endgültig abgelehnt |
server_error |
Vorübergehender Fehler, retryable: true |
conflict_already_resolved, conflict_choice_unavailable |
Konfliktlösung abgelehnt (422) |
Peppol
Peppol-Ablehnungen liefern blocker_codes, eine Liste aus: 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}
}
Nicht alle 422-Fehler tragen einen code. Ein einfacher Validierungsfehler enthält nur message und errors. Berücksichtigen Sie diesen Fall.
Validierungsfehler
{
"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."]
}
}
Rate-Limits
Die Limits gelten pro Minute. Sie werden bei authentifizierten Routen pro Benutzer und bei öffentlichen Routen pro IP-Adresse gezählt. Routen, die in dieser Tabelle nicht aufgeführt sind, haben kein eigenes Limit.
| Route | Limit pro Minute |
|---|---|
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 |
Jede Antwort einer begrenzten Route gibt Ihren Verbrauch an:
HTTP/1.1 200 OK
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 27
Antwort 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."}
Warten Sie die in Retry-After angegebene Anzahl Sekunden, bevor Sie es erneut versuchen. X-RateLimit-Reset gibt den Zeitpunkt der Rücksetzung in Unix-Sekunden an.
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")
Wenn Sie einen Schreibzugriff nach einem Netzwerkfehler, einem 500 oder einem 503 wiederholen, senden Sie dieselbe X-Client-Mutation-Id erneut. Andernfalls riskieren Sie ein Duplikat. Siehe Idempotenz.
Weitere Limits
| Limit | Wert |
|---|---|
| Dateien pro Upload im Importer | 20 |
| Größe einer hochgeladenen Datei | 25 MB |
| Aus einem ZIP-Archiv extrahierte Dateien | 50 |
Mutationen pro Aufruf von sync/push |
200 |
Änderungen pro Aufruf von sync/pull |
standardmäßig 500, höchstens 1000 |
| Elemente pro Seite | standardmäßig 50, höchstens 200 (500 für Bankbewegungen) |
| Gültigkeit einer signierten URL für die Exportvorschau | 15 Minuten |