Esta apresentação NÃO é sobre:
- Criar uma API REST do zero
- Um curso sobre HTTP
- Um curso de FastAPI/Python
Porém se possui interesse nessses temas, recomendo muito o curso FastAPI do Zero publicado pelo Eduardo Mendes.
Esta apresentação é sobre
- Formas de simplificar a implementação e consumo de API REST por meio de boas práticas.
- Independente de tecnologia, ecosistema e linguagem.
- Otimizações para facilitar sua vida na hroa de lidar com automações e deploys orquestrados
A web , REST API e Hipermidia
Se você atua na área de tecnologia como desenvolvedor de sofware para a web, já deve estar familiarizado com o termo API(Application Progaming Interface - Interface de Programação de Aplicação), que pode ser toda e quaisquer aplicação que tem como objetivo interfacear de forrma programavél algum recurso, indo de consulta a base de dados a acesso a recursos de hardware como GPU.
Exemplos de API que podemos citar seria o uso de GPU por meio do navegador, através da API WebGL
Porém pensando em aplicações web, uma API REST(ful) - Representational State Transfer, refere-se a uma forma de controlar e restringir uma aplicação por meio de representação de estados destas em recursos. Atualmente o formato mais comun de implementação consiste em um servidor Web que por meio do protocolo HTTP (Hipertext Transfer Protocol) que entrega as informações a respeito dos estados em estrutura JSON (Javascript Object Notation).
Uma aplicação REST que contemple todos os princípios referentes á ideopotência, que é a capacidade de representar todos os esttados necessários de forma semântica, usando os verbos adequados (GET, POST, PUT, PATCH, DELETE...) bem como respeitando os principíos de se manter sem estados entre requisições, ser cacheavél e possuir mensagens expresivas em caso de falha é denominada de RESTful, porém podemos usar o termo em questão de forma análoga ao próprio conceito de REST API em linhas gerais.
Exemplo prático e resumido
Uma API REST é como um restaurante, onde o estabelecimento é o servidor, o
cliente por sua vez está implicito no nome.
- Para saber quais pratos estão disponivéis, você lê o cardápio, assim como um
método GET no endpointt
/cardapiopode retornar uma lista. - Ao pedir mais informações ao garçon sobre o prato em questão , seria como usar
o método GET no endpoint
cardapio/12para saber os detalhes do item 12 do cardápio - Para realizar um pedido ao garçon para a sua mesa, seria como usar o método POST no endpoint /pedido, enviado no corpo da requisição um objetto com o número da sua mesa e os items do cardápio.
- Para pedir uma mudança em um item no prato, seria equivalente ao usar o método PATCH.
- Para mudar o pedido por completo , ou pedir (com educação) para mudar o seu pedido é como usar o método PUT
- Para cancelar o pedido , podemos usar o DELETE
- O método OPTIONS seria equivalente a verificar se o restaurante está servindo aquele prato.
- O método HEAD seria equivalente a avaliar o preço da refeição e se você tem alguma alergia ao prato em questão.
- Se o restuarante possui pulseiras de identificação entregues na hora da reserva, seria o equivalente ao utilizar tokens de autenticação.
Um exeplo de API REST aberta ao público seria a API OMDb, Open Movie Databse
Cabeçarios HTTP (Headers)
Cabeçarios são informações extras que podem ser enviadas , bem como recebidas por uma ou para uma API REST, nestes em formatos de texto (string) detalhamos informações e metaddos no geral sobre o conteúdo trafegado, coisas como informar a origem da aplicação, realizar o envio de chaves de autentcação e até mesmo informar a aplicação cliente a política de cache do recurso.
Exemplos de cabeçários comuns

HATEOS (Hypermidia as a the Engine of the Application State)
Nesta conversa, o termo Hipermidia, mais precisamente o acrônomo Hypermedia as the engine of application state (HATEOAS), seria uma forma de implementação de arquitetura para REST API que por meio das hipermidias, torna a consulta e navegação pelos recursos mais dinâmica, conseguindo comunicar por meio de metadados e padrões, formas de navegação e integração entre os recursos disponibilizados.
A principal e mais comun forma de implementação de HATEOS em aplicações modernas é dada por meio da implementação de recursos com HAL - Hypertext Application Language, onde adicionamos a resposta do dado, possivéis links relacionados a este, como exemplo a resposta abaixo.
{
"_links": {
"self": {
"href": "http://example.com/api/book/hal-cookbook"
}
},
"id": "hal-cookbook",
"name": "HAL Cookbook"
}
Além do HAL, outros formatos para implementar HATEOS seriam JSON:API, Siren, Hydra (JSON-LD), Collection+JSON e UBER.
JSON:API
{
"data": {
"type": "book",
"id": "1",
"attributes": {
"title": "O Senhor dos Anéis"
},
"links": {
"self": "/books/1"
},
"relationships": {
"author": {
"links": {
"related": "/books/1/author"
}
}
}
},
"links": {
"self": "/books"
}
}
Siren
{
"class": ["book"],
"properties": {
"id": 1,
"title": "O Senhor dos Anéis"
},
"links": [
{ "rel": ["self"], "href": "/books/1" },
{ "rel": ["author"], "href": "/books/1/author" }
],
"actions": [
{
"name": "update-book",
"method": "PUT",
"href": "/books/1",
"type": "application/json",
"fields": [
{ "name": "title", "type": "text" }
]
}
]
}
Hydra (JSON-LD)
{
"@context": "/contexts/Book.jsonld",
"@id": "/books/1",
"@type": "Book",
"title": "O Senhor dos Anéis",
"author": "/books/1/author",
"hydra:operation": [
{
"@type": "hydra:UpdateResourceOperation",
"hydra:method": "PUT",
"hydra:expects": "http://schema.org/Book",
"hydra:returns": "http://schema.org/Book",
"hydra:target": "/books/1"
}
]
}
Collection+JSON
{
"collection": {
"version": "1.0",
"href": "/books",
"items": [
{
"href": "/books/1",
"data": [
{ "name": "id", "value": "1" },
{ "name": "title", "value": "O Senhor dos Anéis" }
],
"links": [
{ "rel": "author", "href": "/books/1/author" }
]
}
],
"links": [
{ "rel": "self", "href": "/books" }
],
"queries": [
{
"rel": "search",
"href": "/books/search",
"data": [
{ "name": "title", "value": "" }
]
}
]
}
}
UBER (Uber Hypermedia)
{
"uber": {
"version": "1.0",
"data": [
{
"id": "book",
"name": "O Senhor dos Anéis",
"rel": ["self"],
"url": "/books/1",
"data": [
{
"rel": ["author"],
"url": "/books/1/author"
}
]
}
]
}
}
HATEOS é complicado, mas não deveria ser
A principal dificuldade dos formatos comuns para HATEOS gira em torno da dificuldade de serialização:
- A obrigatoriedade de serializar os resultados para obter metadados tornando toda operação de leitura de metadados bloqueante.
- Interferência no próprio retorno dos dados , tornando mais complicado a vida das aplicações clientes que consomen esta API
- Mesmo um resultado sem itens algum, geraria a necessidade de serializar o resultado para saber que este está sem itens no caso de listagem
A serialização mal otimizada pode dificultar a performance de aplicações dinâmicas, tais como feeds de redes sociais, leitura de dados em tempo real e procesos de digestão de alto volume de dados.
Outro problema menos evidente seria a obrigatoriedade de manter implementações sequênciais de problemas que seriam resolvidos de uma forma melhor por meio concorrência/paralelismo
Como resolver o problema
A solução para as dificuldades geradas pela implementação de uma arquitetura HATEOS consiste em atender os seguintes pré-requisitos
- Metadados precisam estar separados dos dados
- Metadados Não precisam ser serializados
- Precisamos saber a informação de items na página atual (Mínimo aceitavél)
- Precisamos saber como informar a próxima página e a página anterior (independente da forma de paginação (saltos, paginas ou ponteiros))
A forma mais simples de resolver isso seria por meio da implementação da RFC 8288 - Web Linking para a paginação e demais informações por meio de cabeçários customizados.
Ainda que muitos serviços usem o prefixo
X-para headers especiais, atualmente isso é desencorajado especificamente pela RFC 6648
Desta forma, podemos recompoer nosso exemplo de livros por meio do seguinte modelo para o corpo da resposta (Response Body) em uma simples lista de JSON.
[
{
"id": 1,
"title": "O Senhor dos Anéis",
"author": "R. R. Tolkein"
}
]
Por fim, podemos ter os seguintes cabeçãrios, nem todos são obrigatórios por
questões de performance, principalmente aqueles que realizam a contagem de
items, porém o Items-Returned é uma ótima forma de saber se a lista retornou
sem item algum (vazia).
HTTP/1.1 200 OK
Content-Type: application/json
Total-Count: 1000 # Total de itens no banco de dados
Total-Pages: 100 # Total de páginas (se você já calculou)
Items-Per-Page: 10 # Itens por página
Current-Page: 1 # Página atual
Items-Returned: 1 # Total de itens retornados na página atual
Link: <https://api.exemplo.com/items?page=2>; rel="next",
<https://api.exemplo.com/items?page=100>; rel="last",
<https://api.exemplo.com/items?page=1>; rel="first"
<https://api.exemplo.com/items?page=1>; rel="prev"
Considerando cenários de requisições de criação de dados , principalmente de
objetos únicos, podemos usar o header Location caso este possua algum endpoint
de consulta por meio de id de referência que seja único e ideopotente.
Outro ponto importante é que nem sempre poderemos configurar o domínio, nossa API pode estar limitada por um API Getway ou ferramenta de DNS, nesses casos é recomendado o uso de links relativos, isso cria um ônus para o cliente concatenar ao dôminio original, mas este é disponiblizado no header Host.
Dessa forma o exemplo que utilizamos anteriormente é capaz de evoluir para esse modelo
HTTP/1.1 200 OK
Content-Type: application/json
Total-Count: 1000 # Total de itens no banco de dados
Total-Pages: 100 # Total de páginas (se você já calculou)
Items-Per-Page: 10 # Itens por página
Current-Page: 1 # Página atual
Items-Returned: 1 # Total de itens retornados na página atual
Link: </items?page=2>; rel="next",
</items?page=100>; rel="last",
</items?page=1>; rel="first"
</items?page=1>; rel="prev"
O uso de contadores deve ser moderado, visto que em bases grandes de dados , ou com mudanças constantes, essa operação pode custar muito recurso, nesses casos cabe ao desenvolvedor responsavél, avaliar as necessidades e capacidades do projeto.
Status Code
StatusCode são números de 3 dígitos entregues numa requisição http como forma de comunicar o retorno para uma requisição de forma imediata, sem precisar de serialização ou informações adicionais para tomar decisões básicas.
É importante que estes sejam usados de forma consistente, ao passo que clientes automatizados como frameworks possam consumir sua API sem muito workarround
Podemos dividir os status code em 5 faixas.
- 1xx: status de informação, usados para comunicar algum tipo de informação a respeito do servidor.
- 100: continue, muito usado quando se quer evitar o envio de um payload muito grande mas precisa verificar se o servidor está disponivél
- Um caso de uso curioso que eu vi isso em prática foi em fila de geração de PDF de apólices em sistemas de seguradora.
- 100: continue, muito usado quando se quer evitar o envio de um payload muito grande mas precisa verificar se o servidor está disponivél
- 2xx: status de sucesso (é o que esperamos que aconteça no caminho feliz), representa uma operação bem sucedida.
- 200: Ok, simplesmente Ok
- 201: Content created, um puxão de orelha nos devs que deveriam usar mais esse status, principalmente quando uma operação resulta em algum tipo de dado criado, como vimos, métodos POST e PUT.
- 202: Accepted, quando uma requisição é aceita , porém o resultado será mandado depois, isso é crucial quando se faz http polling, que é o processo de ficar verificando no servidor até a informação está pronta , quando retorna um status 200, muito comun em sistemas de fila de impressão mais antigos ou de fila de arquivos gerados em background.
- 204: No content, a operação deu certo, mas não tem body algum a ser retornado, porém os headers são úteis e se necessário, deve ser atualizado cache, em casos de DELETE é o ideal a ser usado na maioria dos cenários*
- 3xx: status de redirecionamento, servem para informar os possivéis motivos de dados terem sido migrados
- 301: Moved Permanently, siginifica que o conteúdo foi movido de url, a nova será disponibilizada no response.
- 302: Found, siginifica que o conteúdo foi achado e movido temporariamente, pode representar uma nova url e um novo método.
- 307: Temporary Redirect, semântica igual ao 302, porém significa que o método HTTP não deve ser mudado no redirect, apenas a url.
- 4xx: status de erros causados pelo cliente
culpa do frontend, quando algum dado enviado ou requisição feita pelo lado cliente é inconsistente.- 404: Não encontrado, para rota ou conteúdo não encontrado, origem do meme 404: Not Found
- 401: Não autenticado, siginifica que o usuário não forneceu a informação que determina que ele foi autenticado em algum momento, usado como identificador de endpoints protegidos, ou seja , endpoints disponivéis apenas para usuários autenticados.
- 403: Forbidden, siginifica que o usuário, independente de autenticado ou não, não possui acesso a informação devida.
- 418: I'm a teapot (Eu sou uma chaleira), servidor se recusa a fazer café.
- 5xx: status de erro causados pelo servidor
culpa sua, usado principalmente para erros de mecanismos internos/- 500: Internal Server Error, quando seu servidor tem um erro de execução , runtime ou um erro não tratavél, em ambiente de desenvolvimento e nos logs, normalmente consta a stacktrace que ocasionou a falha.
- 502: Bad Getway: Quando um servidor de Getway falha em achar ou realizar a conexão ocasionada pelo servidor de origem, normalmente associado a timeout entre o getway e o servidor consumido por este.
- 503: Service Unavailable, mostado quando há uma falha temporária, em conjunto com uma página de erro amigavél se possivél para explicar de forma breve a falha, em cassos de serviços como aplicação, é recomendado devolver o Header Retry-After com informações de qunado está previsto a voltar o recurso. Era muito comun no período de transição para a Web 2.0 (Twiter lá por 2010 e o famigerado "Rails não escala")
Dicas e macetes para uso coerente de status code
- Quando uma operação como DELETE puder ser revertida por meio de um endpoint simples, ao realizar o DELETE trazer a url de undo nos headers.
- Evite escrever headers costumizados que podem ser sobreescritos por proxy, como headers referente a timeout
- Uma forma de parar ataques de força bruta automatizados é responder toda request de falha de autenticação com status 404 (*Gambiiarra)
- 301 é muito comun para redirect quando você está em transição de dôminios
- Em aplicações fullstack ou servidores que as respostas são visualizadas no browser e/ou pelo usuário final de forma direta, ttendem a responder com mensagens detalhadas e acessivéis possivéis infos de causa, 404 é bem comun vermos esse tipo de design.
- Resultado de requisição POST, PUT é recomendado 201
- Resultado de requisição GET, HEAD é recomendado 200
- Resultado de requisição DELETE é normalmente 204
Referências
- API REST - o que é API REST?, Acessado em 06/12/2025.
- WebGL: 2D and 3D Graphics for the web, Acessado em 06/12/2025
- OMDb API - The Open Movie Database, Acessado em 06/12/2025
- HTTP Headers - HTTP | MDN, Acessado em 07/12/2025
- Hypertext Application Language - Wikipedia, Acessado em 06/12/2025
- RFC 8288 - Web Linking, Acessado em 11/12/2025
- RFC 6648 - Deprecating the "X-" Prefix and Similar Constructs in Application Protocols, Acessado em 11/12/2025
- A história de Ruby on Rails | Por quê deu certo?. Acessado em 12/12/2025