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:
| Parameter | Standard | Hinweise |
|---|---|---|
limit | 50 | Maximal 1000. |
hydrate | true | false liefert nur [{ ticket_id }] — günstig, überspringt das Abrufen des vollständigen Zustands jedes Tickets. |
user | eigene ID des Aufrufers | Nur ein API-Schlüssel mit Operator-Scope darf die ID eines anderen Nutzers übergeben. |
app | eigene App des Aufrufers | Nur 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.
| Status | Fehlercode | Bedeutung |
|---|---|---|
| 404 | — | Unbekannter Tool-Slug. |
| 403 | — | Bot-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). |
| 429 | guest_quota_exceeded | Sie haben das anonyme Tages-Anfragelimit pro IP oder global erreicht. |
| 429 | guest_cost_exceeded | Sie haben das anonyme Tages-Kostenlimit pro IP oder global erreicht (teure Tools verbrauchen dieses Budget schneller). |
| 202 | — | Erfolg — { 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.
| Status | Fehlercode | Bedeutung |
|---|---|---|
| 401 | — | Fehlende, ungültige oder abgelaufene Zugangsdaten. |
| 403 | app_disabled | Ihre Anwendung wurde deaktiviert. |
| 403 | org_suspended | Ihre Organisation wurde gesperrt. |
| 403 | org_pending_deletion | Ihre Organisation ist zur Löschung vorgesehen. |
| 403 | — | Dieses Tool steht nicht auf der erlaubten Pipeline-Liste Ihrer Zugangsdaten. |
| 403 | origin_not_allowed | Ihre 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. |
| 400 | — | Ihre 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. |
| 429 | rate_limited | Sie 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. |
| 429 | quota_exceeded | Sie haben Ihr monatliches Anfragekontingent erreicht. |
| 429 | daily_cost_exceeded | Sie haben ein tägliches Kostenlimit erreicht — ein Geschwindigkeitslimit, zu unterscheiden vom Aufbrauchen des Guthabens unten. |
| 402 | insufficient_credits | Das 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). |
| 202 | — | Erfolg — { 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.