O que orienta um bom design de API
- Comece por consumidores, casos de uso e invariantes; endpoints são consequência do contrato.
- Use métodos e códigos segundo a semântica HTTP, sem tentar codificar toda regra de negócio no status.
- Requests, respostas, erros, paginação e nomes precisam formar uma linguagem consistente.
- Autenticação identifica uma entidade; autorização decide o que ela pode fazer em cada recurso.
- Compatibilidade retroativa exige conhecer como clientes realmente interpretam o contrato.
- Documentação, testes, telemetria e política de depreciação fazem parte da interface.
O que é design de API?
- Sintaxe: operações, parâmetros, schemas e formatos.
- Semântica: o que cada dado significa e quais efeitos a operação produz.
- Operação: autenticação, limites, disponibilidade, rastreabilidade, depreciação e suporte.
Comece pelo caso de uso e pelo contrato
- criar um pedido com itens e endereço;
- consultar o estado atual;
- listar pedidos recentes em páginas estáveis;
- cancelar um pedido ainda não processado;
- distinguir validação inválida, falta de permissão e conflito de estado.
Princípio, problema evitado e custo
Os princípios orientam escolhas; cada custo precisa ser avaliado no contexto da API e de seus consumidores.
Modele recursos, nomes e relacionamentos
Http
GET /orders
GET /orders/ord_01J9M6P2JQ7X
Http
GET /orders/ord_01J9M6P2JQ7X/items
GET /customers/cus_01J8ZK3G/orders
Http
POST /orders/ord_01J9M6P2JQ7X/cancellations
Semântica HTTP sem dogmatismo
Segurança e idempotência não são sinônimos
Métodos precisam representar o efeito
- GET recupera uma representação sem solicitar mudança de estado.
- POST envia dados para processamento conforme a semântica do recurso; costuma criar ou iniciar operações.
- PUT cria ou substitui o estado do recurso identificado pela URI, conforme o contrato.
- PATCH aplica uma modificação parcial segundo o formato de patch adotado.
- DELETE solicita a remoção da associação entre o recurso e sua URI; detalhes de retenção interna pertencem ao contrato.
Códigos de status são uma camada, não o domínio inteiro
- 200 OK para uma resposta bem-sucedida com representação;
- 201 Created quando um novo recurso foi criado, idealmente com Location;
- 202 Accepted quando o processamento foi aceito, mas ainda não terminou;
- 204 No Content quando houve sucesso e não há conteúdo de resposta;
- 400 Bad Request para requisição malformada ou inválida segundo o contrato;
- 401 Unauthorized quando faltam credenciais válidas — apesar do nome histórico, refere-se a autenticação;
- 403 Forbidden quando a requisição é compreendida, mas não autorizada;
- 404 Not Found quando o recurso não foi encontrado ou sua existência não deve ser revelada;
- 409 Conflict quando a requisição conflita com o estado atual;
- 412 Precondition Failed quando uma precondição como If-Match falha;
- 422 Unprocessable Content quando a sintaxe é compreendida, mas as instruções não podem ser processadas;
- 429 Too Many Requests quando o cliente excedeu um limite aplicável;
- 500 Internal Server Error para falha inesperada do servidor, sem expor stack trace.
Requests, respostas e erros consistentes
- nomes e formatos de campos;
- datas e fusos, preferencialmente com formato inequívoco;
- unidades e representação monetária;
- distinção entre campo ausente e null;
- IDs opacos e sua estabilidade;
- envelope de coleções e metadados;
- formato de erros e localização de falhas de validação.
Decisão frágil e versão melhorada
De mensagem improvisada para erro estruturado
Http
HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json
X-Request-Id: req_01J9M8XFCWYK
{
"type": "https://api.example.com/problems/invalid-order",
"title": "Pedido inválido",
"status": 422,
"detail": "Corrija os campos indicados e envie novamente.",
"instance": "/problems/req_01J9M8XFCWYK",
"errors": [
{
"pointer": "/items/0/quantity",
"code": "must_be_positive"
}
]
}
Exemplo evolutivo: uma API pequena de pedidos
1. Criar um pedido
Http
POST /orders HTTP/1.1
Host: api.example.com
Authorization: Bearer <access-token>
Content-Type: application/json
Idempotency-Key: 2f6d0f4e-9fe2-4b54-a50e-38a22fc1d920
{
"customerId": "cus_01J8ZK3G",
"currency": "BRL",
"items": [
{ "productId": "prd_01J82QH4", "quantity": 2 }
]
}
Http
HTTP/1.1 201 Created
Location: /orders/ord_01J9M6P2JQ7X
Content-Type: application/json
ETag: "7e91c9"
X-Request-Id: req_01J9M8H99P8A
{
"id": "ord_01J9M6P2JQ7X",
"customerId": "cus_01J8ZK3G",
"status": "pending",
"currency": "BRL",
"totalMinor": 15980,
"items": [
{
"productId": "prd_01J82QH4",
"quantity": 2,
"unitPriceMinor": 7990
}
],
"createdAt": "2026-08-08T14:32:18Z"
}
2. Listar com paginação por cursor
Http
GET /orders?status=pending&sort=-createdAt&limit=20&cursor=eyJpZCI6Im9yZF8wMUo5In0 HTTP/1.1
Host: api.example.com
Authorization: Bearer <access-token>
Json
{
"data": [
{
"id": "ord_01J9M6P2JQ7X",
"status": "pending",
"currency": "BRL",
"totalMinor": 15980,
"createdAt": "2026-08-08T14:32:18Z"
}
],
"page": {
"limit": 20,
"nextCursor": "eyJpZCI6Im9yZF8wMUo4In0"
}
}
3. Atualizar com controle de concorrência
Http
PATCH /orders/ord_01J9M6P2JQ7X HTTP/1.1
Host: api.example.com
Authorization: Bearer <access-token>
Content-Type: application/merge-patch+json
If-Match: "7e91c9"
{
"deliveryNote": "Entregar na portaria"
}
Validação, filtragem, ordenação e busca
Text
?status=pending
?createdAfter=2026-08-01T00:00:00Z
?sort=-createdAt,totalMinor
?limit=20&cursor=<opaque-cursor>
?q=termo
Autenticação, autorização e proteção contra abuso
Dados sensíveis e segredos
- aceite apenas dados necessários à operação;
- evite reproduzir segredos em respostas, erros, logs e traces;
- marque campos sensíveis e aplique redação antes da telemetria;
- defina retenção e acesso aos registros;
- não trate criptografia como substituto de autorização.
Rate limiting não é apenas um número
Idempotency keys em operações adequadas
- quais operações aceitam a chave;
- formato, escopo e período de retenção;
- se chave igual com payload diferente é rejeitada;
- qual status e resposta são repetidos;
- comportamento enquanto a primeira tentativa ainda está em andamento.
Concorrência e consistência
Evolução, compatibilidade e depreciação
Estratégias de versão
- Caminho, como /v1/orders: visível e simples de rotear, mas pode incentivar cópias integrais.
- Cabeçalho ou media type: separa versão da identidade do recurso, porém aumenta complexidade de teste, cache e descoberta.
- Evolução contínua: mantém uma versão pública e usa mudanças compatíveis, mas exige disciplina, telemetria e política forte de depreciação.
Deprecar é um processo observável
Documentação como contrato
Observabilidade sem expor segredos
Text
cliente ── contrato e credencial ──> gateway/API ── identidade e contexto ──> serviço
^ │ │
└──── resposta + request ID ───────┴──── status, limites e telemetria ─────┘
REST, GraphQL, RPC e eventos
- REST/HTTP orientado a recursos funciona bem quando recursos e semântica do protocolo combinam com os casos de uso, caches e intermediários.
- GraphQL permite ao cliente selecionar um grafo tipado e pode reduzir combinações de endpoints; exige decisões próprias sobre autorização, custo, cache, erros e evolução do schema.
- RPC expressa comandos e procedimentos diretamente; pode ser adequado quando operações dominam o modelo. Ainda precisa de contratos, compatibilidade, deadlines e idempotência.
- Eventos desacoplam produtores e consumidores no tempo, mas introduzem entrega, ordenação, duplicação, schema e observabilidade distribuída.
Checklist de revisão de contrato
Antes de publicar ou alterar uma API
- Consumidores, casos de uso, invariantes e falhas principais estão explícitos?
- Recursos, comandos, nomes, IDs, datas, dinheiro e ausência de valor seguem convenções documentadas?
- Métodos, segurança, idempotência e códigos respeitam a semântica HTTP aplicável?
- Requests, respostas, coleções e erros mantêm estrutura consistente?
- Validação informa campos e códigos sem exigir análise de mensagens humanas?
- Paginação possui ordenação estável e comportamento definido durante mudanças no conjunto?
- Filtros, busca e ordenação têm campos, operadores e limites documentados?
- Autenticação e autorização estão separadas, com mínimo privilégio por recurso e ação?
- Tokens, dados pessoais e segredos são excluídos de URLs, erros e telemetria?
- Retries, idempotency keys, timeouts e operações assíncronas possuem contrato explícito?
- Concorrência e consistência foram analisadas nas operações sujeitas a disputa?
- Mudanças foram classificadas contra clientes reais, inclusive enums e validação mais restritiva?
- Depreciação possui alternativa, prazo, comunicação e medição de uso?
- OpenAPI, exemplos e implementação passam por testes de contrato?
- Request IDs, logs e métricas permitem diagnóstico sem expor conteúdo sensível?