Erreurs
Tous les codes métier, leur statut HTTP, les actions à entreprendre et les nouvelles tentatives utiles.
En cas d’échec, la réponse donne deux informations : un nombre (code) identifiant le problème et une phrase (msg) pour le lecteur. Cette page liste tous les codes, leur sens et l’utilité d’une nouvelle tentative. Pour corriger rapidement un symptôme, commencez par Dépannage.
L’enveloppe
Les réponses JSON natives de tâches utilisent cette enveloppe avec les mêmes quatre champs. Analysez les réponses compatibles /v1 et les SSE selon leurs propres protocoles :
{ "code": 200, "msg": "success", "data": { }, "request_id": "req_…" }codeest un code métier, pas un statut HTTP.200signifie succès.- En cas d’échec,
dataest absent, pasnull: vous recevezcode,msgetrequest_id. Une seule exception : quelques échecs de la bibliothèque d’assets ajoutentdata.reason. msgs’adresse au lecteur : son texte et sa langue peuvent changer ; voir ci-dessous. Ne décidez jamais selon ce texte : utilisezcode.request_idfigure aussi dans l’en-têteX-Request-Id. Indiquez-le pour signaler un problème.
Le statut HTTP est également correct. Utilisez l’un ou l’autre, mais un seul : ils divergent pour les codes spécifiques, par exemple code: 40201 avec HTTP 402 pour un solde insuffisant. Les mélanger finit par faire manquer un cas.
Nous recommandons code. 404 dit seulement « introuvable » ; 40201 précise que le solde disponible est insuffisant.
Toutes les réponses ne sont pas du JSON
Une réponse impossible à analyser comme JSON, par exemple une page texte ou HTML du réseau périphérique, n’a pas de code. Traitez-la selon son statut HTTP, journalisez le début du corps et ne répétez pas aveuglément un 403 : une restriction régionale peut être impossible à résoudre par nouvelle tentative.
Langue des messages d’erreur
Le texte lisible des erreurs peut être renvoyé dans la langue choisie. L’anglais est la valeur par défaut. Seuls trois emplacements suivent ce choix :
msgdans l’enveloppe ;errorMessaged’une tâche échouée, dansrecordInfoet les callbacks webhook, avec une exception ci-dessous ;error.messagedans les objets d’erreur compatibles, aux formats OpenAI, Anthropic ou Google Gemini (/v1beta).
Codes de langues acceptés : en, ja, ko, de, fr, es, pt-BR, ru, it, pl.
L’exception : lorsque le modèle a fourni un motif précis, par exemple une référence illisible ou une restriction de droits sur l’audio généré, errorMessage reprend ce motif en anglais, après retrait des détails internes comme les noms de services, hôtes, URL et IDs de requêtes. Vous pouvez ainsi comprendre le problème réel. Les motifs concernant l’état du compte ou la facturation ne sont jamais transmis tels quels ; notre propre message les remplace. Content-Language décrit toujours msg, et vos décisions doivent toujours utiliser errorCode.
Choisir la langue
Le premier cas applicable l’emporte :
- L’en-tête de requête
Accept-Language, uniquement pour cette requête. La pondération HTTP standard s’applique : la langue reconnue avec le plus grandqest retenue. Les variantes régionales sont ramenées à leur langue :de-DEvautde, etpt-PTvautpt-BR. Le chinois n’étant pas proposé, ses tags ne correspondent à rien et le candidat suivant est essayé.*signifie aucune préférence. - Le réglage du compte, dans Paramètres → Langue des erreurs API de la console. Il couvre toutes les requêtes des clés du compte sans
Accept-Languagereconnu. La plupart des SDK serveur et curl n’envoient pas cet en-tête par défaut ; les intégrations reposent donc généralement sur ce réglage. Les callbacks webhook n’ont pas d’en-tête de requête à consulter et suivent toujours le compte. - Sinon, l’anglais.
Les réponses d’erreur portent un en-tête Content-Language indiquant la langue réellement utilisée pour le message.
Seul le texte lisible change
code, errorCode, les type et code compatibles OpenAI, les code et status compatibles Gemini et tous les noms de champs restent identiques dans chaque langue. Décidez selon les codes, jamais en analysant le texte ; enregistrez code et request_id dans vos journaux et alertes.
Exemple
Le même 40201, solde insuffisant, revient en anglais par défaut :
HTTP/1.1 402 Payment Required
Content-Language: en
{ "code": 40201, "msg": "Insufficient balance", "request_id": "req_…" }Ajoutez un seul en-tête Accept-Language: ja ; le reste est le même appel de création que dans le démarrage rapide :
curl -X POST https://api.spicyapi.ai/api/v1/jobs/createTask \
-H "Authorization: Bearer $SPICY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $SPICY_IDEMPOTENCY_KEY" \
-H "Accept-Language: ja" \
--data "$TASK_PAYLOAD"msg est désormais en japonais ; code reste 40201 :
HTTP/1.1 402 Payment Required
Content-Language: ja
{ "code": 40201, "msg": "残高が不足しています", "request_id": "req_…" }Codes généraux
code | HTTP | Signification | Réessayer ? |
|---|---|---|---|
200 | 200 | Succès | — |
400 | 400 | Requête mal formée ou paramètres invalides | Non. Corrigez puis renvoyez |
40003 | 400 | Taille, type ou contenu d’un fichier envoyé différent de la déclaration du ticket | Non. Demandez une URL avec le bon contentType et la bonne taille, renvoyez puis validez |
40004 | 400 | Requête valide, mais cette combinaison de réglages n’est pas disponible maintenant sur le modèle | Non. Modifiez le réglage nommé dans msg, par exemple résolution ou ratio, ou choisissez un autre modèle. Voir ci-dessous |
401 | 401 | Échec d’authentification ; msg précise lequel des trois cas | Non. Corrigez l’en-tête ou la clé |
403 | 403 | Non autorisé. Avec une clé valide, le compte est restreint ; voir ci-dessous. Une adresse e-mail non vérifiée renvoie plutôt 40310 | Non |
404 | 404 | Inexistant ou ne vous appartenant pas | Non |
409 | 409 | Conflit avec l’état actuel | Parfois, voir ci-dessous |
40901 | 409 | Devis expiré, requête ou tarif modifié | Demandez et confirmez un nouveau devis ; récupérez les requêtes acceptées avec la clé d’idempotence originale |
413 | 413 | Corps au-delà de la taille acceptée par le serveur | Non. Réduisez le corps ou envoyez le média par la procédure dédiée |
429 | 429 | Trop de requêtes | Généralement. Attendez selon Retry-After. Un type de 429 ne concerne pas la vitesse ; voir Limites de débit |
500 | 500 | Problème de notre côté | Oui. Attendez progressivement puis réessayez |
503 | 503 | Service auxiliaire temporairement indisponible : devis, stockage d’images intégrées ou envois de médias | Oui. Respectez Retry-After s’il existe puis réessayez ; pour createTask, avec le même Idempotency-Key. Si cela persiste sans Retry-After, suivez msg, par exemple une URL HTTPS publique plutôt qu’une image intégrée |
503 et 50301 ont le même statut HTTP mais des codes métier différents : 503 concerne un service auxiliaire, 50301 le modèle lui-même.
Distinguer les trois 401
Trois erreurs très différentes produisent 401, avec des corrections différentes. code reste 401 dans tous les cas ; msg les distingue.
msg en anglais | Situation réelle | Correction |
|---|---|---|
Missing credentials: send your API key in the Authorization header as "Bearer sk-spicy-..." (sur les points de terminaison compatibles /v1 et /v1beta : …as "Authorization: Bearer sk-spicy-...", x-api-key, or x-goog-api-key) | Aucun identifiant n’accompagne la requête | Le client perd l’en-tête. Vérifiez l’intercepteur, le proxy et le chargement de la variable d’environnement dans le processus actif |
API key format is not recognized: keys begin with sk-spicy- | Un identifiant est arrivé, mais ce n’est pas l’un des nôtres | Vous avez collé une session de console ou une clé d’un autre service. Les clés SpicyAPI commencent par sk-spicy- ; echo "${SPICY_API_KEY:0:9}" doit afficher exactement ce préfixe |
Credentials are invalid or expired | Bon format, mais clé inexistante, révoquée ou expirée | Vérifiez-la sur la page Clés API ; créez une remplaçante si nécessaire. Réessayer ne produira jamais 200 |
Le cas intermédiaire est déterminé sans recherche en base, expliquant l’information que le troisième ne donne pas : cette chaîne n’a jamais pu fonctionner. Le troisième message est volontairement identique pour une clé inexistante, révoquée ou expirée, afin d’empêcher l’exploration des clés existantes.
Ces chaînes sont présentées ici en anglais ; msg suit le choix de langue précédent et son texte n’est pas un contrat. Décidez selon code et utilisez le message pour la lecture, l’affichage ou les journaux, jamais pour une comparaison logique.
Le compte ne peut pas appeler l’API
La clé est valide dans ces deux cas ; c’est le compte qui ne peut pas encore appeler l’API.
40310 signifie adresse e-mail non vérifiée. Le message est Verify your account email to run models and call the API… :
- Ouvrez la console. Une bannière indique que l’adresse n’est pas vérifiée et permet de renvoyer le mail.
- Ouvrez le lien de vérification ; vérifiez les indésirables.
- Réessayez le même appel. Aucune nouvelle clé n’est nécessaire.
La console reste utilisable pendant le blocage API, notamment pour l’historique.
Un simple 403 avec This account cannot call the API right now signifie compte restreint. Contactez le support avec request_id.
Solde et plafonds
code | HTTP | Signification | Action |
|---|---|---|---|
40201 | 402 | Solde ne couvrant pas le coût estimé | Ajoutez des fonds dans Facturation ; voir Configuration du compte. Vérifiez GET /api/v1/chat/credit |
40202 | 402 | Plafond de dépenses atteint | Lisez msg. Plafond de clé (This key has reached its …) : relevez-le dans Clés API ou attendez la réinitialisation. Limite d’équipe (Workspace … budget has been reached) : demandez au propriétaire, administrateur ou gestionnaire de budget de la relever sur la page Équipe. Plafond de plateforme (Platform quota for today is exhausted…) : vous ne pouvez pas le modifier ; réessayez après 00:00 UTC. Les plafonds quotidiens repartent à 00:00 UTC, les mensuels le 1er à 00:00 UTC ; un plafond total ne se réinitialise jamais |
Réessayer n’aide dans aucun cas : le solde et les plafonds ne changent pas parce que vous redemandez. Voir Plafonds de dépenses.
Permissions
code | HTTP | Signification | Action |
|---|---|---|---|
40301 | 403 | La clé n’est pas autorisée à appeler ce modèle | Élargissez la liste de modèles autorisés dans la console |
40302 | 403 | Adresse source hors de la liste d’IP autorisées de la clé | Ajoutez-la ou retirez cette restriction |
40303 | 403 | Service non proposé dans cette région | Aucun contournement possible ; voir Régions desservies |
40310 | 403 | Adresse e-mail du compte non vérifiée, donc exécution impossible | Ouvrez le lien d’inscription ou renvoyez-le depuis la console. La clé fonctionne dès la vérification, sans modification de votre côté |
Aucune de ces erreurs ne se résout par nouvelle tentative.
Codes de raison de la bibliothèque d’assets
Les échecs sur les points d’accès de la bibliothèque d’assets (/api/v1/assets…) peuvent ajouter à l’enveloppe habituelle un champ lisible par machine, data.reason :
{ "code": 400, "msg": "…", "data": { "reason": "asset_library_locked" }, "request_id": "req_…" }code, le statut HTTP, msg et l’errorCode de la tâche sont identiques avec ou sans raison : votre gestion actuelle continue de fonctionner. La raison n’apparaît que sur les points d’accès de la bibliothèque d’assets, jamais sur les autres points d’accès natifs, et la couche compatible OpenAI et les autres couches de compatibilité gardent leurs propres formes d’erreur. La liste peut s’allonger : traitez une valeur inconnue comme une raison absente.
data.reason | HTTP | Signification | Que faire |
|---|---|---|---|
asset_library_locked | 400 | La bibliothèque d’assets s’ouvre à la première recharge | Rechargez. Les assets déjà enregistrés restent utilisables |
asset_library_full | 400 | Le quota de stockage (éléments ou octets) est plein | Supprimez des assets ou passez au forfait supérieur ; GET /api/v1/assets/usage indique le suivant |
asset_file_too_large | 400 | Le fichier dépasse la limite par fichier du forfait | Utilisez un fichier plus petit ou passez au forfait supérieur |
asset_daily_limit | 429 | Le nombre quotidien de nouveaux assets est atteint | Attendez 00:00 UTC et respectez Retry-After |
asset_storage_full | 503 | Le stockage de toute la plateforme est plein | Réessayez plus tard |
asset_permission_denied | 403 | Votre rôle dans l’équipe n’autorise pas cette modification | Demandez à un propriétaire ou administrateur de l’équipe, ou utilisez une clé dont le créateur a un rôle autorisé |
asset_workspace_forbidden | 403 | Cette clé n’atteint pas cette bibliothèque, par exemple parce que le membre qui a créé la clé d’équipe a quitté l’équipe | Créez une nouvelle clé dans l’espace de travail voulu |
asset_entity_name_taken | 409 | La bibliothèque contient déjà un personnage portant ce nom (sans tenir compte de la casse). Les personnages se nomment sur la page Assets de l’application web, donc l’API en lecture seule ne le renvoie pas aujourd’hui | Choisissez un autre nom |
Disponibilité du modèle
code | HTTP | Signification | Réessayer ? |
|---|---|---|---|
50301 | 503 | Modèle actuellement indisponible | Oui. Réessayez plus tard ou choisissez un autre modèle |
50302 | 503 | Requête de texte échouée au modèle avant livraison, avec ou sans streaming ; réservation remboursée | Oui. Renvoyez avec un nouveau Idempotency-Key |
40004 | 400 | Le modèle fonctionne, mais pas avec ces réglages | Non. Modifiez le réglage nommé dans msg |
50301 signifie que le modèle n’a pas pu accepter la tâche à l’envoi : il n’est pas proposé, n’a pas de tarif actif ou n’a pas de capacité de génération disponible. Les problèmes temporaires de capacité peuvent se résoudre par tentatives bornées. Un modèle indisponible ou sans tarif actif ne sera pas réparé par des requêtes répétées. Actualisez le catalogue et obtenez la confirmation de l’utilisateur avant de changer de modèle.
40004 et 50301 sont volontairement distincts. 50301 signifie qu’aucune tâche n’est acceptée pour l’instant ; attendre peut aider. 40004 signifie que le modèle fonctionne mais refuse cette combinaison, avec le réglage entre parenthèses dans msg, par exemple This model cannot serve this parameter combination right now (…). Attendre n’aide pas ; modifier une valeur, oui. Aucun des deux ne crée de tâche ni ne réserve de fonds.
Les échecs après acceptation apparaissent comme state: failed
Un échec de génération après que createTask a renvoyé un ID apparaît dans recordInfo comme state: "failed" avec errorCode / errorMessage. La réservation est normalement libérée intégralement, sauf certains refus de contenu explicitement annoncés comme facturables sur la page du modèle. La situation équivalente à 40004, découverte seulement après acceptation, apparaît comme errorCode: "unsupported_combination". N’ajoutez pas de branches de codes métier synchrones absentes de cette page.
Codes d’échec des tâches
Un échec après acceptation arrive dans l’errorCode de recordInfo. L’ensemble est fermé : les diagnostics internes n’apparaissent pas ici ; traitez toute valeur hors liste comme upstream_failed.
errorCode | Signification | Réessayer ? |
|---|---|---|
invalid_request | Paramètres non acceptés | Non. Corrigez puis soumettez |
unsupported_combination | Combinaison non prise en charge actuellement | Non. Choisissez d’autres réglages |
content_rejected | Le modèle choisi a refusé le contenu. SpicyAPI n’examine pas les requêtes ; voir Responsabilité du contenu et des usages | Non. Modifiez le prompt ou choisissez un autre modèle |
rate_limited | Service de génération occupé | Oui. Attendez progressivement puis réessayez |
upstream_unavailable | Génération temporairement indisponible | Oui. Réessayez prochainement |
invalid_asset | Référence plus disponible | Pas par relance. retry reprend l’entrée originale ; renvoyez le fichier et créez une tâche avec la nouvelle URI |
generation_failed | Génération commencée sans résultat | Peut-être. Les mêmes entrées échouent généralement de la même façon |
timeout | Échéance dépassée sans fin de tâche | Peut-être. Essayez une durée plus courte ou une résolution inférieure |
upstream_failed | Catégorie générale pour le reste | Oui. Attendez progressivement puis réessayez |
Les tâches échouées ou expirées libèrent normalement la réservation entière. Certains refus de contenu sont facturés au devis accepté uniquement si la page du modèle annonce explicitement cette exception. Vérifiez settled et cost pour la facturation finale. errorMessage est destiné au lecteur : il explique le motif, peut reprendre celui du modèle en anglais, voir plus haut, et sa formulation change. Décidez uniquement selon errorCode. Une « nouvelle tentative » signifie ici une nouvelle tâche, facturée à nouveau si elle réussit.
Les erreurs qui coûtent de l’argent
L’état de la tâche et celui de la connexion sont deux faits distincts.
Les créations explicitement refusées, tâches expirées et anciennes traces annulées n’entraînent aucun coût de génération. Les tâches échouées sont normalement gratuites, sauf certains refus de contenu explicitement annoncés comme facturables sur la page du modèle. Un timeout client ou une déconnexion n’est pas un échec de tâche. Une tâche acceptée ne peut pas être annulée : récupérez l’originale et vérifiez son état final et sa facturation. Un flux de texte déconnecté peut être facturé si une utilisation valide a déjà été enregistrée.
| Situation | Facturée ? |
|---|---|
L’API refuse explicitement createTask sans créer de tâche, par exemple 40201, 40202, 40004 ou 50301 | Non. Création et réservation partagent une transaction ; une erreur de passerelle ou une réponse absente ne prouve pas le refus |
| Timeout à l’envoi, onglet fermé ou connexion coupée | Pas encore connu. Récupérez l’acceptation avec la clé d’idempotence originale ; ce n’est pas une relance gratuite |
createTask renvoie 202, puis la tâche devient failed / expired | Normalement aucune facture. Certains résultats failed / content_rejected sont facturés au devis accepté si la page l’annonce explicitement. Lisez settled et cost |
Ancienne tâche en canceled | Non. État de compatibilité, pas une action actuellement disponible |
createTask renvoie 202, tâche succeeded | Oui, selon l’utilisation réelle, plafonnée à la réservation acceptée. Le reste est libéré ; aucun supplément au-delà n’est prélevé |
Erreur de recordInfo, chat/credit ou common/* | Non. Ces points de terminaison ne sont jamais facturés |
Limitation de débit (429) ou déduplication par idempotence | Non. La première n’a jamais été acceptée ; la seconde renvoie la tâche originale facturée une fois |
La facturation définitive ou la libération se fait automatiquement, même après une interruption de processus. Les échecs ordinaires libèrent la totalité ; certains refus de contenu annoncés sur la page sont facturés au devis accepté. Vérifiez la facturation de la tâche et le solde ; voir Facturation.
Quand réessayer un 409
| Cas | Réessayer ? |
|---|---|
Rare conflit de createTask simultanés avec la même clé et un corps inchangé | Oui. Attendez quelques centaines de millisecondes puis réessayez avec la même clé. Voir Idempotence |
| Même clé déjà utilisée pour un autre corps ou une autre clé API | Non. Arrêtez et corrigez l’appartenance de la clé ; réessayer ne résout pas le conflit |
Images intégrées ou validation d’envoi en cours (Retry-After possible) | Oui. Attendez Retry-After ou quelques secondes, puis renvoyez avec le même Idempotency-Key |
| Tarif ou configuration du compte modifié pendant la requête | Oui. Redemandez un devis si vous en utilisez, puis renvoyez |
| Fichier encore en cours de copie | Oui. Attendez quelques secondes puis redemandez le lien |
jobs/retry sur une source pas encore terminée ou dont la facturation n’est pas finalisée | Oui, plus tard. Attendez un état terminal et settled à true, puis relancez |
jobs/retry sur une tâche réussie ou une entrée déjà retirée par conservation | Non. Créez une nouvelle tâche avec createTask |
| URL d’envoi ou fichier envoyé expiré | Non. Renvoyez le fichier |
Écrire les nouvelles tentatives
Ne réessayez pas aveuglément
400, 401, 40004, 40201 et les erreurs similaires d’entrée ou d’autorisation donnent toujours la même réponse. Chaque tentative marquée « Non » est inutile et consomme votre propre quota de débit.
Utilisez une temporisation exponentielle avec variation aléatoire, pour éviter que tous les échecs reviennent simultanément :
// 409 is operation-specific and must be handled at the call site.
const RETRYABLE = new Set([429, 500, 503, 50301]);
async function callWithRetry(path, init, { attempts = 4 } = {}) {
for (let i = 0; i < attempts; i++) {
const res = await fetch(`https://api.spicyapi.ai/api/v1${path}`, init);
// A page from the edge network is not our JSON envelope
if (!res.headers.get('content-type')?.includes('json')) {
const text = await res.text();
throw new Error(`HTTP ${res.status}, not JSON: ${text.slice(0, 200)}`);
}
const body = await res.json();
if (body.code === 200) return body.data;
if (!RETRYABLE.has(body.code)) {
throw new Error(`${body.code} ${body.msg} (request_id=${body.request_id})`);
}
// When the server says how long to wait, trust it
const retryAfter = Number(res.headers.get('retry-after'));
const backoff = Number.isFinite(retryAfter) && retryAfter > 0
? retryAfter * 1000
: 2 ** i * 1000 + Math.random() * 500;
await new Promise((r) => setTimeout(r, backoff));
}
throw new Error('out of retries');
}import random, time, requests
# 409 is operation-specific and must be handled at the call site.
RETRYABLE = {429, 500, 503, 50301}
BASE = "https://api.spicyapi.ai/api/v1"
def call_with_retry(method: str, path: str, attempts: int = 4, **kwargs) -> dict:
for i in range(attempts):
res = requests.request(method, f"{BASE}{path}", **kwargs)
# A page from the edge network is not our JSON envelope
try:
body = res.json()
except ValueError:
raise RuntimeError(f"HTTP {res.status_code}, not JSON: {res.text[:200]}")
if body["code"] == 200:
return body["data"]
if body["code"] not in RETRYABLE:
raise RuntimeError(f'{body["code"]} {body["msg"]} (request_id={body.get("request_id")})')
# When the server says how long to wait, trust it
retry_after = res.headers.get("retry-after")
backoff = float(retry_after) if retry_after else 2**i + random.random() * 0.5
time.sleep(backoff)
raise RuntimeError("out of retries")package main
import (
"encoding/json"
"fmt"
"io"
"math/rand"
"net/http"
"strconv"
"time"
)
// retryable lists the codes worth another attempt. Anything else returns
// the same answer however many times you ask — and each ask eats your own
// rate limit.
// Whether the generation itself failed is read from recordInfo's state.
var retryable = map[int]bool{429: true, 500: true, 503: true, 50301: true}
type envelope struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data json.RawMessage `json:"data"`
RequestID string `json:"request_id"`
}
func callWithRetry(newReq func() (*http.Request, error), attempts int, out any) error {
for i := 0; i < attempts; i++ {
req, err := newReq()
if err != nil {
return err
}
res, err := http.DefaultClient.Do(req)
if err != nil {
// Transport-level failure: the request may well have arrived.
// On createTask, send the same Idempotency-Key or this retry
// turns into a second generation and a second charge.
time.Sleep(backoff(i, ""))
continue
}
var env envelope
decErr := json.NewDecoder(res.Body).Decode(&env)
io.Copy(io.Discard, res.Body)
res.Body.Close()
if decErr != nil {
// Not our JSON envelope, for example a page from the edge network.
return fmt.Errorf("HTTP %d, response is not JSON: %w", res.StatusCode, decErr)
}
if env.Code == 200 {
return json.Unmarshal(env.Data, out)
}
if !retryable[env.Code] {
return fmt.Errorf("%d %s (request_id=%s)", env.Code, env.Msg, env.RequestID)
}
// When the server says how long to wait, trust it
time.Sleep(backoff(i, res.Header.Get("Retry-After")))
}
return fmt.Errorf("out of retries")
}
// backoff trusts Retry-After when present, otherwise backs off
// exponentially with jitter so a batch of failures does not come back
// as one thundering herd.
func backoff(attempt int, retryAfter string) time.Duration {
if s, err := strconv.Atoi(retryAfter); err == nil && s > 0 {
return time.Duration(s) * time.Second
}
base := time.Duration(1<<attempt) * time.Second
return base + time.Duration(rand.Intn(500))*time.Millisecond
}Pour relancer createTask, envoyez toujours le même Idempotency-Key. Sinon, « succès réel mais réponse perdue » devient une génération et une facturation en double.
Diagnostic
Pour une erreur incompréhensible, suivez cette liste :
request_id: il nous permet de retrouver la requête exacte.code: consultez les tableaux précédents.- Journaux de la console : collez l’ID de tâche ou
request_iddans la recherche de Journaux pour ouvrir état, coût, latence, clé d’envoi, code d’erreur et motif. Les paramètres et résultats sont affichés uniquement pendant leur conservation et, dans une équipe, aux rôles autorisés à lire le contenu.
Le msg d’un 500 est toujours un « service temporairement indisponible » générique, sans détails internes : aucune structure interne, aucun nom de composant ni aucune trace d’exécution n’apparaît dans une réponse. Seul request_id permet de retrouver ces détails.
Contactez-nous par Support dans la console ou par e-mail à support@spicyapi.ai. Incluez request_id ou l’ID de tâche, l’heure UTC et code. N’envoyez jamais de clé API.
OpenAPI et index des points de terminaison
Contrat OpenAPI 3.1 téléchargeable, points de terminaison publics et guides associés, en-têtes communs et origine de production.
Limites de débit
Fonctionnement des quotas de lecture et d’écriture, limites supplémentaires et différence entre débit et concurrence.

