← Entwickler-Anleitungen

Direkte API-Integration

Rufen Sie die API mit reinem HTTP auf — kein SDK, jede Sprache. Die exakten anonymen und authentifizierten Anfrage-/Antwortformen, mit curl-Beispielen.

Kein SDK, jede Sprache — dies ist der exakte HTTP-Vertrag für den direkten Aufruf der API. Wenn Sie JavaScript verwenden, kapselt das SDK all dies (absenden, pollen, Fehlerbehandlung) für Sie — siehe Integration für einfache Webseiten oder Wählen Sie Ihren Integrationspfad, falls Sie noch keine Anleitung gewählt haben.

Jedes Beispiel unten zeigt die echte API-Basis-URL für diese Umgebung — kopieren Sie sie genau so, ohne zusätzliches Pfadsegment danach.

Zwei verschiedene Endpunkte, nicht eine URL mit zwei Auth-Modi

Dies sind zwei getrennte HTTP-Endpunkte. Sie geben für dasselbe Tool auch unterschiedliche Antwortformen zurück — wissen Sie, gegen welchen Sie entwickeln.

Anonym — POST /tools/:slug/run + GET /tools/runs/:ticketId

Keine Zugangsdaten erforderlich. Verwendet den Tool-Slug. Antwortfelder werden über alle Tools hinweg zu result.text normalisiert (plus Token-/Latenz-Metadaten), sodass das öffentliche Tool-Portal jedes Tool mit einem generischen Renderer darstellen kann. Ratenbegrenzt pro IP; siehe Fehler unten für die Fehlertabelle des anonymen Pfads (insbesondere erfordert dieser Pfad einen echten Browser — siehe den Hinweis zu 403).

curl -X POST "https://api.quravin.com/tools/translate/run" \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": { "text": "Hello", "target_language": "de" }
  }'

Antwort (202):

{ "ticket_id": "01J...ULID", "status": "QUEUED" }

Pollen:

curl "https://api.quravin.com/tools/runs/01J...ULID"

Antwort nach Abschluss:

{
  "ticket_id": "01J...ULID",
  "status": "DONE",
  "mode": "pipeline",
  "pipeline_id": "translate-string",
  "result": { "text": "Hallo", "model": "gpt-4o-mini", "latency_ms": 812 },
  "created_at": "2026-07-10T12:00:00.000Z",
  "updated_at": "2026-07-10T12:00:02.000Z"
}

Beachten Sie result.text, nicht result.translation — der anonyme Pfad normalisiert immer zu text.

Authentifiziert — POST /tickets + GET /tickets/:id

Erfordert x-api-key: <key> oder Authorization: Bearer <jwt> (siehe Wählen Sie Ihren Auth-Modus dafür, wie Sie eines der beiden erhalten). Verwendet die pipeline_id und gibt die rohe, nicht normalisierte Ausgabeform jeder Pipeline zurück — bei translate-string ist das translation, nicht text. Siehe Tool-Referenz für die pipeline_id jedes Tools und seine echten Ausgabefelder.

Mit einem statischen API-Schlüssel:

curl -X POST "https://api.quravin.com/tickets" \
  -H "Content-Type: application/json" \
  -H "x-api-key: <your-api-key>" \
  -d '{
    "mode": "pipeline",
    "pipeline_id": "translate-string",
    "inputs": { "text": "Hello", "target_language": "de" }
  }'

Mit einem Session-JWT (erstellt über POST /auth/token — siehe Wählen Sie Ihren Auth-Modus) — identischer Body, nur der Header ändert sich:

curl -X POST "https://api.quravin.com/tickets" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <your-jwt>" \
  -d '{
    "mode": "pipeline",
    "pipeline_id": "translate-string",
    "inputs": { "text": "Hello", "target_language": "de" }
  }'

Beide liefern dieselbe Antwort (202):

{ "ticket_id": "01J...ULID", "status": "QUEUED" }

Pollen — mit einem API-Schlüssel:

curl "https://api.quravin.com/tickets/01J...ULID" \
  -H "x-api-key: <your-api-key>"

Pollen — mit einem Session-JWT:

curl "https://api.quravin.com/tickets/01J...ULID" \
  -H "Authorization: Bearer <your-jwt>"

Antwort nach Abschluss:

{
  "ticket_id": "01J...ULID",
  "status": "DONE",
  "mode": "pipeline",
  "pipeline_id": "translate-string",
  "pipeline_version": "v3",
  "result": { "translation": "Hallo", "applied_terms": [] },
  "created_at": "2026-07-10T12:00:00.000Z",
  "updated_at": "2026-07-10T12:00:02.000Z"
}

Bei einem Fehlschlag stattdessen:

{
  "ticket_id": "01J...ULID",
  "status": "FAILED",
  "mode": "pipeline",
  "pipeline_id": "translate-string",
  "error": "Ticket failed: <reason>",
  "created_at": "2026-07-10T12:00:00.000Z",
  "updated_at": "2026-07-10T12:00:02.000Z"
}

Ein Ticket stornieren — DELETE /tickets/:id

Fordert eine Stornierung an (durch Schreiben eines cancel.flag). Sie können nur ein Ticket stornieren, das mit Ihren eigenen Zugangsdaten erstellt wurde — ein API-Schlüssel mit Operator-Scope kann jedes Ticket stornieren, ein JWT-/Webtoken-Aufrufer nur seine eigenen (sonst 403).

curl -X DELETE "https://api.quravin.com/tickets/01J...ULID" \
  -H "x-api-key: <your-api-key>"

# oder mit einem Session-JWT:
curl -X DELETE "https://api.quravin.com/tickets/01J...ULID" \
  -H "Authorization: Bearer <your-jwt>"

Antwort:

{ "ticket_id": "01J...ULID", "status": "CANCELED" }

Ein gepolltes GET /tickets/:id für ein storniertes Ticket liefert dieselbe Form wie DONE/FAILED oben, nur mit status: "CANCELED".

Ihre Tickets auflisten — GET /tickets

Gibt Tickets zurück, die auf Ihre eigene Identität beschränkt sind — ein JWT-/Webtoken-Aufrufer erhält immer seine eigenen Tickets zurück; nur ein API-Schlüssel mit Operator-Scope darf ?user= / ?app= übergeben, um die Tickets eines beliebigen Nutzers/einer beliebigen App abzufragen.

curl "https://api.quravin.com/tickets?limit=20" \
  -H "Authorization: Bearer <your-jwt>"

Query-Parameter:

ParameterStandardHinweise
limit50Maximal 1000.
hydratetruefalse liefert nur [{ ticket_id }] — günstig, überspringt das Abrufen des vollständigen Zustands jedes Tickets.
usereigene ID des AufrufersNur ein API-Schlüssel mit Operator-Scope darf die ID eines anderen Nutzers übergeben.
appeigene App des AufrufersNur ein API-Schlüssel mit Operator-Scope darf die ID einer anderen App übergeben.

Antwort:

{ "tickets": [ { "ticket_id": "01J...ULID", "status": "DONE", "...": "..." } ] }

Die wichtige Erkenntnis, wenn Sie vom öffentlichen „Try it”-Widget zu einer echten Integration übergehen: der Name des Ausgabefelds ändert sich von result.text (anonym) zum Pipeline-spezifischen Feld (authentifiziert) — bei translate ist das result.translation.

Fehler

Welche Fehler zurückkommen können, hängt davon ab, wie Sie aufrufen — anonyme und authentifizierte Aufrufe werden unterschiedlich validiert. Gehen Sie nicht davon aus, dass das Fehlerverhalten des einen Pfads auch für den anderen gilt.

Anonymer Aufruf (kein API-Schlüssel)

Alle veröffentlichten Tools, ratenbegrenzt pro IP.

StatusFehlercodeBedeutung
404Unbekannter Tool-Slug.
403Bot-Check fehlgeschlagen. Dieser Pfad erfordert einen echten Browser-Kontext, der eine Cloudflare-Turnstile-Challenge ausführen kann — von einem Server, curl oder einem Headless-Script ohne Turnstile-Token liefert er immer 403. Verwenden Sie für Server-zu-Server-Aufrufe einen authentifizierten Pfad (API-Schlüssel oder Session-JWT).
429guest_quota_exceededSie haben das anonyme Tages-Anfragelimit pro IP oder global erreicht.
429guest_cost_exceededSie haben das anonyme Tages-Kostenlimit pro IP oder global erreicht (teure Tools verbrauchen dieses Budget schneller).
202Erfolg — { ticket_id, status: "QUEUED" }. Pollen Sie das Ergebnis wie bei jedem anderen Aufruf.

Wichtig: Auf diesem Pfad werden Ihre inputs vor der Annahme des Aufrufs nicht gegen das Schema jedes Tools geprüft — ein fehlendes Pflichtfeld oder ein ungültiger Wert führt nicht zu einem 400. Stattdessen schlägt der Lauf selbst fehl, was Sie beim Pollen des Ergebnisses sehen. Sobald Sie einen API-Schlüssel haben, wechseln Sie zum authentifizierten Pfad unten, der im Voraus validiert.

Aufruf mit API-Schlüssel oder Session-Token

Jedes Tool, auf das Sie Zugriff haben.

StatusFehlercodeBedeutung
401Fehlende, ungültige oder abgelaufene Zugangsdaten.
403app_disabledIhre Anwendung wurde deaktiviert.
403org_suspendedIhre Organisation wurde gesperrt.
403org_pending_deletionIhre Organisation ist zur Löschung vorgesehen.
403Dieses Tool steht nicht auf der erlaubten Pipeline-Liste Ihrer Zugangsdaten.
403origin_not_allowedIhre Anwendung hat allowed_origins konfiguriert, und der Origin-Header der Anfrage stimmt mit keinem davon exakt überein. Gilt nur, wenn Sie (oder Ihr Org-Admin) sich in der Console bewusst dafür entschieden haben — Anwendungen, die das nie konfigurieren, sind nicht betroffen.
400Ihre inputs erfüllen die Anforderungen des Tools nicht (fehlendes Pflichtfeld, ungültiger Wert, oder die Gesamteingabe ist zu groß). Dieser Pfad validiert im Voraus, anders als der anonyme.
429rate_limitedSie senden Anfragen schneller als Ihr Limit pro Minute erlaubt — ein festes Ein-Minuten-Fenster pro Organisation, kein gleitendes Fenster. Weil es fest statt gleitend ist, kann ein Burst die nominelle Obergrenze genau an einer Minutengrenze kurzzeitig um bis zu ~2x überschreiten (z. B. ein Burst um 12:00:59 plus ein weiterer um 12:01:00); reagieren Sie mit Backoff und erneutem Versuch, statt eine exakte Obergrenze anzunehmen.
429quota_exceededSie haben Ihr monatliches Anfragekontingent erreicht.
429daily_cost_exceededSie haben ein tägliches Kostenlimit erreicht — ein Geschwindigkeitslimit, zu unterscheiden vom Aufbrauchen des Guthabens unten.
402insufficient_creditsDas Credit-Guthaben Ihrer Organisation reicht für diesen Aufruf nicht aus. Aufladen und erneut versuchen. Hinweis: Ein reiner x-api-key hat überhaupt kein Org-Wallet, sodass ein abrechenbarer Aufruf bei Wallet-Abrechnung dies zurückgibt, selbst wenn Guthaben vorhanden ist — wechseln Sie zu einem Session-JWT (siehe Wählen Sie Ihren Auth-Modus).
202Erfolg — { ticket_id, status: "QUEUED" }. Pollen Sie das Ergebnis.

Wie Zugangsdaten und die 401/403/429-Auth-Entscheidungen im Detail funktionieren, zeigt Wählen Sie Ihren Auth-Modus. Für die Eingaben, gültigen Werte und die Ausgabestruktur jedes Tools siehe Tool-Referenz.