API-Referenz
Doppelbelastung vermeiden
Idempotenz bedeutet, dass eine wiederholte Anfrage nur einmal ausgeführt wird: Senden Sie bei der Wiederholung denselben Idempotency-Key, dann wird Ihnen nur einmal etwas berechnet, auch wenn der erste Versuch nur verloren schien.
Eine Anfrage mit Timeout ist keine fehlgeschlagene Anfrage. Die Generierung läuft womöglich schon, und eine blinde Wiederholung startet — und berechnet — eine zweite. Senden Sie einen Idempotency-Key, dann führt das Gateway die Anfrage einmal aus und liefert 24 Stunden lang dieselbe Antwort erneut.
#Wann Sie einen Schlüssel senden sollten
Senden
- Jede asynchrone Einreichung — Video, Bild-Task, Musik, 3D. Das sind die teuren.
- Jeder Aufruf ohne Streaming, den Ihr Worker automatisch wiederholt.
- Aufrufe hinter einer Queue, die einen Job nach einem Absturz erneut zustellen kann.
Weglassen
- Streaming-Anfragen — der Header wird mit 400 abgelehnt, ein Stream lässt sich nicht erneut ausliefern.
- GET-Abfragen und Metadaten-Lesezugriffe — sie zu wiederholen ist ohnehin kostenlos und sicher.
- Interaktiver Chat, bei dem eine doppelte Antwort weniger kostet als die Buchführung.
curl https://www.aisplice.store/v1/videos \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"model": "doubao-seedance-2.5",
"prompt": "A drone shot of a lighthouse at dawn"
}'Leiten Sie den Schlüssel aus Ihrem eigenen Datensatz ab
#Wie Schlüssel abgeglichen werden
Opt-in, nie automatisch
Ohne den Header ändert sich nichts. Eine Wiederholung ohne Schlüssel ist eine zweite kostenpflichtige Anfrage.
Nur schreibende Methoden
GET, HEAD und OPTIONS ignorieren den Header — das Abfragen eines Tasks lässt sich ohnehin gefahrlos wiederholen.
Gilt pro Nutzer + Schlüssel + Methode + Route
Derselbe Wert unter einem anderen API-Schlüssel oder an einem anderen Endpunkt ist eine andere Operation.
Der Body gehört zur Identität
Pfad, Query und Body werden gemeinsam gehasht. Wird ein Schlüssel mit geändertem Payload wiederverwendet, kommt 409 zurück — nichts wird überschrieben.
Nicht mit Streaming kompatibel
Eine gestreamte Antwort lässt sich nicht für eine Wiederholung speichern, daher wird stream:true zusammen mit einem Schlüssel mit 400 abgelehnt.
Blockiert im Zweifel
Ist das Register nicht verfügbar, wird die Anfrage mit 503 abgelehnt, statt ungeschützt ausgeführt zu werden.
Schlüssel haben höchstens 255 Zeichen. Längere werden mit 400 abgelehnt, bevor die Anfrage ausgeführt wird.
#Ergebnisse und Statuscodes
Eine erneut ausgelieferte Antwort enthält X-Idempotent-Replayed: true und den ursprünglichen Status — behandeln Sie sie als die Antwort, nicht als abzugleichendes Duplikat. Jede Ablehnung nutzt die flache Struktur der Vorprüfungen.
| HTTP | Code | Bedeutung | Was tun |
|---|---|---|---|
| 400 | IDEMPOTENCY_STREAM_UNSUPPORTED | Idempotency-Key wurde bei einer Streaming-Anfrage gesendet. | Lassen Sie den Header bei Streaming-Aufrufen weg, oder setzen Sie stream:false, wenn Sie Replay-Schutz brauchen. |
| 400 | IDEMPOTENCY_BODY_UNREADABLE | Der Body konnte für das Idempotenz-Register nicht gehasht werden. | Senden Sie einen normalen JSON- oder Multipart-Body — Chunked-Bodys, die sich nicht puffern lassen, werden abgelehnt. |
| 409 | IDEMPOTENCY_PAYLOAD_CONFLICT | Dieser Schlüssel wurde bereits mit einem anderen Body, Pfad oder Query verwendet. | Erzeugen Sie einen neuen Schlüssel. Ein Schlüssel kennzeichnet genau eine Anfrage, nicht eine ganze Wiederholungsschleife. |
| 409 | IDEMPOTENCY_IN_PROGRESS | Die erste Anfrage mit diesem Schlüssel läuft noch. | Warten Sie Retry-After (2 s) ab und versuchen Sie es mit demselben Schlüssel erneut — Sie erhalten die ursprüngliche Antwort. |
| 409 | IDEMPOTENCY_RESULT_UNREPLAYABLE | Die ursprüngliche Anfrage ist abgeschlossen, ihre Antwort wurde jedoch versiegelt und kann nicht erneut ausgeliefert werden. | Nicht blind erneut senden. Gleichen Sie zuerst über den Task-Endpunkt oder Ihre eigenen Aufzeichnungen ab. |
| 503 | IDEMPOTENCY_UNAVAILABLE | Das Idempotenz-Register ist nicht verfügbar, daher blockiert die Prüfung lieber, statt eine doppelte Belastung zu riskieren. | Mit Backoff erneut versuchen — die Anfrage wurde nicht ausgeführt. |
#Wiederholungsschleife
Ein Schlüssel pro Job, bei jedem Versuch wiederverwendet, wobei 409 in-progress als „warten“ behandelt wird, nicht als „fehlgeschlagen“.
import time, uuid, requests
def submit_once(job_id: str, body: dict, api_key: str, tries: int = 5):
# Same key for every attempt of this job — that is what makes it safe.
key = str(uuid.uuid5(uuid.NAMESPACE_URL, f"video-job:{job_id}"))
for attempt in range(tries):
response = requests.post(
f"https://www.aisplice.store/v1/videos",
headers={
"Authorization": f"Bearer {api_key}",
"Idempotency-Key": key,
},
json=body,
timeout=60,
)
if response.status_code == 409:
code = response.json().get("code", "")
if code == "IDEMPOTENCY_IN_PROGRESS":
time.sleep(int(response.headers.get("Retry-After", 2)))
continue
# PAYLOAD_CONFLICT or RESULT_UNREPLAYABLE: a human decision,
# never a silent resubmit.
raise RuntimeError(response.text)
if response.status_code >= 500:
time.sleep(2 ** attempt)
continue
response.raise_for_status()
replayed = response.headers.get("X-Idempotent-Replayed") == "true"
return response.json(), replayed
raise TimeoutError(f"submit for {job_id} did not settle")Speichern Sie die Task-ID, bevor Sie irgendetwas wiederholen
Immer noch nicht gelöst?
Senden Sie uns die Anfrage-ID oder die Fehlermeldung, und wir sehen uns das an.