Piloterr

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 chamada
  • You have open invoices: … — uma fatura em aberto bloqueia a conta
  • Insufficient credits: X required, Y available — um endpoint por linhas retornaria mais linhas do que pode pagar

O que fazer:

  1. Compre um pack pontual ou faça upgrade do plano no seu painel, ou quite as faturas em aberto em Definições → Faturas.
  2. 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

StatusTentar novamente?Estratégia
400NãoCorrigir o pedido primeiro
401 (limite de taxa)SimAguardar 2–5 s, depois tentar novamente
401 (auth)NãoCorrigir a chave de API
402NãoAdicionar créditos ou quitar faturas primeiro
403NãoVerificar permissões
404NãoTratar como resultado vazio
500SimBackoff exponencial (máx. 3 tentativas)

Resumo de cobrança

StatusCobrado
200Sim
201Sim
404Específico do endpoint (consulte a documentação)
Todos os outros códigosNã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.

Nesta página