No primeiro artigo, eu falei sobre os recursos e as operações em uma API, abordando uma arquitetura com “API Design Patterns”.
Hoje, irei abordar os Status Codes existentes, bem como ponderar sobre alguns casos e que são, provavelmente, um ponto de discussão.
O retorno de uma requisição HTTP sempre vem acompanhada de um Status Code, utilizado para representar o resultado da requisição.
Há anos eu venho percebendo que os Status Code mais utilizados são sempre os básicos: 200, 201, 400, 404, 401, 403. Por que?
- Seria desconhecimento?
- Desinteresse em fazer melhor?
- Preguiça?
- Pressão de tempo?
- Requisitos do projeto?
Eu uso IAs para conversar, para saber qual seria a resposta de alguns questionamentos que faço. Você acredita que a IA quis passar pano quente nas justificativas acima?
Como se o alegar desconhecer a gama de Status Codes existentes, por um arquiteto ou mesmo desenvolver pleno/sênior, fosse algo aceitável. Se estamos trabalhando com um tipo de software e neste caso, um software baseado no HTTP – uma API, temos a obrigação de buscar o conhecimento mínimo necessário para entregar um software de qualidade e com uma semântica mais adequada, independente do client.
Aceitar algo medíocre e utilizar como justificativa a opção “soluções mais simples e rápidas”, mostrando o desinteresse e preguiça seria, no mínimo, uma falta de cuidado na adoção das boas práticas.
Da mesma forma, não podemos aceitar que a manutenção e o suporte sejam usados como desculpa para alegar que seriam prejudicados por um aumento de complexidade, principalmente para equipes ou projetos pequenos. Pelo contrário.
A implementação correta dos Status Code traz como benefícios:
- Melhora a depuração: Informações específicas sobre o que deu errado podem ajudar os desenvolvedores a identificarem e resolverem problemas mais eficientemente.
- Facilita a documentação: Documentar uma API com Status Code apropriados oferece aos usuários/desenvolvedores – tanto front, quanto back, uma melhor compreensão do comportamento esperado da API.
- Aumenta a transparência: Clients da API podem receber feedback mais detalhado e agir de acordo, melhorando a interação entre cliente e servidor.
- Reduz a ambiguidade: Status Code claros e precisos eliminam a necessidade de adivinhar o que um código genérico (como 400) poderia significar em um contexto específico.
Portanto, a adoção de uma prática mais detalhada no uso de Status Code HTTP é benéfica para todos os envolvidos, sejam os desenvolvedores dos clients ou da própria API.
Reforçando que a utilização correta dos Status Code HTTP é um aspecto crucial no design de APIs e a subutilização dos Status Code é uma falha comum em APIs.
Cada Status Code tem um significado específico e a escolha correta do código pode tornar uma API muito mais semântica e intuitiva para os desenvolvedores que a utilizam.
Como API, sou responsável por identificar os recursos solicitados e conforme o método HTTP utilizado, retornar um Status Code mais semântico e mais assertivo em relação às informações que preciso devolver para o client.
Um exemplo bem comum é a utilização do 200 para os casos de sucesso e do 400 para os casos de erro.
Muitas APIs recorrem ao uso genérico do Status Code 400 (Bad Request) para indicar quase todo tipo de erro de entrada de dados ou de operação. Embora seja tecnicamente correto que um 400 indique uma requisição mal-formada ou com parâmetros errados, existem muitos outros Status Code que poderiam fornecer uma descrição mais precisa do tipo de erro que ocorreu.

A seguir estão descritas as cinco classes de HTTP Status Code:
HTTP Status, Descrição
- 1xx: Informativo - Não utilizado para APIs
- 2xx: Sucesso
- 3xx: Redirecionamento
- 4xx: Erro de Cliente
- 5xx: Erro de Servidor
Detalhamento das classes de Status Code
A seguir estão descritos os HTTP Status Code que podem ser utilizados em cada método (GET, POST, PUT, DELETE e PATCH) nas APIs:
Status Code 2xx
200: OK
- Requisição bem-sucedida.
- Métodos: GET, POST *, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Pode ser retornado para PUT, DELETE ou PATCH, só quando houver necessidade real de um retorno com conteúdo, caso contrário deveremos retornar 204 para esses métodos.
Nota *: Para o POST, somente no retorno de uma consulta com filtros obrigatórios. Como mencionado no primeiro artigo, os parâmetros da query string são opcionais e não podem ser obrigatórios. Se a consulta for feita através de um formulário e este possuir campos obrigatórios, deve-se utilizar o método POST, já que o GET envia os dados na query string, e por se tratar do retorno de uma consulta, então 200 é o retorno assertivo.
201: Created
- Requisição concluída e resultou em um novo recurso.
- Método: POST
- Response body: Padronizado, de acordo com a necessidade.
202: Accepted
- Requisição aceita para processamento, mas o processamento ainda não foi concluído.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Utilizado em requisições assíncronas.
Exemplo: Considere um e-commerce onde o pedido foi aceito e o pagamento com cartão só será processo posteriormente.
204: No Content
- Requisição concluída, mas não é necessário retornar informações adicionais.
- Métodos: PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
206: Partial Content
- Requisição com resposta parcial.
- Métodos: GET, POST *
- Response body: Padronizado, de acordo com a necessidade.
Nota: Normalmente utilizado ao retornar conteúdo de uma paginação. Quando o resultado retorna uma única página, então o retorno deve ser 200.
Nota *: Para o POST, temos a mesma situação do 200.
Status Code 3xx
301: Moved Permanently
- Indica que o recurso solicitado foi movido permanentemente para uma nova URL. O servidor inclui no cabeçalho da resposta o campo Location, que fornece a nova URL permanente do recurso.
- Método: GET
- Response body: Padronizado, de acordo com a necessidade.
302: Recurso Movido
- Indica que o recurso solicitado foi temporariamente movido para uma nova URL. Quando um cliente faz uma requisição a um servidor web por um recurso que possui um Status Code 302, também é incluído no cabeçalho da resposta o campo Location, que contém a URL temporária do recurso.
- Método: GET
- Response body: Padronizado, de acordo com a necessidade.
303: See Other
- A resposta ao pedido pode ser encontrada em uma URI diferente e deve ser recuperada utilizando um método GET nesse recurso (utilizado no retorno de uma consulta de status de um recurso assíncrono que já foi concluído.
- Método: GET
- Response body: Link { rel: string, href: string }
Status Code 4xx
400: Bad Request
- A solicitação não pôde ser entendida pelo servidor devido à sintaxe malformada.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Utilizado quando o consumidor da API fez uma requisição passando uma mensagem com formato diferente do especificado pela documentação da API.
Nota: Utilizado também, quando constatamos uma má intenção na requisição do Client
401: Unauthorized
- Requisição requer autenticação do usuário.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Utilizado quando o consumidor da API não passou uma credencial de acesso válida.
403: Forbidden
- Servidor entendeu o pedido, mas se recusa a aceitá-la.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Utilizado quando o consumidor da API passou sua credencial de acesso válida, mas não tem permissão para acessar um recurso em específico.
404: Not Found
- Servidor não encontrou nada na URI.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Utilizado quando o consumidor da API tentou acessar um, recurso ou elemento que não existe.
Nota: Caso o retorno seja o padrão da API, então a URI não foi encontrada. Falaremos sobre isso adiante.
405: Method not Allowed
- Método especificado não é permitido para o recurso.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padrão da API; Possível criar um retorno padronizado, de acordo com a necessidade.
Nota: Utilizado quando o método HTTP não é compatível com o recurso/elemento. Por exemplo: POST: /fornecedores/123, nesse caso, não é possível criar um fornecedor em um elemento. Não deverá haver uma configuração de URI recebendo o id.
410: Gone
- Indica que o recurso foi intencionalmente removido e não está mais acessível.
- Métodos: GET, POST *, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota *: Para o POST, temos a mesma situação do 200.
412: Precondition Failed
- Condição prévia dada em um ou mais dos campos avaliada como falsa quando foi testado no servidor.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Utilizado, por exemplo, quando o consumidor da API fez uma requisição com um parâmetro obrigatório vazio etc.
413: Request Entity Too Large
- A solicitação é maior do que o servidor está disposto ou capaz de processar.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Utilizado quando a mensagem passada pelo consumidor da API é maior do que a API está configurada para aceitar.
Exemplo: A API espera que um documento para upload tenho no máximo 1Mb e o envio foi de um documento com tamanho maior.
415: Unsupported Media Type
- Servidor está se recusando a atender o pedido porque a entidade do pedido está em um formato não suportado pelo recurso solicitado.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Utilizado quando o consumidor está passando ou tentando consumir um media type não suportado pela API.
422: Unprocessable Entity
- O pedido foi bem formado, mas não pôde ser seguido devido a erros semânticos.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Utilizado para o caso de algum erro de negócio, por exemplo, tentativa de excluir um recurso associado a outro recurso - relacionamentos.
429: Too Many Requests
- Usuário enviou muitas solicitações em um determinado período de tempo.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Utilizado quando o consumidor da API fez mais requisições do que é permitido para ele ou para a API.
Status Code 5xx
500: Internal Server Error
- Servidor encontrou uma condição inesperada que impediu de cumprir o pedido.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Utilizado em caso de erros inesperados na implementação da API.
502: Bad Gateway
- Servidor, enquanto age como um gateway ou proxy, recebeu uma resposta inválida.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Utilizado em casos de erros inesperados no Gateway de APIs.
503: Service Unavailable
- Indica que o servidor não está pronto para lidar com a solicitação. Geralmente é um estado temporário.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
504: Gateway Timeout
- O servidor, enquanto age como um gateway ou proxy, não recebeu uma resposta do servidor no tempo especificado.
- Métodos: GET, POST, PUT, DELETE, PATCH
- Response body: Padronizado, de acordo com a necessidade.
Nota: Utilizado quando a implemenação da API demorou mais tempo do que era esperado para responder.
Ponderações sobre alguns Status Code
Quando pensamos em API, nos deparamos com algumas possibilidades que não imaginávamos quando lidávamos com o modelo antigo de aplicações web, fosse HTML estático ou aplicações que processam o HTML no servidor, tipo MVC.
No desenvolvimento de APIs, mais de um Status Code pode se apresentar como uma opção válida de retorno em uma requisição.
Vamos ponderar sobre essas possibilidades.
Buscando por recursos: 200 ou 206
Em situações em que uma consulta retorna um volume extremamente grande de dados, surge a necessidade de dividir a entrega desses resultados. Isso é particularmente comum ao lidar com consultas que retornam listas extensas de recursos e que requerem paginação.
É essencial documentar que, para consultas que excedam um determinado número de recursos retornados, serão fornecidas as seguintes informações: o total de recursos correspondentes à consulta, o número de recursos por página, a página atualmente entregue e o total de páginas disponíveis.
Deve-se também deixar claro sob quais condições o retorno terá um Status Code 200 ou 206. Vejamos:
Retorno 200: OK
A consulta gerou uma única página de resultados. Portanto, o retorno de 200 indicará que todos os dados esperados foram entregues.
Retorno 206: Partial Content
Quando uma consulta resultar em duas ou mais páginas, deve-se retornar o status 206. Isso informará ao client que existem mais resultados para a consulta realizada e que ele deve considerar as informações adicionais fornecidas para lidar com a paginação dos resultados.
Buscando por um recurso: 400 ou 404 ou 410
Quando pensamos em API, podemos ter três possibilidades para falha no retorno de consultas a um recurso.
Retorno 400: Bad Request
Consulta de detalhes de um recurso obtido a partir de uma lista de recursos:
Se o usuário está usando a lista recebida em uma consulta anterior, para buscar os detalhes de um recurso específico, então o recurso tem que existir no servidor.
Se o recurso não for localizado no servidor, então podemos retornar um Status Code 400 (bad request), pois podemos encarar como violação, uma tentativa de acessar algum outro recurso que não está na lista. Observação: IDs numéricos e sequenciais facilitam essa violação.
Retorno 404: Not Found Not Found
Consulta de detalhes de um recurso obtido a partir de uma consulta direta:
Se o usuário está usando um formulário para digitar um dado a ser pesquisado no servidor e este não for localizado, então podemos retornar um Status Code 404 (not found), pois podemos entender que realmente não foi encontrado o que o client está procurando.
Exemplo: um formulário para buscar por um CPF, ou um e-mail, ou um título de um documento. Etc.
Retorno 410: Gone
Agora, vamos evoluir a API. Imagine múltiplos usuários e que os recursos não são excluídos fisicamente, mas virtualmente (marcado como excluído).
Imagine que dois usuários receberam uma lista de recursos, em uma consulta anterior. Agora, enquanto o primeiro está analisando os detalhes de algum recurso específico, o segundo já localizou o recurso que deseja excluir e o faz. Se o primeiro usuário tentar acessar os detalhes do recurso que foi excluído, mas que ainda consta em sua lista, o que devemos fazer? Qual o retorno apropriado?
Vai depender do entendimento do negócio. Mas, considerando ser um ambiente multiusuário e que a exclusão é virtual, então devemos dar um retorno semântico e assertivo para a situação, indicando que o recurso existiu, mas foi intencionalmente removido e não está mais acessível. Para isso, devemos retornar o Status Code 410 (gone). Caso contrário, o retorno seria 404. Só que, 404 deixa o primeiro usuário confuso, pois se o recurso estava na lista dele, como pode ter recebido 404?
Só lembrando que no servidor, ao realizar a consulta, devemos nos preocupar com o campo de “excluído”. Se no servidor temos o retorno, mas o campo estiver marcado como “sim” então devemos retornar 410 e se o registro não for encontrado, então devemos retornar 400 – afinal, o usuário está partindo de uma lista recebida anteriormente.
Veremos o 404 a seguir.
Recurso não encontrado: 404
O Status Code 404 (Not Found) nos deixa com uma certa dúvida. O 404 aconteceu porque o recurso não foi encontrado ou porque não existe a configuração para a URI solicitada?
Estamos muito acostumados a receber um 404 quando tentamos acessar uma página que não existe. Só que não resolve trazer essa ideia para uma API, porque não temos uma página, mas sim um recurso.
Temos que partir do princípio de que a API possui uma documentação. Sendo assim, não faz sentido termos um 404 porque a URI não existe.
Mas se quisermos oferecer uma forma do client ter certeza de que o erro é dele, temos duas possiblidades:
- Informar na documentação que o retorno padrão da API é um indicativo. Um simples retorno com Status Code 404 sem corpo.
- Também podemos adicionar um middleware que irá realizar o retorno de uma resposta padronizada – falaremos de resposta padronizada em um próximo artigo.
Na resposta abaixo, perceba a propriedade “succeeded” com valor “false”, indicando que a URI não existe de fato.
1 {
2 "status": 404,
3 "title": "URI inexistente",
4 "succeeded": false,
5 "responseCode": 404999
6 }
Em uma situação normal para 404, quando o recurso não foi localizado, a propriedade “succeeded” tem o valor “true”. Lembrando que a requisição aconteceu com sucesso e que 404 serve para indicar que o recurso não foi localizado.
1 {
2 "status": 404,
3 "title": "Consulta pessoa física",
4 "succeeded": true,
5 "responseCode": 404001,
6 "detail": "A pessoa física informada não foi encontrada na base corporativa."
7 }
Tratando os dados de entrada: 412 ou 400 ou 422
Como já dito anteriormente, parece que só existe o Status Code 400 (bad request) para todo tipo de erro na requisição.
Retorno 412: Precondition Failed
Uma das ocasiões em que vemos isso, é na validação dos dados de entrada. Seja porque o dado é requerido, ou se é um número, ou se o tamanho mínimo ou máximo de caracteres está dentro do esperado, ou se um e-mail, CPF ou CNPJ são válidos, entre outras possibilidades que devemos verificar.
Essa validação é considerada um pré-condição para que o processamento seja iniciado. Se é uma pré-condição, então devemos utilizar o Status Code 412 (precondition failed) e não o 400, como normalmente vemos nesse caso.
Retorno 400: Bad Request
Não estamos querendo dizer que o 400 não pode ser devolvido. Pelo contrário, devemos utilizá-lo adequadamente.
Por exemplo: em uma requisição para obter os usuários para um dado CNPJ, como no CSA, devemos validar o CNPJ no path parameters com o CNPJ existente nas credenciais (token). Neste caso, se os CNPJs forem diferentes, o retorno deve ser um 400.
https://domonio/acessos/{cnpj}/usuarios/
Se, em outras situações, ponderarmos que a intenção na falha da requisição foi intencional, então devemos retornar 400. Cabe ao Arquiteto discutir isso com a equipe de negócio e, também conforme a situação, com a equipe de desenvolvedores.
Retorno 422: Unprocessable Entity
O Status Code 422 indica erros semânticos na entidade. Isto é, já passamos pela validação dos dados: o que é número está dentro do range esperado; o que é strings está dentro do tamanho correto; e-mail no formato válido; datas válidas. Porém, quando se olha para os dados como um todo, representando uma entidade, chega-se na conclusão de que a entidade não está válida.
Exemplo:
- A regra de negócio dita que para ser um cliente, a pessoa precisa ser maior de idade. Apesar da data de nascimento ser uma data válida (pré-condição atendida), quando comparamos com a data do processamento da requisição, percebe-se que a diferença entre esta e a data de nascimento é menor de 18 anos e portando, o cliente não é válido para cadastro. Eis um caso de entidade não processável.
- Entende-se, para um dado negócio, que um carro de luxo deve ser preto, possuir 4 portas, ser sedã e ter o modelo com menos de 2 anos na data de processamento da requisição. No recebimento da requisição, todos os dados indicam que se trata de um carro, porém, se não atender aos requisitos para ser tratado como carro de luxo, então eis mais um caso de entidade não processável.
- Tentar excluir uma entidade relacionada, ou com falhas de relacionamento, também gera uma falha nas regas de negócio e, portanto, o erro 422 deve ser retornado.
Desta forma, temos o 422 para tratar falhas relacionadas as regras de negócio.
No próximo artigo, irei abordar o HATEOAS, e finalmente falar da arquitetura REST.
Até lá.