Erros e novas tentativas
Códigos de negócio, status HTTP, repetição e cobrança.
As respostas JSON da API nativa usam o envelope {code,msg,data,request_id}. Tome decisões por code, nunca por msg, e informe request_id ao suporte.
{
"code": 200,
"msg": "success",
"data": {},
"request_id": "req_…"
}Idioma das mensagens de erro
Os textos de erro feitos para pessoas podem voltar no idioma que você escolher. Isso vale para três campos: msg na resposta, errorMessage de uma tarefa com falha (tanto em recordInfo quanto nas entregas de webhook) e error.message nos objetos de erro das APIs compatíveis, seja no formato da OpenAI, da Anthropic ou do Google Gemini. O padrão é inglês. Códigos de idioma aceitos: en, zh-Hant, ja, ko, de, fr, es, pt-BR, ru.
Só o texto legível muda. Os valores de code e errorCode, de type e code na camada compatível com OpenAI, de code e status na camada compatível com Gemini e todos os nomes de campo são os mesmos em qualquer idioma. Tome decisões sempre pelos códigos, nunca analise o texto, e registre code e request_id nos seus logs e alertas. O cabeçalho de resposta Content-Language indica o idioma realmente usado. Por exemplo, para o mesmo 40201 (saldo insuficiente), msg é “Insufficient balance” por padrão; com Accept-Language: ja, msg vem em japonês e code continua 40201.
O idioma é definido nesta ordem:
- Cabeçalho Accept-Language: vale só para aquela requisição. Segue a ponderação padrão do HTTP: é escolhido o idioma reconhecido com o maior valor q. Variantes regionais caem no idioma correspondente: de-DE vira de, pt-PT vira pt-BR, e zh-TW, zh-HK e zh-Hant viram zh-Hant. O chinês só é oferecido em caracteres tradicionais, então zh-CN e zh-Hans não correspondem a nenhum idioma e o próximo candidato é avaliado. * conta como sem preferência.
- Configuração da conta: no console, em “Configurações → Idioma dos erros da API”. Vale para toda requisição feita com uma chave de API desta conta que não traga um Accept-Language reconhecível. A maioria dos SDKs de servidor e o curl não enviam esse cabeçalho por padrão, então, na prática, esta é a forma mais usada. Entregas de webhook não têm cabeçalho de requisição e seguem sempre a configuração da conta.
- Sem nenhum dos dois, vale o inglês.
# Default: no Accept-Language, no account setting
HTTP/1.1 402 Payment Required
Content-Language: en
{ "code": 40201, "msg": "Insufficient balance", "request_id": "req_…" }
# The same request with one extra header
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"
HTTP/1.1 402 Payment Required
Content-Language: ja
{ "code": 40201, "msg": "残高が不足しています", "request_id": "req_…" }Erros que não devem ser repetidos
400, 401, 403, 404, 40201, 40202 e 40301–40303 só mudam após corrigir entrada, credencial, permissão, saldo ou limite. Um 413 indica corpo grande demais: não repita sem mudanças; reduza-o ou use o upload de mídia.
Erros que podem ser repetidos
Em 429, respeite Retry-After. Para HTTP 500/503 e códigos de negócio 500/50301, use backoff exponencial com jitter. Um 409 depende da operação: repita apenas media pending ou o raro conflito concorrente de createTask com o mesmo Idempotency-Key e o mesmo payload. Conflito de chave com outro payload não deve ser repetido.
Em erro de rede de createTask, reutilize o mesmo Idempotency-Key. A mesma chave com outro payload retorna 409.
Cobrança
Uma solicitação rejeitada antes da criação não é cobrada. Depois, failed, expired e registros canceled históricos liberam toda a reserva. Uma nova tarefa aceita não pode ser cancelada; só succeeded é liquidada pelo uso real.
Consulte o contrato OpenAPI 3.1 para ver a definição completa dos campos.

