NueForm

Fehlerbehandlung

Verstehe das Fehlerformat der NueForm-API, die Fehlercodes und wie du Fehler in deiner Anwendung sauber behandelst.

Die NueForm-API verwendet die üblichen HTTP-Statuscodes und gibt strukturierte JSON-Fehlerantworten zurück. Diese Anleitung behandelt das Antwortformat, alle möglichen Fehlercodes und Muster für die Fehlerbehandlung in deinem Code.

Antwortformate

Erfolgsantworten

Erfolgreiche API-Aufrufe geben ein JSON-Objekt mit einem data-Feld zurück. Listen-Endpunkte enthalten zusätzlich ein meta-Feld mit Paginierungsinformationen.

json
{
  "data": {
    "id": "clx1abc2d3e4f5g6h7i8j9k0",
    "title": "Customer Feedback",
    "status": "published",
    "created_at": "2026-01-15T09:30:00.000Z"
  }
}

Mit Paginierungs-Metadaten:

json
{
  "data": [
    {
      "id": "clx1abc2d3e4f5g6h7i8j9k0",
      "title": "Customer Feedback"
    },
    {
      "id": "clx2def3g4h5i6j7k8l9m0n1",
      "title": "Employee Survey"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 150,
    "total_pages": 8
  }
}

Fehlerantworten

Fehlerantworten geben ein JSON-Objekt mit einem error-Feld zurück, das den Fehler-code, eine menschenlesbare message und den HTTP-status-Code enthält.

json
{
  "error": {
    "code": "NOT_FOUND",
    "message": "The requested form could not be found.",
    "status": 404
  }
}

Fehlercodes

Die folgende Tabelle listet alle Fehlercodes auf, die die API zurückgibt:

CodeHTTP-StatusBeschreibung
BAD_REQUEST400Die Anfrage ist fehlerhaft, es fehlen Pflichtfelder oder sie enthält ungültige Werte.
UNAUTHORIZED401Die Authentifizierung ist fehlgeschlagen. Der API-Schlüssel fehlt, ist fehlerhaft, widerrufen oder abgelaufen.
FORBIDDEN403Der authentifizierte Benutzer hat keine Berechtigung für diese Aktion.
NOT_FOUND404Die angeforderte Ressource existiert nicht oder ist für den authentifizierten Benutzer nicht zugänglich.
CONFLICT409Die Anfrage steht im Konflikt mit dem aktuellen Zustand der Ressource (z. B. doppelter Eintrag oder ein Formular, das noch nicht veröffentlicht werden kann).
RATE_LIMITED429Zu viele Anfragen. Details findest du unter Rate Limits.
INTERNAL_ERROR500Auf dem Server ist ein unerwarteter Fehler aufgetreten.

Beispiele für Fehlerantworten

400 Bad Request

Wird zurückgegeben, wenn der Anfrage-Body ungültig ist oder Pflichtfelder fehlen.

json
{
  "error": {
    "code": "BAD_REQUEST",
    "message": "Field 'title' is required.",
    "status": 400
  }
}

401 Unauthorized

Wird zurückgegeben, wenn die Authentifizierung aus irgendeinem Grund fehlschlägt.

json
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or expired API key.",
    "status": 401
  }
}

403 Forbidden

Wird zurückgegeben, wenn der Benutzer zwar authentifiziert ist, aber keine Berechtigung hat. Häufige Ursachen sind der Zugriff auf Ressourcen eines anderen Benutzers oder die Nutzung einer Funktion, die im aktuellen Tarif nicht enthalten ist.

json
{
  "error": {
    "code": "FORBIDDEN",
    "message": "API access is not available on your current plan.",
    "status": 403
  }
}

404 Not Found

Wird zurückgegeben, wenn die angeforderte Ressource nicht existiert.

json
{
  "error": {
    "code": "NOT_FOUND",
    "message": "The requested form could not be found.",
    "status": 404
  }
}

409 Conflict

Wird zurückgegeben, wenn die Anfrage ein Duplikat erzeugen würde oder mit vorhandenen Daten in Konflikt steht.

json
{
  "error": {
    "code": "CONFLICT",
    "message": "A form with this slug already exists.",
    "status": 409
  }
}

409 Conflict — Veröffentlichung blockiert

Wird von POST /api/v1/forms/:id/publish (und von PUT /api/v1/forms/:id mit published: true) zurückgegeben, wenn das Formular noch nicht live gehen kann. Es wird nichts veröffentlicht. reason nennt den Grund, und question_ids listet die zu korrigierenden Fragen auf. Ist upgrade_required true, braucht der Plan des Formularinhabers ein Upgrade.

json
{
  "error": {
    "code": "CONFLICT",
    "message": "E-signature contracts need a Pro plan to go live. Upgrade to publish this form, or remove the contract question.",
    "status": 409,
    "reason": "contract_requires_pro",
    "question_ids": ["66a1b2c3d4e5f6a7b8c9d001"],
    "upgrade_required": true
  }
}
reasonWas zu beheben ist
contract_requires_pro, data_node_requires_pro, booking_requires_pro, payment_connect_requires_pro, webhook_requires_proDer Plan des Formularinhabers (bei Team-Formularen der des Team-Owners) enthält diese Funktion nicht. Mach ein Upgrade oder entferne sie: Lösche die Frage, leere webhook_url oder stelle die Zahlungsfrage auf die Standardoption um.
booking_*Eine Buchungsfrage kann noch keine Buchungen annehmen: Verbinde ihren Kalender (erneut) oder ergänze ihre Zeiten, ihre Zeitzone, ihre Daueroptionen oder die Nummer für Bestätigungsanrufe.
email_node_*Einem E-Mail-Schritt fehlen Empfänger, Absendername, Betreff oder Inhalt, oder er sendet an {respondent.email} in einem Formular, das keine Anmeldung verlangt.
fuse_*Eine Fuse-Frage hat kein Fuse-Formular, ihr Fuse-Formular fehlt oder ist nicht veröffentlicht, oder ihre angeheftete Session wurde archiviert.
composite_*Ein Composite, das das Formular verwendet, ist nicht veröffentlicht, gelöscht oder leer; composite_ids listet sie auf.

Erstellst du ein Formular mit published: true und wird die Veröffentlichung blockiert, wird das Formular trotzdem als Entwurf angelegt: Die Antwort ist 201 Created mit einem publish_error-Objekt (reason, message, question_ids, upgrade_required), sodass ein erneuter Versuch nie ein Duplikat erzeugt. Gibt PUT /api/v1/forms/:id diesen Fehler zurück, wurden deine Änderungen gespeichert (saved_as_draft: true), und nur die Veröffentlichung ist fehlgeschlagen.

429 Rate Limited

Wird zurückgegeben, wenn das Rate Limit überschritten wurde. Enthält einen Retry-After-Header.

json
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded. Please try again later.",
    "status": 429
  }
}

500 Internal Error

Wird zurückgegeben, wenn ein unerwarteter Serverfehler auftritt. Wenn das Problem bestehen bleibt, wende dich an den Support.

json
{
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "An internal error occurred.",
    "status": 500
  }
}

Fehler der Voice-API

Die Voice-API ergänzt diese Codes. Nichts, was mit einem Fehler endet, wird berechnet, und die zusätzlichen Felder stehen neben code innerhalb von error.

CodeHTTP-StatusBeschreibung
INSUFFICIENT_CREDITS402Dein Guthaben reicht für die Anfrage nicht. credits_required, credits_available und top_up_url sagen, wie viel fehlt und wo du mehr bekommst.
TEXT_TOO_LONG413Mehr gesprochene Zeichen, als eine Anfrage annimmt (max_characters). Teile den Text auf mehrere Anfragen auf.
CONTENT_BLOCKED422Der Text darf nach unseren Nutzungsrichtlinien nicht gesprochen werden (categories).
VOICE_UNAVAILABLE422Die Stimme existiert nicht oder du darfst sie nicht verwenden (voice).
LANGUAGE_NOT_SUPPORTED_BY_VOICE422Die Stimme kann diese Sprache nicht sprechen (voice, language, supported_languages).
LINE_LANGUAGE_NOT_SUPPORTED_BY_VOICE422Einige Zeilen sind in einer Sprache, die ihre eigene Stimme nicht sprechen kann. mismatches listet jede davon auf (speaker, voice, voice_name, language, line_count), dazu bis zu vier suggestions mit Stimmen, die diese Sprache sprechen. Ist native_voices false, spricht keine Stimme genau diese Sprache: Die Vorschläge sprechen eine verwandte Sprache und klingen womöglich nicht richtig.
INVALID_SCRIPT422Das Skript kann so nicht gesprochen werden (reason, zum Beispiel speaker_not_cast).
CONCURRENCY_LIMIT429Zu viele gleichzeitig laufende Generierungen für dein Konto. Versuche es nach Retry-After erneut.
CAPACITY503Gerade keine Kapazität. Versuche es nach Retry-After erneut.
WARMING_UP503Die Sprach-Engine startet gerade. Versuche es nach Retry-After erneut.
MODERATION_UNAVAILABLE503Der Text konnte gerade nicht geprüft werden. Versuche es nach Retry-After erneut.
AI_UNAVAILABLE503auto_convert oder auto_cast konnte gerade nicht laufen. Versuche es nach Retry-After erneut.
DELETE_INCOMPLETE503Ein Löschvorgang wurde unterbrochen. Sende ihn erneut, um ihn abzuschließen.

FORBIDDEN (403) und CONFLICT (409) nennen den Grund in reason: zum Beispiel key_limit_reached, account_gate oder scope_not_allowed bzw. quote_exceeds_max_credits, idempotency_conflict oder request_in_progress.

json
{
  "error": {
    "code": "INSUFFICIENT_CREDITS",
    "message": "This request needs 30 credits; 12 are available. Nothing was charged.",
    "status": 402,
    "credits_required": 30,
    "credits_available": 12,
    "top_up_url": "https://nueform.io/wallet?tab=buy"
  }
}

Fehler im Code behandeln

JavaScript

Baue einen wiederverwendbaren API-Client, der auf Fehler prüft und typisierte Exceptions wirft:

javascript
class NueFormApiError extends Error {
  constructor(code, message, status) {
    super(message);
    this.name = "NueFormApiError";
    this.code = code;
    this.status = status;
  }
}

async function nueformRequest(path, options = {}) {
  const response = await fetch(`https://app.nueform.io/api/v1${path}`, {
    ...options,
    headers: {
      "Authorization": `Bearer ${process.env.NUEFORM_API_KEY}`,
      "Content-Type": "application/json",
      ...options.headers,
    },
  });

  const body = await response.json();

  if (!response.ok) {
    const { code, message, status } = body.error;
    throw new NueFormApiError(code, message, status);
  }

  return body;
}

// Usage
async function getForm(formId) {
  try {
    const { data } = await nueformRequest(`/forms/${formId}`);
    return data;
  } catch (error) {
    if (error instanceof NueFormApiError) {
      switch (error.code) {
        case "NOT_FOUND":
          console.error(`Form ${formId} does not exist.`);
          return null;
        case "UNAUTHORIZED":
          console.error("Check your API key configuration.");
          break;
        case "RATE_LIMITED":
          console.warn("Rate limited. Implement backoff and retry.");
          break;
        default:
          console.error(`API error [${error.code}]: ${error.message}`);
      }
    }
    throw error;
  }
}

Python

python
import os
import requests

class NueFormApiError(Exception):
    def __init__(self, code, message, status):
        super().__init__(message)
        self.code = code
        self.status = status

class NueFormClient:
    def __init__(self, api_key=None):
        self.api_key = api_key or os.environ["NUEFORM_API_KEY"]
        self.base_url = "https://app.nueform.io/api/v1"

    def request(self, method, path, **kwargs):
        url = f"{self.base_url}{path}"
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json",
        }

        response = requests.request(method, url, headers=headers, **kwargs)
        body = response.json()

        if not response.ok:
            error = body["error"]
            raise NueFormApiError(
                error["code"], error["message"], error["status"]
            )

        return body

# Usage
client = NueFormClient()

try:
    result = client.request("GET", f"/forms/{form_id}")
    form = result["data"]
    print(f"Form: {form['title']}")

except NueFormApiError as e:
    if e.code == "NOT_FOUND":
        print(f"Form {form_id} does not exist.")
    elif e.code == "UNAUTHORIZED":
        print("Check your API key configuration.")
    elif e.code == "RATE_LIMITED":
        print("Rate limited. Implement backoff and retry.")
    else:
        print(f"API error [{e.code}]: {e}")

Best Practices

Prüfe immer das error-Feld

Gehe niemals allein aufgrund eines vorhandenen Bodys davon aus, dass eine Antwort erfolgreich war. Prüfe immer auf das error-Feld oder den HTTP-Statuscode, bevor du die Antwort weiterverarbeitest.

Nutze konkrete Fehlercodes für die Ablaufsteuerung

Werte error.code aus (z. B. NOT_FOUND, RATE_LIMITED) statt des HTTP-Statuscodes. Fehlercodes sind stabil, aussagekräftig und in der Anwendungslogik leichter nachzuvollziehen.

Protokolliere Fehlerdetails

Nimm die vollständige Fehlerantwort zum Debuggen in deine Logs auf. code, message und status liefern zusammen genug Kontext, um die meisten Probleme zu diagnostizieren, ohne die Anfrage reproduzieren zu müssen.

Behandle 5xx-Fehler mit Retries

Serverfehler (500 Internal Error) sind in der Regel vorübergehend. Implementiere für diese Antworten eine Retry-Logik mit exponentiellem Backoff. Begrenze die Wiederholungen auf 2--3 Versuche, bevor du abbrichst.

Zeige Fehlermeldungen nicht den Endnutzern

API-Fehlermeldungen richten sich an Entwickler, nicht an Endnutzer. Übersetze API-Fehler in deiner Anwendung in nutzerfreundliche Meldungen.

Wenn du dauerhaft 500 Internal Error-Antworten erhältst, wende dich bitte mit den Anfragedetails und Zeitstempeln an den Support. Serverfehler werden bei uns protokolliert und untersucht.

Zuletzt aktualisiert: 30. Oktober 2026