7 min leitura • Guide 349 of 877
Melhores Práticas de Design de API
Bom design de API facilita a vida dos consumidores e reduz carga de suporte. Má design de API leva a confusão, bugs e desenvolvedores frustrados. Este guia aborda abordagens práticas para design de API que resistem ao teste do tempo.
Princípios de API
| Princípio | Descrição | Benefício |
|---|---|---|
| Consistência | Mesmos padrões | Aprendibilidade |
| Previsibilidade | Comportamento esperado | Menos bugs |
| Evolutibilidade | Mude com segurança | Longevidade |
| Simplicidade | Fácil de usar | Adoção |
Design RESTful
API Orientada a Recursos
DESIGN DE API RESTFUL
═════════════════════
RECURSOS:
─────────────────────────────────────
Pense em substantivos, não verbos:
├── /users (não /getUsers)
├── /projects (não /createProject)
├── /tasks (não /deleteTask)
├── Recursos são coisas
└── Métodos HTTP são ações
OPERAÇÕES CRUD:
─────────────────────────────────────
Método HTTP │ Operação │ Exemplo
────────────┼──────────┼──────────────────
GET │ Ler │ GET /users
POST │ Criar │ POST /users
PUT │ Substituir│ PUT /users/123
PATCH │ Atualizar│ PATCH /users/123
DELETE │ Deletar │ DELETE /users/123
HIERARQUIA DE RECURSOS:
─────────────────────────────────────
Recursos aninhados:
├── GET /projects/123/tasks
├── POST /projects/123/tasks
├── GET /projects/123/tasks/456
├── Relacionamentos claros
└── Hierarquia lógica
ESTRUTURA DE URL:
─────────────────────────────────────
Nomes consistentes:
├── Substantivos plurais: /users, /tasks
├── Minúsculas: /user-profiles
├── Hífens para múltiplas palavras
├── Sem barras finais
├── Sem extensões de arquivo
└── Limpo, previsível
Request/Response
Formatação de Dados
DESIGN DE REQUEST/RESPONSE
═════════════════════════
JSON CONSISTENTE:
─────────────────────────────────────
Sempre mesma estrutura:
Resposta de sucesso:
{
"data": {
"id": 123,
"name": "John Doe",
"email": "john@example.com"
}
}
Resposta de lista:
{
"data": [
{ "id": 123, "name": "John" },
{ "id": 124, "name": "Jane" }
],
"meta": {
"total": 100,
"page": 1,
"perPage": 20
}
}
CONVENÇÕES DE NOMENCLATURA:
─────────────────────────────────────
Casing consistente:
├── camelCase para JSON: firstName
├── snake_case também comum: first_name
├── Escolha um, use em todo lugar
├── Combine com convenções da linguagem
└── Consistência importa mais
FILTRAGEM DE CAMPOS:
─────────────────────────────────────
Deixe clientes requisitarem campos:
├── GET /users?fields=id,name,email
├── Reduza over-fetching
├── Melhor performance
├── Abordagem GraphQL para REST
└── Opcional mas útil
Tratamento de Erros
Respostas de Erro Claras
TRATAMENTO DE ERROS
═══════════════════
FORMATO DE RESPOSTA DE ERRO:
─────────────────────────────────────
Estrutura consistente de erro:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A requisição foi inválida",
"details": [
{
"field": "email",
"message": "Formato de email inválido"
},
{
"field": "password",
"message": "Deve ter pelo menos 8 caracteres"
}
]
}
}
CÓDIGOS DE STATUS HTTP:
─────────────────────────────────────
Use corretamente:
├── 200: Sucesso
├── 201: Criado
├── 204: Sem conteúdo (sucesso de delete)
├── 400: Requisição ruim (erro do cliente)
├── 401: Não autorizado (não logado)
├── 403: Proibido (sem permissão)
├── 404: Não encontrado
├── 409: Conflito (duplicado, etc.)
├── 422: Não processável (validação)
├── 500: Erro do servidor
└── Códigos de status significativos
MENSAGENS DE ERRO:
─────────────────────────────────────
Boas mensagens de erro:
├── Mensagem legível por humanos
├── Código legível por máquina
├── Erros específicos de campo
├── Orientação acionável
├── Sem stack traces em prod
└── Útil, não críptico
✅ "Email já está registrado"
❌ "Erro: violação de chave duplicada"
Paginação
Lidando com Listas Grandes
PADRÕES DE PAGINAÇÃO
════════════════════
PAGINAÇÃO OFFSET:
─────────────────────────────────────
GET /users?page=2&perPage=20
Resposta:
{
"data": [...],
"meta": {
"total": 500,
"page": 2,
"perPage": 20,
"totalPages": 25
}
}
Prós: Simples, familiar
Contras: Performance em offsets grandes
PAGINAÇÃO CURSOR:
─────────────────────────────────────
GET /users?cursor=abc123&limit=20
Resposta:
{
"data": [...],
"cursors": {
"next": "xyz789",
"previous": "abc122"
}
}
Prós: Melhor performance
Contras: Não pode pular para página
MELHOR PRÁTICA:
─────────────────────────────────────
├── Tamanho de página padrão (20)
├── Tamanho máximo de página (100)
├── Incluir contagem total
├── Incluir links de navegação
├── Documentar abordagem de paginação
└── Consistente através de endpoints
Versionamento
Evolução de API
VERSIONAMENTO DE API
════════════════════
VERSIONAMENTO URL:
─────────────────────────────────────
/v1/users
/v2/users
Prós:
├── Explícito e claro
├── Fácil de entender
├── Bom para cache
├── Fácil de testar
└── Mais comum
VERSIONAMENTO HEADER:
─────────────────────────────────────
Accept: application/vnd.api+json;version=1
Prós:
├── URLs mais limpos
├── Mesmo recurso, representação diferente
Contras:
├── Menos visível
├── Mais difícil de testar
ESTRATÉGIA DE VERSIONAMENTO:
─────────────────────────────────────
├── Não versione muito cedo
├── Versione apenas para mudanças quebradoras
├── Mantenha versões antigas (6-12 meses)
├── Avisos de depreciação
├── Guias de migração
├── Datas claras de sunset
└── Planeje para mudança
EVITANDO MUDANÇAS QUEBRADORAS:
─────────────────────────────────────
Mudanças não quebradoras:
├── Adicione novos campos (opcionais)
├── Adicione novos endpoints
├── Adicione novos valores enum
├── Relaxe validação
└── Estenda, não mude
Mudanças quebradoras (evite):
├── Remova campos
├── Renomeie campos
├── Mude tipos de campo
├── Requeira novos campos
├── Mude comportamento
└── Requer nova versão
Documentação
Documentação de API
DOCUMENTAÇÃO DE API
═══════════════════
OPENAPI/SWAGGER:
─────────────────────────────────────
Documentação padrão:
├── Especificação legível por máquina
├── Docs auto-gerados
├── Funcionalidade try-it-out
├── Geração de cliente
├── Fonte única de verdade
└── Padrão da indústria
DOCUMENTAÇÃO INCLUI:
─────────────────────────────────────
Para cada endpoint:
├── URL e método
├── Descrição
├── Parâmetros de requisição
├── Schema de body de requisição
├── Schemas de resposta
├── Exemplos de requisição
├── Exemplos de resposta
├── Códigos de erro
├── Autenticação
└── Imagem completa
BONS EXEMPLOS:
─────────────────────────────────────
Mostre uso do mundo real:
## Criar Usuário
POST /v1/users
Requisição:
{
"name": "John Doe",
"email": "john@example.com",
"password": "securePassword123"
}
Resposta: 201 Created
{
"data": {
"id": "user_abc123",
"name": "John Doe",
"email": "john@example.com",
"createdAt": "2024-01-15T10:30:00Z"
}
}
MANTENHA DOCS ATUALIZADOS:
─────────────────────────────────────
├── Gere do código
├── Parte do processo de build
├── CI valida spec
├── Docs desatualizados são prejudiciais
└── Trate como first-class
Integração de Projeto
Tarefas de API no GitScrum
GITSCRUM PARA PROJETOS DE API
════════════════════════════
ESTRUTURA DE TAREFA DE API:
─────────────────────────────────────
Tarefa: "Criar endpoint de registro de usuário"
├── Critérios de aceitação:
│ ├── POST /v1/users
│ ├── Valida email/password
│ ├── Retorna 201 com dados do usuário
│ └── Erros seguem formato padrão
├── Documentação atualizada
├── Testes incluídos
└── Definição clara
RASTREAMENTO:
─────────────────────────────────────
├── Label: api, endpoint
├── Link para spec da API
├── Tag de versão
├── Tarefas relacionadas de frontend
└── Trabalho organizado
DOCUMENTAÇÃO DE API:
─────────────────────────────────────
├── Spec OpenAPI no repo
├── Link no NoteVault
├── Mudanças rastreadas
├── Histórico de versão
└── Documentação encontrável
Melhores Práticas
Para Design de API
- Consistência primeiro — Mesmos padrões em todo lugar
- Boas mensagens de erro — Acionáveis, claras
- Versione cuidadosamente — Evite mudanças quebradoras
- Documente bem — Spec OpenAPI
- Pagine sempre — Não retorne tudo
Anti-Padrões
ERROS DE DESIGN DE API:
✗ Nomes inconsistentes
✗ Mudanças quebradoras sem versão
✗ Mensagens de erro genéricas
✗ Sem paginação
✗ Retornando banco de dados inteiro
✗ Documentação desatualizada
✗ Sem rate limiting
✗ Autenticação ruim