Tratamento de erros
Entenda as respostas de erro da API Piloterr e aprenda a lidar com cada caso corretamente.
Cada pedido à API Piloterr retorna um código de estado HTTP padrão. Este guia explica o que cada código significa, quando os créditos são consumidos e como lidar com falhas na sua integração.
Formato de resposta
Respostas bem-sucedidas retornam um objeto JSON com os dados do endpoint. Respostas de erro seguem uma estrutura consistente:
{
"error": "Human-readable description of what went wrong"
}Sempre verifique o código de estado HTTP antes de ler o corpo.
Códigos de estado
200 Sucesso
Cobrado. O pedido foi concluído com sucesso. Os créditos são deduzidos do seu saldo.
const res = await fetch(url, { headers: { "x-api-key": API_KEY } })
if (res.status === 200) {
const data = await res.json()
// process data
}201 Trabalho criado
Cobrado. Um trabalho assíncrono foi criado e aceito. Seu saldo é verificado antes de o trabalho ser enfileirado, então um trabalho nunca começa sem os créditos necessários para pagá-lo.
202 Aceito (async)
Não cobrado. O pedido foi aceita e enfileirada para processamento. Use o ID do trabalho retornado para consultar o resultado — consultar o estado do trabalho é gratuito.
400 Pedido incorreto
Não cobrado. O seu pedido contém parâmetros inválidos ou ausentes.
Causas comuns:
- Um parâmetro de consulta obrigatório está ausente
- Um valor de parâmetro tem o tipo ou formato incorreto
- O corpo do pedido está malformado
O que fazer: Releia a documentação do endpoint e verifique cada parâmetro obrigatório. Registe a URL completa do pedido para detectar erros de digitação.
if (res.status === 400) {
const { error } = await res.json()
console.error("Bad request:", error)
// do not retry, fix the parameters first
}401 Não autorizado
Não cobrado. Retornado para problemas de autenticação e limitação de taxa. Verifique a mensagem de erro para distingui-los.
O seu cabeçalho x-api-key está ausente ou contém um valor não reconhecido.
Correção: Copie a sua chave do seu painel → Chaves API e certifique-se de que o cabeçalho x-api-key está presente em cada pedido.
A chave existe mas foi desativada.
Correção: Vá ao seu painel → Chaves API e ative a chave, ou gere uma nova.
A chave ultrapassou a sua data de expiração.
Correção: Gere uma nova chave ou estenda a expiração no seu painel.
Enviou muitos pedidos num curto período. Os limites do plano têm o aspeto de Rate limit exceeded: You've exceeded the … rate limit on your subscription. As cotas por chave têm o aspeto de Rate limit exceeded for the API key: quota daily (ou total / weekly / monthly).
Correção: Aguarde e tente novamente após um intervalo. Se isso ocorrer com frequência, faça upgrade do plano ou aumente as cotas da chave. Esses limites retornam 401, não 429.
if (res.status === 401) {
const { error } = await res.json()
if (error.toLowerCase().includes("rate limit")) {
await new Promise(r => setTimeout(r, 2000))
// retry
}
}402 Payment required
Não cobrado. O pedido não foi executado. A string error indica o motivo:
Payment required— a cota API e os créditos pay-as-you-go não cobrem a chamadaYou have open invoices: …— uma fatura em aberto bloqueia a contaInsufficient credits: X required, Y available— um endpoint por linhas retornaria mais linhas do que pode pagar
O que fazer:
- Compre um pack pontual ou faça upgrade do plano no seu painel, ou quite as faturas em aberto em Definições → Faturas.
- Ou ative a Recarga automática para evitar que o saldo se esgote novamente.
A recarga automática só é ativada quando o seu saldo desce abaixo do limite configurado. Ela nunca é executada num horário fixo ou programado. Um período de espera de 72 horas integrado também impede múltiplas cobranças em pouco tempo: uma vez que uma recarga é feita, ela não pode ser ativada novamente por 72 horas independentemente de como seu saldo se mova. Se uma cobrança falhar, a recarga automática é desativada automaticamente para proteger a sua conta.
Não tente novamente uma resposta 402 imediatamente. A chamada falhará novamente até adicionar créditos. Configure um alerta para que a sua equipa seja notificada quando isso acontecer.
if (res.status === 402) {
// alert your team or trigger an auto top-up flow
throw new Error("Insufficient credits. Top up at https://app.piloterr.com")
}403 Proibido
Não cobrado. O pedido foi recusado antes de ser executado. As causas habituais são um endpoint que não existe no seu plano, uma conta desativada ou um IP temporariamente bloqueado após várias falhas de autenticação.
O que fazer: Confira o caminho do endpoint na referência e depois confirme que a sua conta está ativa no painel. Contacte o suporte se acredita que é um erro.
404 Não encontrado
Pode ser cobrado (específico do endpoint). O recurso não foi encontrado. Verifique a documentação do endpoint para confirmar se esta resposta é cobrada.
if (res.status === 404) {
// handle "no result" gracefully, not as a fatal error
return null
}500 Erro interno do servidor
Não cobrado. Ocorreu um erro inesperado do nosso lado.
O que fazer: Tente novamente com backoff exponencial. Se o problema persistir, contacte o suporte.
async function fetchWithRetry(url: string, options: RequestInit, maxRetries = 3) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const res = await fetch(url, options)
if (res.status !== 500 || attempt === maxRetries) return res
const delay = 500 * 2 ** attempt
console.warn(`500 error, retrying in ${delay}ms (attempt ${attempt + 1}/${maxRetries})`)
await new Promise(r => setTimeout(r, delay))
}
}Tratador de erros completo
Uma única função que cobre cada código de status:
interface ApiResult<T> {
data: T | null
error: string | null
status: number
billed: boolean
}
async function apiCall<T>(url: string, apiKey: string): Promise<ApiResult<T>> {
const res = await fetch(url, {
headers: { "x-api-key": apiKey },
})
// 200 and 201 are always billed; 404 billing is endpoint-specific
const billed = res.status === 200 || res.status === 201
if (res.status === 200) {
return { data: await res.json() as T, error: null, status: 200, billed }
}
const body = await res.json().catch(() => ({ error: "Unknown error" }))
const error = body?.error ?? "Unknown error"
switch (res.status) {
case 400:
console.error("[400] Bad request, fix your parameters:", error)
break
case 401:
if (error.toLowerCase().includes("rate limit")) {
console.warn("[401] Rate limit, back off and retry")
} else {
console.error("[401] Auth error, check your API key:", error)
}
break
case 402:
console.error("[402] No credits remaining. Top up at https://app.piloterr.com")
break
case 403:
console.error("[403] Forbidden, check your key permissions")
break
case 404:
console.warn("[404] Not found, no result for this request")
break
case 500:
console.error("[500] Server error, retry with backoff")
break
default:
console.error(`[${res.status}] Unexpected status:`, error)
}
return { data: null, error, status: res.status, billed }
}Estratégia de nova tentativa
| Status | Tentar novamente? | Estratégia |
|---|---|---|
400 | Não | Corrigir o pedido primeiro |
401 (limite de taxa) | Sim | Aguardar 2–5 s, depois tentar novamente |
401 (auth) | Não | Corrigir a chave de API |
402 | Não | Adicionar créditos ou quitar faturas primeiro |
403 | Não | Verificar permissões |
404 | Não | Tratar como resultado vazio |
500 | Sim | Backoff exponencial (máx. 3 tentativas) |
Resumo de cobrança
| Status | Cobrado |
|---|---|
200 | Sim |
201 | Sim |
404 | Específico do endpoint (consulte a documentação) |
| Todos os outros códigos | Não |
Consulte a página Créditos para um detalhe completo de custos por endpoint. Para conselhos mais amplos de integração, consulte Melhores práticas.