alltools.one
API
2025-06-30
9 min
alltools.one Team
JSONAPIRESTDesign PatternsBackend

Padrões de Design de APIs JSON: Construir Melhores APIs REST

Uma API bem concebida é um prazer de utilizar. Uma mal concebida cria erros, frustração e dívida técnica. Este guia abrange padrões testados em combate para conceber APIs REST JSON que são consistentes, descobríveis e fáceis de manter.

Nomenclatura de Recursos

Os recursos são substantivos, não verbos. Utilize substantivos no plural para coleções e recursos individuais via ID:

GET    /api/users          # List users
POST   /api/users          # Create a user
GET    /api/users/123      # Get user 123
PUT    /api/users/123      # Update user 123
DELETE /api/users/123      # Delete user 123

Convenções de nomenclatura:

  • Utilize minúsculas com hífenes: /api/blog-posts (não blogPosts ou blog_posts)
  • Aninhe recursos relacionados: /api/users/123/orders
  • Limite o aninhamento a 2 níveis: /api/users/123/orders/456 (não mais profundo)
  • Evite verbos nos URLs: /api/users/123/activate é aceitável para ações que não mapeiam para CRUD

Envelope de Resposta

Envolva as respostas num envelope consistente:

{
  "data": {
    "id": "123",
    "type": "user",
    "attributes": {
      "name": "Alice",
      "email": "alice@example.com",
      "createdAt": "2024-01-15T10:30:00Z"
    }
  },
  "meta": {
    "requestId": "req_abc123"
  }
}

Para coleções:

{
  "data": [
    { "id": "123", "name": "Alice" },
    { "id": "456", "name": "Bob" }
  ],
  "meta": {
    "total": 142,
    "page": 1,
    "perPage": 20
  }
}

Valide as respostas da sua API com o nosso Validador de JSON para garantir que correspondem ao seu schema.

Paginação

Três abordagens comuns:

Baseada em Offset (Mais Simples)

GET /api/users?page=2&per_page=20
{
  "data": [...],
  "meta": {
    "page": 2,
    "perPage": 20,
    "total": 142,
    "totalPages": 8
  }
}

Vantagem: Simples, suporta saltar para qualquer página. Desvantagem: Resultados inconsistentes com inserções/eliminações concorrentes.

Baseada em Cursor (Mais Fiável)

GET /api/users?cursor=eyJpZCI6MTIzfQ&limit=20
{
  "data": [...],
  "meta": {
    "hasNext": true,
    "nextCursor": "eyJpZCI6MTQzfQ"
  }
}

Vantagem: Consistente com alterações concorrentes, performante em grandes conjuntos de dados. Desvantagem: Não permite saltar para páginas arbitrárias.

Baseada em Keyset (Mais Performante)

GET /api/users?after_id=123&limit=20

Utiliza o ID do último item (ou outro campo ordenado) para obter a página seguinte. Semelhante à baseada em cursor mas com parâmetros transparentes.

Recomendação: Utilize baseada em cursor para feeds em tempo real e grandes conjuntos de dados. Utilize baseada em offset para painéis de administração onde saltar entre páginas é importante.

Filtragem e Ordenação

Filtragem

GET /api/users?status=active&role=admin
GET /api/users?created_after=2024-01-01
GET /api/users?search=alice

Para filtros complexos, considere um parâmetro de consulta dedicado:

GET /api/users?filter[status]=active&filter[role]=admin

Ordenação

GET /api/users?sort=name          # Ascending
GET /api/users?sort=-created_at   # Descending (prefix with -)
GET /api/users?sort=-created_at,name  # Multiple fields

Tratamento de Erros

Respostas de erro consistentes são críticas para a usabilidade da API:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "details": [
      {
        "field": "email",
        "message": "Must be a valid email address",
        "value": "not-an-email"
      },
      {
        "field": "age",
        "message": "Must be between 0 and 150",
        "value": -5
      }
    ]
  },
  "meta": {
    "requestId": "req_abc123"
  }
}

Códigos de estado HTTP a utilizar:

CódigoSignificadoQuando
200OKGET, PUT com sucesso
201CriadoPOST com sucesso
204Sem ConteúdoDELETE com sucesso
400Pedido InválidoErros de validação
401Não AutorizadoAutenticação em falta/inválida
403ProibidoAutenticação válida, permissões insuficientes
404Não EncontradoO recurso não existe
409ConflitoRecurso duplicado, conflito de versão
422Não ProcessávelSemanticamente inválido
429Demasiados PedidosLimite de taxa excedido
500Erro InternoErro inesperado do servidor

Versionamento

Três abordagens:

Caminho do URL (Recomendado)

GET /api/v1/users
GET /api/v2/users

Vantagem: Explícito, fácil de encaminhar, fácil de testar.

Baseado em Cabeçalho

GET /api/users
Accept: application/vnd.myapi.v2+json

Vantagem: URLs limpos. Desvantagem: Mais difícil de testar, menos descobrível.

Parâmetro de Consulta

GET /api/users?version=2

Vantagem: Fácil de testar. Desvantagem: Semântica de parâmetro opcional.

Recomendação: O versionamento por caminho de URL é a escolha mais prática. É explícito, cacheável e funciona com todas as ferramentas HTTP.

Gestão de Datas e Horas

Utilize sempre ISO 8601 em UTC:

{
  "createdAt": "2024-01-15T10:30:00Z",
  "updatedAt": "2024-01-15T14:22:33Z",
  "expiresAt": "2024-12-31T23:59:59Z"
}

Nunca utilize timestamps Unix nas respostas da API — são ambíguos (segundos vs milissegundos) e não são legíveis por humanos. Para mais informações sobre o tratamento de timestamps, consulte o nosso guia de Unix Timestamps.

Limitação de Taxa

Comunique os limites de taxa nos cabeçalhos de resposta:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 67
X-RateLimit-Reset: 1705312800
Retry-After: 30

Devolva 429 Too Many Requests quando o limite é excedido, com uma mensagem de erro clara e o cabeçalho Retry-After.

HATEOAS (Opcional mas Poderoso)

Inclua ligações para recursos e ações relacionados:

{
  "data": {
    "id": "123",
    "name": "Alice",
    "links": {
      "self": "/api/users/123",
      "orders": "/api/users/123/orders",
      "avatar": "/api/users/123/avatar"
    }
  }
}

Isto torna a sua API autodocumentada e reduz a construção de URLs do lado do cliente.

FAQ

Devo utilizar a especificação JSON:API ou conceber o meu próprio formato?

A especificação JSON:API (jsonapi.org) fornece um padrão abrangente, mas pode ser verbosa para APIs simples. Para a maioria dos projetos, conceber um formato personalizado mais simples seguindo os padrões deste guia é mais prático. Utilize JSON:API se precisar de bibliotecas de cliente automáticas e de um padrão rigoroso.

Como devo lidar com atualizações parciais (PATCH vs PUT)?

Utilize PUT para substituição completa do recurso (o cliente envia todos os campos). Utilize PATCH para atualizações parciais (o cliente envia apenas os campos alterados). PATCH com JSON Merge Patch (RFC 7396) é a abordagem mais simples: envie um objeto JSON apenas com os campos a atualizar, e null para remover um campo.

Recursos Relacionados

Published on 2025-06-30
JSON API Design Patterns: Building Better REST APIs | alltools.one