Erros Comuns em APIs REST que Você Deve Evitar para Melhorar Desempenho e Segurança

Erros Comuns em APIs REST que Você Deve Evitar para Melhorar Desempenho e Segurança





Erros comuns em API REST que você deve evitar



1. Tratamento de erros: mensagens inconsistentes

Eu observo que muitos times não padronizam o payload de erro, o que dificulta consumo, logs e rastreamento. Adoto um formato único de erro para toda a API desde o começo do projeto.

  • Utilize um formato de erro consistente em todos os pontos de falha.
  • Inclua código de erro, mensagem humana clara e detalhes opcionais para debugging controlado.
  • Documente o schema de erro na API docs e mantenha-o estável entre versões.

Exemplo de payload de erro recomendado:

{
  "error": {
    "code": "USER_NOT_FOUND",
    "message": "Usuário com o identificador informado não foi encontrado.",
    "details": {
      "field": "userId",
      "value": "12345"
    }
  }
}

Dicas: mantenha mensagens em idioma local do consumidor e evite expor dados sensíveis nos detalhes.

2. Uso inadequado de códigos de status

Um erro comum é retornar 200 OK para falhas, ou usar 500 para cenários que são previsíveis (validação, por exemplo). Eu sigo princípios explícitos de HTTP para comunicação clara.

  • 200 OK: apenas quando a operação teve sucesso e há o corpo retornado.
  • 201 Created: quando um recurso é criado; inclua Location se aplicável.
  • 204 No Content: para operações sem corpo de resposta (ex: delete com sucesso).
  • 4xx para erros do cliente, 5xx para erros do servidor; não use 200 com payload de erro.

Exemplos de uso correto:

  • GET /users/999 -> 404 Not Found
  • POST /users -> 201 Created, Location: /api/v1/users/{id}
  • DELETE /users/123 -> 204 No Content

3. Falta de validação de entrada e mensagens pouco claras

Sem validação adequada, APIs aceitam dados inválidos, provocando falhas mais adiante. Eu valido na entrada (DTO/binding) e retorno mensagens claras e acionáveis.

  • Valide tipos, formatos, limites (tamanho, range, enums).
  • Envie mensagens de erro com código e descrição legível.
  • Não exponha dados sensíveis nos detalhes do erro.

Exemplo de validação simples (JavaScript/Node.js com Express):

// Exemplo de validação simples em Node.js/Express
if (!payload.email || !/^[^@]+@[^@]+\.[^@]+$/.test(payload.email)) {
  res.status(422).json({
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "O e-mail fornecido é inválido.",
      "details": { "field": "email", "value": payload.email }
    }
  });
}

Sugestão prática: padronize mensagens de erro por categoria (VALIDATION_ERROR, AUTH_ERROR, RESOURCE_NOT_FOUND, etc.).

4. Ausência de versionamento e contrato frágil

Sem versionamento, mudanças inesperadas quebram clientes. Eu sigo um contrato estável com deprecação responsável.

  • Versionamento visível na URL: /api/v1/… e /api/v2/…
  • Comunique deprecação via cabeçalhos, notificações na documentação e no nosso changelog.
  • Manter contratos estáveis com OpenAPI/Swagger, mocks e testes regressivos.

Exemplos de rotas com versionamento:

  • GET /api/v1/users
  • GET /api/v2/users?active=true

Bloco de código recomendado: esquema de erro padronizado

// Exemplo consolidado de erro com metadados
{
  "error": {
    "code": "STRING_UNIQUE",
    "message": "Este recurso já existe.",
    "details": {
      "field": "slug",
      "value": "exemplo"
    }
  },
  "meta": {
    "timestamp": "2026-04-06T12:34:56Z",
    "traceId": "abc123"
  }
}

Mantemos um payload de erro homogêneo para facilitar logs, triagem e documentação.