O que é REST?
REST, ou Representational State Transfer, é um estilo arquitetural para o design de APIs HTTP. Em vez de inventar comandos, você modela seu domínio como recursos e utiliza os métodos que o HTTP já define para interagir com eles. Um POST /posts cria um post, GET /posts/42 lê um, PATCH /posts/42 o atualiza e DELETE /posts/42 o remove.
O valor disso é a familiaridade. Todo cliente HTTP, proxy, cache e ferramenta já compreende os métodos, códigos de status e headers. Quando você segue as convenções, os clientes conseguem prever como sua API se comporta sem a necessidade de ler um manual específico.
Recursos e URIs
Recursos são os substantivos da sua API. Use coleções no plural e identifique itens individuais por id.
GET /posts
POST /posts
GET /posts/42
PUT /posts/42
PATCH /posts/42
DELETE /posts/42
- Use substantivos, não verbos. O método é o verbo.
- Use nomes de coleções no plural de forma consistente.
- Mantenha as URLs em letras minúsculas com hifens, não underscores ou camelCase.
- Aninhe apenas quando a relação for essencial, como
/posts/42/comments. - Não coloque o formato no caminho; use o header
Accept.
Aninhamentos profundos tornam-se complicados rapidamente. /users/1/posts/2/comments/3 é difícil de construir e documentar; prefira /comments/3 e deixe que os clientes filtrem.
Métodos e suas semânticas
Cada método possui semânticas definidas nas quais os clientes e a infraestrutura confiam.
| Método | Propósito | Seguro | Idempotente |
|---|---|---|---|
| GET | Ler um recurso ou coleção | Sim | Sim |
| POST | Criar um recurso ou disparar uma ação | Não | Não |
| PUT | Substituir um recurso | Não | Sim |
| PATCH | Atualizar parcialmente um recurso | Não | Não |
| DELETE | Remover um recurso | Não | Sim |
Seguro significa que não altera o estado; idempotente significa que repeti-lo tem o mesmo efeito que fazê-lo apenas uma vez. Nunca altere dados com GET, pois clientes, crawlers e caches podem emitir requisições GET livremente.
Status codes
Retorne o código que corresponda ao que aconteceu. Esta é a parte da qual os clientes mais dependem.
- 200 OK — sucesso com corpo de resposta.
- 201 Created — um recurso foi criado; inclua um header
Location. - 204 No Content — sucesso sem corpo, comum para DELETE.
- 400 Bad Request — requisição malformada.
- 401 Unauthorized — autenticação ausente ou inválida.
- 403 Forbidden — autenticado, mas sem permissão.
- 404 Not Found — recurso não encontrado.
- 409 Conflict — conflito de estado, como um item duplicado.
- 422 Unprocessable Entity — sintaticamente válido, mas falhou na validação.
- 429 Too Many Requests — limite de requisições atingido (rate limited); inclua
Retry-After. - 500 Internal Server Error — falha inesperada no servidor.
Retornar 200 com { "success": false } esconde falhas de clientes, caches e monitoramento, e força cada cliente a inventar seu próprio tratamento de erros.
Coleções: filtragem, ordenação e paginação
As coleções precisam de uma linguagem de consulta consistente.
GET /posts?status=published&sort=-createdAt&limit=20&cursor=abc123
- Filtragem com
field=value, e chaves repetidas para OR. - Ordenação com
sort=fieldousort=-fieldpara ordem decrescente. - Paginação com
limitecursor(oupageeperPage). - Seleção de campos com
fields=id,titlequando os clientes desejam menos dados. - Busca com um parâmetro
qdedicado.
Prefira a paginação por cursor para conjuntos de dados grandes ou voláteis, e sempre retorne o próximo cursor na resposta para que os clientes possam paginar sem precisar adivinhar.
{
"data": [{ "id": "42", "title": "Hello" }],
"pagination": { "nextCursor": "abc123", "hasMore": true }
}
Representações e respostas
Respostas são representações de recursos. O JSON é a norma, com um formato estável.
{
"id": "42",
"title": "Hello",
"createdAt": "2026-09-15T10:00:00Z"
}
- Use camelCase ou snake_case de forma consistente, não ambos.
- Use strings ISO 8601 para datas.
- Use ids estáveis como strings quando os clientes puderem exceder a precisão numérica.
- Envolva coleções com
dataepagination, mas retorne recursos únicos diretamente. - Suporte
Accepte definaContent-Typecorretamente.
Statelessness e caching
Cada requisição deve carregar tudo o que é necessário para processá-la: a URL, o método, os headers e o body. Não dependa da memória do servidor entre requisições; é isso que permite executar múltiplas instâncias atrás de um load balancer.
Como o GET é seguro e as respostas são autocontidas, o REST funciona muito bem com o caching do HTTP. Configure Cache-Control e validadores como ETag em recursos cacheáveis, conforme abordado no guia de HTTP.
Erros
Use um formato de erro único em todo o projeto e documente-o.
{
"error": {
"code": "validation_error",
"message": "Title is required",
"details": [{ "field": "title", "issue": "required" }]
}
}
Um code legível por máquina permite que os clientes criem ramificações na lógica, uma message é segura para exibir aos usuários e details ajuda formulários a destacarem campos. Combine isso com o código de status correto.
Melhores práticas
- Modele os recursos com substantivos e deixe que os métodos expressem as ações.
- Retorne o código de status mais específico possível.
- Versione a API antes mesmo de precisar e documente-a (veja Versionamento de API).
- Pagine todas as coleções e defina um limite de
limit. - Valide as entradas e retorne erros estruturados.
- Use nomenclatura e casing consistentes em todo o projeto.
- Faça cache de respostas GET seguras com headers explícitos.
- Implemente rate limit e autenticação (veja Rate Limiting).
Erros comuns
- URLs baseadas em verbos que duplicam os métodos HTTP.
- Retornar 200 para erros.
- Coleções ilimitadas sem paginação.
- Inconsistência em casing, formatos de data ou estruturas de erro.
- Aninhamento profundo que se torna impossível de manter.
- Mutação de estado em requisições GET.
- Quebrar clientes ao alterar a estrutura de respostas silenciosamente.
Próximos passos
REST é a maneira padrão de expor um backend. Consolide seus conhecimentos com o guia de HTTP, documente-o com OpenAPI, evolua-o com segurança através de API Versioning e proteja-o com Rate Limiting. Compare esse modelo com GraphQL quando os clientes precisarem de mais flexibilidade.