Códigos de erro
Erros das chamadas a /v1/* (proxy Tokia → modelos IA) seguem o formato OpenAI-compatible:
json
{
"error": {
"type": "rate_limit_exceeded",
"message": "Muitas requisições simultâneas. Aguarde alguns segundos e tente novamente.",
"code": "rate_limit_exceeded"
}
}Erros das chamadas REST (/api-keys, /topups, /payment-methods, /me/profile etc.) usam { "error": "<código>", "details"?: string }. Códigos HTTP seguem convenção REST.
Erros do proxy /v1/*
Tokia normaliza todos os erros dos modelos IA upstream em 6 categorias. A mensagem é em pt-BR e sempre acionável — nunca vaza nome do provedor ou detalhe interno.
| HTTP | type / code | Quando acontece | O que fazer |
|---|---|---|---|
| 400 | invalid_request | Parâmetro inválido (model inexistente, max_tokens absurdo, messages malformado). | Verificar payload contra /docs/api/chat. |
| 401 | authentication_failed | API key Tokia inválida, revogada, expirada, ou sem acesso ao modelo solicitado. | Recriar key em /dashboard/keys incluindo o modelo desejado. |
| 404 | model_not_found | ID do modelo não existe no catálogo Tokia. | Ver lista atual em /docs/models. |
| 429 | rate_limit_exceeded | Throttling Tokia (default 100 req/min/IP) ou limite do modelo. | Backoff exponencial — esperar 1-2s e retentar. Lê header retry-after. |
| 429 | api_key_rate_limited | Sprint 177 — limite por API key (default 120 req/min) atingido. | Crie 2ª API key em /dashboard/keys pra paralelizar carga, ou backoff lendo x-ratelimit-reset. |
| 403 | ip_blocked_by_allowlist | Sprint 111 — IP do cliente não está na allowlist desta key. | Adicionar IP em /dashboard/keys → editar key → IP allowlist. |
| 502 | upstream_error | Falha temporária na infraestrutura Tokia/upstream. | Retentar em alguns segundos. Se persistir, contatar suporte. |
| 503 | service_unavailable | Modelo temporariamente indisponível (manutenção, recarga em curso). | Retentar em alguns minutos. Tokia já foi notificada automaticamente. |
Erros REST (dashboard / billing / keys)
400 Bad Request
| Código | Significado |
|---|---|
cpf_required | Profile sem CPF/CNPJ. Cliente precisa preencher em PUT /me/profile antes de fazer top-up ou cadastrar cartão. |
invalid_cpf_cnpj_format | Formato inválido (não tem 11 ou 14 dígitos). |
invalid_cpf_cnpj_checksum | Dígitos verificadores não batem. |
amount must be number between 10 and 5000 | Valor de top-up fora do intervalo. |
name must be 3-50 chars | Nome de API key inválido. |
no_valid_models | Lista model_ids[] passada não tem nenhum ID válido do catálogo. |
card_rejected | Asaas rejeitou o cartão (recusado, expirado, dados incorretos). |
missing_card_or_holder_info | POST /payment-methods sem campos obrigatórios. |
401 Unauthorized
| Código | Significado |
|---|---|
| (sem corpo) | Token Bearer ausente ou inválido. Verifique header Authorization. |
invalid_token | Webhook Asaas com token errado (não afeta clientes). |
invalid_signature | Webhook Logto com HMAC inválido (não afeta clientes). |
403 Forbidden
| Código | Significado |
|---|---|
forbidden | Endpoint admin sem permissão. Cliente normal vê 403; admins precisam estar na allowlist. |
key_model_access_denied | API key não tem o modelo solicitado em sua lista permitida. Crie nova key incluindo o modelo. |
404 Not Found
| Código | Significado |
|---|---|
key_not_found | DELETE /api-keys/:id com id que não pertence ao user. |
payment_method_not_found | DELETE /payment-methods/:id com id inválido. |
profile_not_found | GET /me/profile antes do webhook Logto criar o profile. |
500 Internal Server Error
Erro inesperado Tokia. Reporte pra contato@usetokia.com com timestamp + request_id (do header x-request-id da response).
Headers úteis
Toda resposta de /v1/* retorna headers extras pra debug e controle de fluxo:
| Header | Quando aparece | Pra que serve |
|---|---|---|
x-tokia-request-id | Toda resposta | Sprint 164 — UUID único da chamada. Inclua em suporte. Cliente pode enviar o próprio header pra correlação ponta-a-ponta. |
x-ratelimit-limit | Toda resposta (Sprint 177) | Quantos requests por minuto a key pode fazer. |
x-ratelimit-remaining | Toda resposta (Sprint 177) | Quantos requests ainda cabem na janela atual. |
x-ratelimit-reset | Toda resposta (Sprint 177) | Unix timestamp (segundos) quando o contador zera. |
retry-after | Só em 429 | Segundos até poder retentar. |
Padrão de retry recomendado
ts
// SDK Node oficial já faz isso (sdks/node v0.3+).
// Implementação manual em qualquer cliente HTTP:
async function retryableFetch(url: string, opts: RequestInit, max = 5) {
for (let attempt = 0; attempt < max; attempt++) {
const r = await fetch(url, opts);
// Retentar em 429 e 5xx
if (r.status === 429 || r.status >= 500) {
const retryAfter = Number(r.headers.get("retry-after")) || 1;
const wait = retryAfter * 1000 * Math.pow(2, attempt);
await new Promise((ok) => setTimeout(ok, Math.min(wait, 30_000)));
continue;
}
return r;
}
throw new Error("Tokia: max retries exceeded");
}