Erros
Todos os códigos de negócio, seus status HTTP, as ações recomendadas e quais erros vale a pena repetir.
Quando uma chamada falha, a resposta informa duas coisas: um número (code) que identifica o tipo de problema e uma frase (msg) para leitura humana. Esta página lista cada número, seu significado e se tentar novamente pode ajudar. Se você só precisa resolver um sintoma rapidamente, comece por Solução de problemas.
O envelope
Respostas JSON da API nativa de tarefas usam este envelope, com os mesmos quatro campos em cada resposta. Interprete respostas de compatibilidade /v1 e SSE conforme seus próprios protocolos:
{ "code": 200, "msg": "success", "data": { }, "request_id": "req_…" }codeé um código de negócio, não um status HTTP.200significa sucesso.- Em falhas,
datafica ausente, nãonull; você recebecode,msgerequest_id. A única exceção: algumas falhas da biblioteca de ativos acrescentamdata.reason. msgé para pessoas: a redação pode mudar, assim como o idioma; veja abaixo. Nunca baseie a lógica nela; usecode.request_idtambém retorna no cabeçalhoX-Request-Id. Informe-o ao relatar um problema.
O status HTTP também é definido corretamente. Baseie a lógica em um deles, mas somente em um: eles diferem nos códigos específicos, como saldo insuficiente, que é code: 40201 com HTTP 402. Misturar os dois acaba deixando algum caso sem tratamento.
Recomendamos usar code. 404 só diz “não encontrado”; 40201 informa que o saldo disponível é insuficiente.
Nem toda resposta é JSON
Uma resposta que não pode ser interpretada como JSON, como texto puro ou uma página HTML da nossa rede de borda, não tem code. Trate-a pelo status HTTP, registre o início do corpo e não repita 403 sem verificar: pode ser um bloqueio regional que nenhuma nova tentativa resolve.
Idioma das mensagens de erro
O texto de erro para leitura humana pode ser retornado no idioma escolhido por você. O padrão é inglês. Somente estes três campos seguem a escolha:
msgno envelope de resposta;errorMessagede uma tarefa com falha, tanto emrecordInfoquanto em callbacks de webhook, com uma exceção abaixo;error.messagenos objetos de erro dos endpoints compatíveis, nos formatos OpenAI, Anthropic ou Google Gemini (/v1beta).
Códigos de idioma aceitos: en, ja, ko, de, fr, es, pt-BR, ru, it, pl.
A exceção: quando o próprio modelo informa um motivo específico da falha, como uma imagem de referência que não conseguiu ler ou uma restrição de direitos autorais no áudio gerado, errorMessage apresenta esse motivo em inglês, sem detalhes internos como nomes de serviços, hosts, URLs e IDs de solicitação, para que você entenda o que aconteceu. Motivos que mencionam estado da conta ou faturamento nunca são repassados; você recebe nossa própria mensagem. Content-Language ainda descreve msg, e errorCode é sempre o valor para a lógica do seu programa.
Escolher o idioma
Vale a primeira opção aplicável:
- Cabeçalho
Accept-Languageda solicitação, apenas para aquela chamada. Aplica-se a ponderação HTTP padrão: usamos o idioma reconhecido com maior valorq. Variantes regionais são agrupadas no idioma;de-DEconta comode, ept-PT, comopt-BR. Chinês não é oferecido, portanto nenhuma etiqueta chinesa corresponde a um idioma, e o próximo candidato é tentado.*significa sem preferência. - Configuração da conta, em Configurações → Idioma dos erros da API no console. Ela abrange toda solicitação com uma chave de API da conta que não tenha um
Accept-Languagereconhecível. A maioria dos SDKs no servidor e o curl não envia esse cabeçalho por padrão; por isso, esta é a opção usada pela maioria das integrações. Callbacks de webhook não têm cabeçalho de solicitação para essa escolha e sempre seguem a configuração da conta. - Caso contrário, inglês.
Respostas de erro incluem um cabeçalho Content-Language que identifica o idioma efetivamente usado na mensagem.
Somente o texto para leitura humana muda
code, errorCode, type e code compatíveis com OpenAI, code e status compatíveis com Gemini e todos os nomes de campos permanecem iguais em qualquer idioma. Baseie a lógica nos códigos, nunca na redação; registre code e request_id nos logs e alertas.
Exemplo
O mesmo 40201, saldo insuficiente, retorna em inglês por padrão:
HTTP/1.1 402 Payment Required
Content-Language: en
{ "code": 40201, "msg": "Insufficient balance", "request_id": "req_…" }Adicione um cabeçalho Accept-Language: ja; o restante é a mesma chamada de criação de tarefa dos primeiros passos:
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 agora está em japonês; code continua sendo 40201:
HTTP/1.1 402 Payment Required
Content-Language: ja
{ "code": 40201, "msg": "残高が不足しています", "request_id": "req_…" }Códigos gerais
code | HTTP | Significado | Tentar novamente? |
|---|---|---|---|
200 | 200 | Sucesso | — |
400 | 400 | Solicitação malformada ou parâmetros inválidos | Não. Corrija e reenvie |
40003 | 400 | Tamanho, tipo ou conteúdo de um arquivo enviado não corresponde ao declarado ao solicitar a URL de upload | Não. Solicite outra URL de upload com contentType e tamanho corretos, envie novamente e confirme |
40004 | 400 | A solicitação é válida, mas o modelo não pode atender essa combinação de configurações agora | Não. Altere a configuração indicada em msg, como resolução ou proporção, ou escolha outro modelo. Veja abaixo |
401 | 401 | A autenticação falhou; msg indica qual dos três casos | Não. Corrija o cabeçalho ou a chave |
403 | 403 | Não permitido. Em uma chamada com chave válida, a conta está restrita; veja abaixo. E-mail não verificado retorna 40310 | Não |
404 | 404 | Não existe ou não pertence a você | Não |
409 | 409 | Conflito com o estado atual | Às vezes; veja abaixo |
40901 | 409 | Orçamento expirou, solicitação mudou ou preço mudou | Obtenha e confirme outro orçamento; recupere solicitações aceitas com a chave de idempotência original |
413 | 413 | O corpo da solicitação ultrapassa o limite de tamanho aceito pelo servidor | Não. Reduza o corpo ou envie a mídia pelo fluxo de upload |
429 | 429 | Solicitações demais | Normalmente. Aguarde conforme Retry-After. Um tipo de 429 não se refere à velocidade; veja Limites de solicitações |
500 | 500 | Houve uma falha no nosso serviço | Sim. Aguarde e tente novamente |
503 | 503 | Um serviço de apoio, como orçamentos, armazenamento de imagens inline ou uploads de mídia, está temporariamente indisponível | Sim. Espere conforme Retry-After quando presente e repita; em createTask, use o mesmo Idempotency-Key. Se persistir sem Retry-After, siga msg, como usar uma URL HTTPS pública em vez de imagem inline |
503 e 50301 compartilham status HTTP, mas são códigos de negócio diferentes: 503 trata de um serviço de apoio; 50301, do próprio modelo.
Diferenciar os três erros 401
Três erros bem diferentes de autenticação retornam 401 e exigem correções diferentes. O code permanece 401 em todos; msg permite diferenciá-los.
msg em inglês | O que aconteceu | O que mudar |
|---|---|---|
Missing credentials: send your API key in the Authorization header as "Bearer sk-spicy-..." (nos endpoints compatíveis /v1 e /v1beta: …as "Authorization: Bearer sk-spicy-...", x-api-key, or x-goog-api-key) | A solicitação chegou sem nenhuma credencial | O cliente está omitindo o cabeçalho. Confira o interceptor, o proxy e se a variável de ambiente foi carregada no processo em execução |
API key format is not recognized: keys begin with sk-spicy- | Uma credencial chegou, mas não é uma chave nossa | Você colou o valor de uma sessão do console ou uma chave de outro serviço. Chaves da SpicyAPI começam com sk-spicy-; echo "${SPICY_API_KEY:0:9}" deve exibir exatamente esse prefixo |
Credentials are invalid or expired | A chave tem nosso formato, mas não existe, foi revogada ou expirou | Confira-a na página de chaves de API; se revogada ou expirada, crie uma substituta. Tentar novamente nunca produzirá um 200 |
O caso intermediário é identificado sem consultar o banco de dados; por isso, permite afirmar algo que o terceiro não permite: aquela string nunca poderia funcionar. A terceira mensagem é intencionalmente igual para uma chave inexistente, revogada ou expirada, para que a resposta não possa ser usada para investigar quais chaves existem.
As strings aqui aparecem em inglês; msg segue a escolha de idioma acima, e sua redação não faz parte do contrato. Baseie a lógica em code e use a mensagem para ler, exibir ou registrar, não para comparar com um texto fixo.
A conta não pode chamar a API
Nestes dois casos, a chave é válida; é a conta que ainda não pode chamar a API.
40310 significa e-mail ainda não verificado. A mensagem é Verify your account email to run models and call the API…:
- Abra o console. Um aviso no topo informa que o e-mail não foi verificado e permite reenviar a mensagem de verificação.
- Abra o link no e-mail de verificação; confira a pasta de spam.
- Repita a mesma chamada. Não é necessário criar outra chave.
O console continua funcionando enquanto a API está bloqueada; você ainda pode consultar o histórico.
Um 403 simples com This account cannot call the API right now significa conta restrita. Contate o suporte com o request_id.
Saldo e limites
code | HTTP | Significado | O que fazer |
|---|---|---|---|
40201 | 402 | O saldo não cobre o custo estimado | Adicione saldo em Faturamento no console; veja Configuração da conta. Confira GET /api/v1/chat/credit |
40202 | 402 | Um limite de gastos foi atingido | Leia msg para identificar qual. Limite da chave (This key has reached its …): aumente-o na página de chaves de API ou espere o reinício. Limite da equipe (Workspace … budget has been reached): peça a um proprietário, administrador ou gestor de orçamento para aumentá-lo na página Equipe. Limite da plataforma (Platform quota for today is exhausted…): você não pode alterá-lo; tente após 00:00 UTC. Limites diários reiniciam às 00:00 UTC; mensais, no dia 1 às 00:00 UTC; o total nunca reinicia |
Não vale repetir nenhum dos dois: saldo e limites não mudam por você perguntar de novo. Veja Limites de gastos.
Permissões
code | HTTP | Significado | O que fazer |
|---|---|---|---|
40301 | 403 | Esta chave não pode chamar este modelo | Amplie a lista de modelos permitidos da chave no console |
40302 | 403 | O endereço de origem não está na lista de IPs permitidos da chave | Adicione-o ou remova a restrição de IP dessa chave |
40303 | 403 | O serviço não é oferecido nesta região | Não pode ser contornado. Veja Onde operamos |
40310 | 403 | O e-mail da conta ainda não foi verificado, impedindo a execução de modelos | Abra o link de verificação do e-mail de cadastro ou reenvie-o pelo Console. A chave funciona assim que o endereço é verificado, sem outra alteração |
Nenhum desses erros é resolvido por novas tentativas.
Códigos de motivo da biblioteca de ativos
Falhas nos endpoints da biblioteca de ativos (/api/v1/assets…) podem acrescentar ao envelope usual um campo legível por máquina, data.reason:
{ "code": 400, "msg": "…", "data": { "reason": "asset_library_locked" }, "request_id": "req_…" }code, o status HTTP, msg e o errorCode da tarefa são os mesmos com ou sem motivo, então o seu tratamento atual continua funcionando. O motivo aparece só nos endpoints da biblioteca de ativos, nunca em outros endpoints nativos, e a camada compatível com OpenAI e as demais camadas de compatibilidade mantêm seus próprios formatos de erro. A lista pode crescer: trate um valor desconhecido como motivo ausente.
data.reason | HTTP | Significado | O que fazer |
|---|---|---|---|
asset_library_locked | 400 | A biblioteca de ativos é liberada na primeira recarga | Faça uma recarga. Os ativos já salvos continuam utilizáveis |
asset_library_full | 400 | A cota de armazenamento (itens ou bytes) está cheia | Exclua ativos ou suba de plano; GET /api/v1/assets/usage mostra o próximo |
asset_file_too_large | 400 | O arquivo ultrapassa o limite por arquivo do plano | Use um arquivo menor ou suba de plano |
asset_daily_limit | 429 | O número diário de ativos novos foi atingido | Espere até 00:00 UTC e respeite Retry-After |
asset_storage_full | 503 | O armazenamento de toda a plataforma está cheio | Tente de novo mais tarde |
asset_permission_denied | 403 | O seu papel na equipe não permite esta alteração | Peça a um proprietário ou administrador da equipe, ou use uma chave cujo criador tenha um papel com essa permissão |
asset_workspace_forbidden | 403 | Esta chave não alcança essa biblioteca, por exemplo porque o membro que criou a chave de equipe saiu da equipe | Crie uma chave nova no workspace de que você precisa |
asset_entity_name_taken | 409 | A biblioteca já tem um personagem com esse nome (sem diferenciar maiúsculas e minúsculas). Os personagens são nomeados na página Assets do app web, então a API somente leitura ainda não o retorna | Escolha outro nome |
Disponibilidade dos modelos
code | HTTP | Significado | Tentar novamente? |
|---|---|---|---|
50301 | 503 | O modelo está indisponível no momento | Sim. Tente mais tarde ou escolha outro modelo |
50302 | 503 | Uma solicitação de texto, com ou sem streaming, falhou no modelo antes de entregar uma resposta; a reserva foi devolvida | Sim. Reenvie com outro Idempotency-Key |
40004 | 400 | O modelo está funcionando, mas não com essas configurações | Não. Altere a configuração indicada em msg |
50301 significa que o modelo não conseguiu aceitar a tarefa no momento do envio: ele não está listado, não tem preço ativo ou não dispõe de capacidade de geração naquele momento. Problemas temporários de capacidade podem ser resolvidos com tentativas limitadas. Um modelo indisponível ou sem preço ativo não é corrigido por solicitações repetidas. Atualize o catálogo e obtenha confirmação do usuário antes de trocar de modelo.
40004 e 50301 são intencionalmente diferentes. 50301 significa que o modelo não pode aceitar nenhuma tarefa agora; esperar pode ajudar. 40004 significa que funciona, mas não atende esta combinação de configurações, e msg indica o ajuste entre parênteses, como This model cannot serve this parameter combination right now (…). Esperar não ajuda; alterar um valor, sim. Nenhum dos dois cria tarefa nem reserva dinheiro.
Falhas de geração após a aceitação aparecem como state: failed
Uma falha de geração após createTask retornar um ID aparece em recordInfo como state: "failed", com errorCode / errorMessage; normalmente toda a reserva é liberada, exceto em recusas de conteúdo expressamente informadas como cobráveis na página do modelo. A mesma situação de 40004, identificada só após a aceitação, aparece como errorCode: "unsupported_combination". Não adicione ao código tratamentos de códigos de negócio síncronos ausentes desta página.
Códigos de falha de tarefas
Uma falha após a aceitação aparece em errorCode de recordInfo. O conjunto é fechado: diagnósticos internos nunca aparecem aqui; trate qualquer valor fora da lista como upstream_failed.
errorCode | Significado | Tentar novamente? |
|---|---|---|
invalid_request | Os parâmetros não foram aceitos | Não. Corrija e envie novamente |
unsupported_combination | Esta combinação não é aceita no momento | Não. Escolha outras configurações |
content_rejected | O modelo selecionado recusou o conteúdo. A própria SpicyAPI não analisa as solicitações; veja Responsabilidade pelo conteúdo e pelo uso | Não. Mude o prompt ou escolha outro modelo |
rate_limited | O serviço de geração estava ocupado | Sim. Aguarde e tente novamente |
upstream_unavailable | A geração está temporariamente indisponível | Sim. Tente em breve |
invalid_asset | Uma referência não está mais disponível | Não pelo endpoint de nova tentativa. retry reutiliza a entrada original; envie o arquivo novamente e crie outra tarefa com o novo URI |
generation_failed | A geração começou, mas não produziu nada | Talvez. As mesmas entradas normalmente falham da mesma forma |
timeout | A tarefa ultrapassou o prazo sem terminar | Talvez. Tente duração menor ou resolução mais baixa |
upstream_failed | Categoria geral para os demais casos | Sim. Aguarde e tente novamente |
Tarefas com falha ou expiradas normalmente liberam toda a reserva. Algumas recusas de conteúdo são cobradas pelo orçamento aceito somente quando a página do modelo informa expressamente essa exceção. Confira settled e cost para saber a cobrança final. errorMessage é para pessoas: explica o motivo em texto, pode citar em inglês o motivo do próprio modelo, conforme acima, e sua redação muda; baseie a lógica somente em errorCode. “Tentar novamente” aqui significa enviar outra tarefa, cobrada de novo se for bem-sucedida.
Quais erros custam dinheiro
Estado da tarefa e estado da conexão são informações diferentes.
Criações expressamente recusadas, tarefas expiradas e registros históricos de cancelamento não geram cobrança de geração. Tarefas com falha normalmente são gratuitas, exceto em recusas de conteúdo expressamente informadas como cobráveis na página do modelo. Um tempo limite ou uma desconexão do cliente não é falha da tarefa. Tarefas aceitas não podem ser canceladas: recupere a tarefa original e confira seu estado final e liquidação. Um stream de texto desconectado pode ser cobrado quando uso válido já foi registrado.
| Situação | Há cobrança? |
|---|---|
A API recusa expressamente createTask sem criar tarefa, como em 40201, 40202, 40004 ou 50301 | Não. A criação e a reserva compartilham uma transação; erro de gateway ou resposta ausente não comprova recusa |
| O envio excede o tempo limite, uma aba fecha ou a conexão cai | Ainda não se sabe. Recupere a aceitação com a chave de idempotência original; não trate como nova tentativa gratuita |
createTask retorna 202, e depois a tarefa fica em failed / expired | Normalmente não. Alguns resultados failed / content_rejected são cobrados pelo orçamento aceito quando a página do modelo informa expressamente isso. Leia settled e cost |
Uma tarefa histórica está em canceled | Não. É um estado de compatibilidade, não uma ação disponível hoje |
createTask retorna 202, e a tarefa fica em succeeded | Sim, liquidada pelo uso efetivo e limitada à reserva aceita. Recursos não usados são liberados, sem cobrança posterior acima da reserva |
Qualquer erro de recordInfo, chat/credit ou common/* | Não. Esses endpoints nunca são cobrados |
Limite de solicitações (429) ou deduplicação por chave de idempotência | Não. A primeira solicitação nunca foi aceita; a segunda retorna a tarefa original, cobrada uma vez |
A liquidação ou liberação é concluída automaticamente, inclusive após uma interrupção de processo. Falhas comuns liberam toda a reserva; algumas recusas de conteúdo expressamente informadas na página do modelo são cobradas pelo orçamento aceito. Confira a liquidação da tarefa e o saldo para verificar o resultado; veja Faturamento.
Quando vale repetir um 409
| Caso | Tentar novamente? |
|---|---|
Conflito raro de createTask simultâneos com a mesma chave e o mesmo corpo | Sim. Aguarde algumas centenas de milissegundos e repita com a mesma chave. Veja Idempotência |
| A mesma chave já foi usada com outro corpo ou outra chave de API | Não. Pare e corrija a vinculação da chave; novas tentativas não alteram o conflito |
Imagens inline ou confirmação de upload ainda em processamento, possivelmente com Retry-After | Sim. Espere conforme Retry-After, ou alguns segundos, e reenvie com o mesmo Idempotency-Key |
| Preço ou configuração da conta mudou durante a solicitação | Sim. Obtenha outro orçamento se você usa orçamentos e reenvie |
| Arquivo gerado ainda sendo copiado | Sim. Aguarde alguns segundos e solicite novamente o link de download |
jobs/retry em uma tarefa que não terminou ou ainda não concluiu a liquidação | Sim, depois. Aguarde a tarefa original chegar a um estado final com settled em true e repita |
jobs/retry em uma tarefa bem-sucedida ou cuja entrada já foi removida pela retenção | Não. Crie outra tarefa com createTask |
| URL de upload ou arquivo enviado expirou | Não. Envie o arquivo novamente |
Implementar novas tentativas
Não repita sem verificar
400, 401, 40004, 40201 e erros semelhantes de entrada ou autorização retornam a mesma resposta, por mais que você tente. Toda tentativa marcada como “Não” acima é desperdício e consome seu próprio limite de solicitações.
Use espera exponencial com variação aleatória para que um lote de falhas não volte todo no mesmo instante:
// 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
}Ao repetir createTask, sempre envie o mesmo Idempotency-Key; caso contrário, “funcionou, mas perdemos a resposta” vira geração e cobrança duplicadas.
Diagnóstico
Quando um erro não fizer sentido, siga esta lista:
request_id: informe-o para que possamos localizar a solicitação exata.code: consulte as tabelas acima.- Logs no console: cole o ID da tarefa ou
request_idna busca da página Logs para abrir a tarefa: status, custo, latência, chave de envio, código de erro e motivo. Parâmetros e resultados só aparecem enquanto ainda estão retidos e, em uma equipe, somente para papéis com permissão de leitura de conteúdo.
O msg de 500 é sempre uma mensagem genérica de serviço temporariamente indisponível, sem detalhes internos: estrutura interna, nomes de componentes e stack traces nunca aparecem na resposta. Essas informações só podem ser investigadas por request_id.
Para falar conosco, abra uma conversa em Suporte no console ou envie e-mail para support@spicyapi.ai. Inclua request_id ou ID da tarefa, horário em UTC e code. Nunca envie uma chave de API.
OpenAPI e índice de endpoints
Contrato OpenAPI 3.1 para download, todos os endpoints públicos com seus guias, cabeçalhos compartilhados e endereço de produção.
Limites de solicitações
Como funcionam os limites de leitura e escrita, quais chamadas contam em cada um, outros limites possíveis e a diferença em relação à concorrência.

