Formatos de Resposta de API: Boas Práticas para APIs Consistentes
Respostas de API inconsistentes são uma das principais queixas dos programadores de frontend. Quando cada endpoint devolve dados num formato diferente, o código do cliente fica cheio de casos especiais. Um formato de resposta consistente melhora a experiência do programador, reduz erros e torna a sua API auto-documentada.
O Envelope de Resposta
Envolva cada resposta numa estrutura consistente:
Sucesso (Recurso Único)
{
"data": {
"id": "user_123",
"name": "Alice",
"email": "alice@example.com",
"createdAt": "2024-01-15T10:30:00Z"
},
"meta": {
"requestId": "req_abc123"
}
}
Sucesso (Coleção)
{
"data": [
{ "id": "user_123", "name": "Alice" },
{ "id": "user_456", "name": "Bob" }
],
"meta": {
"total": 142,
"page": 1,
"perPage": 20,
"requestId": "req_def456"
}
}
Erro
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{ "field": "email", "message": "Invalid email format" }
]
},
"meta": {
"requestId": "req_ghi789"
}
}
O princípio fundamental: os clientes verificam sempre data ou error no nível superior. Nunca misture dados de sucesso e informações de erro na mesma resposta.
Valide o seu formato de resposta com o nosso Validador de JSON.
Códigos de Estado HTTP
Utilize os códigos de estado corretamente — são a primeira coisa que os clientes verificam:
Códigos de Sucesso
| Código | Quando |
|---|---|
| 200 OK | Sucesso em GET, PUT/PATCH |
| 201 Created | POST que criou um recurso |
| 204 No Content | Sucesso em DELETE (sem corpo) |
Códigos de Erro do Cliente
| Código | Quando |
|---|---|
| 400 Bad Request | Sintaxe de pedido malformada |
| 401 Unauthorized | Autenticação ausente ou inválida |
| 403 Forbidden | Autenticado mas não autorizado |
| 404 Not Found | O recurso não existe |
| 409 Conflict | Conflito de estado do recurso (duplicado) |
| 422 Unprocessable | Sintaxe válida mas erros semânticos |
| 429 Too Many Requests | Limite de taxa excedido |
Códigos de Erro do Servidor
| Código | Quando |
|---|---|
| 500 Internal Server Error | Falha inesperada do servidor |
| 502 Bad Gateway | Falha do serviço upstream |
| 503 Service Unavailable | Sobrecarga temporária ou manutenção |
Desenho de Respostas de Erro
Boas respostas de erro ajudam os programadores a depurar rapidamente:
{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "User with ID 'user_999' not found",
"details": [],
"documentationUrl": "https://api.example.com/docs/errors#RESOURCE_NOT_FOUND"
},
"meta": {
"requestId": "req_xyz789",
"timestamp": "2024-01-15T10:30:00Z"
}
}
Regras:
codeé legível por máquinas (string constante, não o código de estado HTTP)messageé legível por humanos (pode mudar sem quebrar os clientes)detailsfornece erros ao nível do campo para falhas de validaçãorequestIdpermite à equipa de suporte rastrear o pedido nos registos
Padrões de Paginação
Baseada em Offset
Simples e suporta saltar para páginas arbitrárias:
{
"data": ["..."],
"meta": {
"page": 2,
"perPage": 20,
"total": 142,
"totalPages": 8
},
"links": {
"first": "/api/users?page=1&per_page=20",
"prev": "/api/users?page=1&per_page=20",
"next": "/api/users?page=3&per_page=20",
"last": "/api/users?page=8&per_page=20"
}
}
Baseada em Cursor
Melhor para dados em tempo real e conjuntos de dados grandes:
{
"data": ["..."],
"meta": {
"hasNext": true,
"hasPrev": true
},
"links": {
"next": "/api/users?cursor=eyJpZCI6MTQzfQ&limit=20",
"prev": "/api/users?cursor=eyJpZCI6MTIzfQ&limit=20&direction=prev"
}
}
Data e Hora
Utilize sempre ISO 8601 com informação de fuso horário:
{
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T14:22:33+00:00",
"expiresAt": "2024-12-31T23:59:59Z"
}
Nunca utilize:
- Timestamps Unix (ambíguos: segundos ou milissegundos?)
- Datas locais sem fuso horário
- Formatos personalizados como MM/DD/AAAA
Para mais informações sobre o tratamento de timestamps, consulte o nosso guia de Timestamps Unix.
Null vs Campos Ausentes
Duas abordagens comuns:
Incluir com null (explícito):
{ "name": "Alice", "avatar": null, "bio": null }
Omitir campos ausentes (esparso):
{ "name": "Alice" }
Recomendação: Seja consistente dentro da sua API. Nulls explícitos são melhores para linguagens tipadas (os clientes sabem que o campo existe). Esparso é melhor para ambientes com restrições de largura de banda.
Versionamento de Respostas
Quando o formato de resposta muda, versione a sua API:
GET /api/v2/users/123
Alterações que quebram e requerem versionamento:
- Remover um campo
- Alterar o tipo de um campo
- Renomear um campo
- Alterar a estrutura do envelope de resposta
Alterações não destrutivas (seguras sem versionamento):
- Adicionar novos campos
- Adicionar novos endpoints
- Adicionar novos valores de enum
FAQ
Devo envolver as respostas de sucesso numa chave data ou devolver o recurso diretamente?
Utilizar um invólucro data proporciona uma estrutura consistente para todas as respostas e deixa espaço para metadados, paginação e ligações ao lado dos dados. Devolver o recurso diretamente é mais simples para endpoints de recurso único. A maioria das APIs modernas utiliza a abordagem com invólucro para consistência.
Como devo lidar com falhas parciais em operações em lote?
Devolva 200 com uma resposta que inclua tanto os sucessos como as falhas no objeto de dados. Utilizar 207 Multi-Status (WebDAV) é outra opção mas é menos comum em APIs REST.
Recursos Relacionados
- Formatador de JSON — Formate respostas de API
- Padrões de Design de API JSON — Guia completo de design de API
- Validação de JSON Schema — Valide estruturas de resposta