Skip to main content
Todo erro da API da AWSales segue uma estrutura JSON consistente, facilitando a construção de tratamento de erros confiável na sua integração.

Formato da response de erro

Todos os erros retornam um body JSON com o seguinte formato:
{
  "statusCode": 400,
  "message": "Bad Request Error",
  "errors": [
    {
      "message": "required",
      "path": "email"
    }
  ]
}
CampoTipoDescrição
statusCodeintegerO código de status HTTP
messagestringUma mensagem de erro legível ou um código de erro programático (ex: auth.invalid_credentials)
errorsarrayDetalhes de validação. Presente em responses 400 com erros por campo.
resourceIdstringO ID do recurso não encontrado. Presente em algumas responses 404.
O campo message também funciona como código de erro para tratamento programático. Códigos programáticos seguem o padrão {domínio}.{erro} — por exemplo, auth.invalid_credentials, organization.not_found, subscription.active_subscription_exists.

Códigos de status HTTP

StatusNomeQuando ocorre
400Bad RequestFalha de validação, campos obrigatórios ausentes ou input malformado
401UnauthorizedAccess token ausente, expirado ou inválido
403ForbiddenPermissões insuficientes ou ação adicional necessária (veja sub-códigos 403)
404Not FoundO recurso solicitado não existe
409ConflictRecurso duplicado ou conflito de estado (ex: assinatura já existe)
422Unprocessable EntityViolação de regra de negócio (ex: plano não elegível para downgrade)
429Too Many RequestsLimite de requisição excedido (veja Limites de Requisição)
500Internal Server ErrorErro inesperado no servidor

Padrões de tratamento de erros

async function apiRequest(url, options = {}) {
  const response = await fetch(url, {
    ...options,
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${accessToken}`,
      ...options.headers,
    },
  });

  if (response.ok) {
    // 204 No Content returns no body
    if (response.status === 204) return null;
    return response.json();
  }

  const error = await response.json();

  switch (response.status) {
    case 400:
      // Validation error -- check error.errors for field details
      console.error("Validation failed:", error.errors);
      throw new ValidationError(error.message, error.errors);

    case 401:
      // Token expired -- attempt refresh
      const newTokens = await refreshAccessToken();
      if (newTokens) {
        return apiRequest(url, options); // Retry with new token
      }
      throw new AuthError("Session expired. Please sign in again.");

    case 403:
      // Check for special sub-codes
      return handle403(error);

    case 404:
      throw new NotFoundError(error.message, error.resourceId);

    case 409:
      throw new ConflictError(error.message);

    case 429:
      // Rate limited -- retry after delay
      const retryAfter = response.headers.get("Retry-After");
      await sleep(parseInt(retryAfter || "1") * 1000);
      return apiRequest(url, options);

    default:
      throw new ApiError(error.message, response.status);
  }
}

Sub-códigos 403

O status 403 é usado tanto para erros de permissão quanto para sinais de controle de fluxo. Quando você receber um 403, inspecione o campo message para determinar a ação necessária:
CódigoSignificadoAção necessária
auth.organization_selection_requiredUsuário pertence a múltiplas organizaçõesChame Trocar Organização com o organizationId desejado
auth.otp_verification_requiredEmail ainda não verificadoComplete a verificação de OTP
auth.method_not_allowedConta usa um método de autenticação diferenteUse o fluxo de autenticação correto (ex: OAuth em vez de senha)
auth.invitation_requiredUsuário precisa ser convidado antes de acessar a plataformaSolicite um convite a um administrador da organização
forbiddenPermissões RBAC insuficientesVerifique se o usuário tem a permissão resource:action necessária
function handle403(error) {
  switch (error.message) {
    case "auth.organization_selection_required":
      // Prompt user to select an organization
      return redirectToOrgSelection();

    case "auth.otp_verification_required":
      // Redirect to email verification screen
      return redirectToVerification();

    case "auth.method_not_allowed":
      // User signed up with OAuth but is trying email/password
      throw new Error("Please sign in using your Google or Microsoft account.");

    case "auth.invitation_required":
      throw new Error("You need an invitation to access this organization.");

    default:
      // Generic permission error
      throw new ForbiddenError("You don't have permission to perform this action.");
  }
}

Erros de validação (400)

Erros de validação incluem um array errors com detalhes por campo:
{
  "statusCode": 400,
  "message": "Bad Request Error",
  "errors": [
    { "message": "required", "path": "email" },
    { "message": "required", "path": "password" }
  ]
}
Cada entrada no array errors contém:
CampoDescrição
messageA regra de validação que falhou (ex: required, invalid_format, too_long)
pathO campo que falhou na validação
Mapeie os valores de path para os campos do seu formulário para exibir mensagens de validação inline para os usuários.

Estratégias de recuperação de erros

1

Identificar a categoria do erro

Verifique o código de status HTTP primeiro, depois inspecione o campo message para códigos de erro específicos.
2

Tratar erros que podem ser retentados

401 (token expirado): renove o token e retente. 429 (rate limited): aguarde o período do Retry-After e retente. 500 (erro no servidor): retente com backoff exponencial (veja abaixo).
3

Tratar erros que não devem ser retentados

400 (validação): corrija o body da request e reenvie. 403 (proibido): verifique permissões ou siga as instruções do sub-código. 404 (não encontrado): verifique se o ID do recurso existe. 409 (conflito): resolva o estado de conflito antes de retentar.
4

Implementar backoff exponencial para retentativas

Para erros que podem ser retentados, aumente o intervalo entre tentativas para evitar sobrecarregar o servidor.
async function retryWithBackoff(fn, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      const isRetriable =
        error.status === 429 ||
        error.status === 500 ||
        error.status === 503;

      if (!isRetriable || attempt === maxRetries) {
        throw error;
      }

      const delay = Math.min(1000 * Math.pow(2, attempt), 10000);
      const jitter = Math.random() * 500;
      await new Promise((r) => setTimeout(r, delay + jitter));
    }
  }
}
5

Registrar erros para debugging

Sempre registre a response de erro completa incluindo statusCode, message e o array errors. Isso facilita muito o diagnóstico de problemas.
Não retente erros 400, 403, 404 ou 409 automaticamente. Eles indicam um problema com a request em si, não uma falha transitória. Retentá-los produzirá o mesmo resultado e consumirá seu orçamento de rate limit.

Idempotência

Algumas operações são seguras para retentar, enquanto outras não:
Seguro para retentarNão seguro para retentar
Todas as requests GETPOST para criar recursos (pode criar duplicatas)
Atualizações PUT / PATCHPOST /invoices/{id}/pay (pode cobrar duas vezes)
Requests DELETE (idempotentes por natureza)
Para operações não idempotentes, sempre verifique a response antes de retentar. Se a request original retornou 409 Conflict, o recurso provavelmente já foi criado com sucesso.

Cenários de erro comuns

CenárioStatusCódigoSolução
Header Authorization ausente401unauthorizedInclua Bearer {token} no header
Token expirado401unauthorizedRenove o token e retente
Usuário sem permissão403forbiddenAtribua a role/permissão necessária
Organização não encontrada404organization.not_foundVerifique o organizationId
Assinatura já existe409subscription.active_subscription_existsVerifique a assinatura existente antes de criar
Cupom expirado409coupon.not_availableUse um código de cupom válido
Máximo de métodos de pagamento atingido409payment_method.max_of_3_card_payment_methods_reachedExclua um método de pagamento existente primeiro

Próximos passos

Limites de Requisição

Entenda os limites de requisição e implemente estratégias de backoff.

Autenticação

Aprenda sobre gerenciamento de tokens e fluxos de renovação.