Uma resposta 500 para input inválido é sempre um bug: o servidor deveria retornar 4xx, não travar. Um 403 ausente é um bypass de autorização. Se um usuário comum acessa um endpoint de admin e recebe 200 em vez de 403, o controle de acesso não está funcionando.
Como os status codes são organizados
Os status codes HTTP são números de três dígitos organizados em cinco classes:
| Faixa | Classe | Significado |
|-------|--------|-------------|
| 1xx | Informativo | Requisição recebida, processamento em andamento |
| 2xx | Sucesso | Requisição concluída com êxito |
| 3xx | Redirecionamento | O cliente precisa tomar outra ação (geralmente seguir o redirect) |
| 4xx | Erro do cliente | A requisição tem um problema: o cliente enviou algo errado |
| 5xx | Erro do servidor | A requisição era válida: o servidor falhou em processá-la |
O primeiro dígito diz a categoria. 4xx = sua requisição estava errada. 5xx = o servidor quebrou.
2xx: códigos de sucesso
200 OK
O código de sucesso mais comum. A requisição funcionou e há conteúdo na resposta.
Usado para:- Requisições
GETque retornam dados - Requisições
POSTque não criam um novo recurso (como uma busca) - Atualizações via
PUT/PATCH
- O corpo da resposta contém os dados esperados
- A resposta está no formato correto (JSON, XML)
- Os campos obrigatórios estão presentes
201 Created
Um recurso foi criado com sucesso. Deve ser retornado para requisições POST que criam novos itens.
- A resposta inclui o recurso criado com seu novo ID
- O header Location frequentemente aponta para a URL do novo recurso
POST /users→201com{ id: 123, email: "...", ... }
200 em vez de 201 para endpoints de criação. Tecnicamente funciona, mas está semanticamente errado e pode confundir os consumidores da API.
204 No Content
Sucesso, mas nada a retornar. Usado para requisições DELETE e algumas respostas de PUT/PATCH.
- O corpo da resposta está vazio (algumas APIs retornam corpo incorretamente com 204)
- O recurso foi de fato deletado (faça um
GETpara confirmar)
206 Partial Content
Retornado quando apenas parte de um recurso é enviada (downloads em partes, streaming de vídeo). Relevante principalmente para testar downloads de arquivo e streaming de mídia.
3xx: códigos de redirecionamento
301 Moved Permanently
O recurso foi movido permanentemente para uma nova URL. Buscadores atualizam seus índices para 301.
Relevância para testes: verifique se URLs antigas redirecionam corretamente, se redirects de HTTP para HTTPS são 301 (não 302), e se os destinos dos redirects carregam corretamente.302 Found (Redirect Temporário)
O recurso está temporariamente em outra URL. Usado para redirects de login ("vá aqui agora, a URL original ainda é válida").
304 Not Modified
O cliente tem uma versão em cache e ela ainda é atual: nenhum conteúdo é enviado, use o cache. Você vai ver isso na aba Network do navegador para assets estáticos.
Relevância para testes: se você está testando comportamento de cache,304 significa que o cache está funcionando. Se você está vendo 304 para dados que deveriam ter mudado, há um bug de cache.
4xx: códigos de erro do cliente
Esses significam que a sua requisição tinha um problema: dados ruins, auth ausente, URL errada.
400 Bad Request
O servidor não conseguiu entender a requisição. Geralmente significa sintaxe malformada, JSON inválido ou erro de validação.
Quando você deve ver 400:- JSON inválido no corpo da requisição
- Header obrigatório ausente
- URL malformada
- Retorna mensagem de erro útil explicando o problema
- Não revela detalhes internos (stack traces)
- Retorna 400, não 500 (500 para input inválido é um bug do servidor)
401 Unauthorized
A requisição não tem credenciais de autenticação válidas. "Você não está logado" ou "seu token expirou."
Diferença do 403: 401 = não autenticado (quem é você?). 403 = autenticado mas sem permissão (sei quem você é, mas você não pode fazer isso). O que testar:- Requisição sem token algum → 401
- Requisição com token expirado → 401
- Requisição com token inválido ou forjado → 401
- A resposta de erro não revela informações sobre tokens válidos
403 Forbidden
Autenticado, mas sem permissão. "Você está logado, mas não tem autorização para isso."
O que testar:- Usuário comum acessando endpoint de admin → 403
- Usuário acessando dados privados de outro usuário → 403
- A resposta não expõe nenhum dado que o usuário não deveria ver
404 Not Found
O recurso solicitado não existe naquela URL.
O que testar:- Solicitar um recurso deletado → 404
- Solicitar com um ID que nunca foi criado → 404
- Para recursos sensíveis, não deve revelar se o recurso existe (contas de usuário: retornar 404 "user not found" vs 403 "forbidden" pode revelar a existência da conta)
- É 404 ou 410? (410 = deletado permanentemente, algumas APIs fazem essa distinção)
405 Method Not Allowed
Você usou o método HTTP errado. GET em um endpoint que só aceita POST.
DELETE /users quando só deveria aceitar GET. Deve retornar 405, não 500 ou falha silenciosa.
409 Conflict
A requisição conflita com o estado atual do recurso.
Usos comuns:- Criar um usuário com e-mail que já existe
- Editar um recurso que outra pessoa bloqueou
- Conflito de versão (optimistic locking)
- Criação duplicada → 409 (não 200 ou 500)
- A resposta explica o conflito com clareza
422 Unprocessable Entity
O JSON da requisição é sintaticamente válido, mas semanticamente errado: a validação falhou.
Exemplo: corpo JSON válido, masage: -5 viola a regra de que a idade deve ser positiva.
400 vs 422:
400= não consegue nem interpretar a requisição (JSON ruim, Content-Type errado)422= interpretou, mas os valores falham na validação
Muitas APIs usam 400 para os dois casos. O que importa é consistência: escolha um e use corretamente em toda a API.
O que testar:- Cada campo obrigatório ausente → 422 com o nome do campo específico no erro
- Valores fora do range válido → 422
- Violações de regras de negócio → 422
429 Too Many Requests
Rate limiting: você enviou requisições demais em tempo curto demais.
O que testar:- Confirmar que headers de rate limit são retornados (
X-RateLimit-Limit,X-RateLimit-Remaining,Retry-After) - Após atingir o limite, requisições são rejeitadas
- Após a janela expirar, requisições voltam a funcionar
5xx: códigos de erro do servidor
Esses são sempre bugs. A requisição era válida: o servidor falhou em processá-la.
500 Internal Server Error
Crash genérico do servidor. Algo inesperado aconteceu.
Em testes: se você consegue reproduzir um 500 de forma confiável, é um bug, mesmo que o input fosse intencionalmente inválido. Bom design de API significa que input inválido retorna 4xx, não 500. O que testar:- Input inválido nunca deve produzir 500: deve produzir 400/422
- Campos opcionais nulos ou ausentes não devem produzir 500
- Dados de edge case (arrays vazios, strings muito longas) não devem produzir 500
502 Bad Gateway
O servidor estava atuando como gateway/proxy e recebeu uma resposta ruim de um servidor upstream. Geralmente significa que uma dependência está fora.
503 Service Unavailable
O servidor está temporariamente indisponível: sobrecarregado ou em manutenção.
Relevância para testes: verifique como o frontend trata o 503. Mostra uma página de erro útil? Tenta novamente de forma inteligente? Degrada graciosamente?504 Gateway Timeout
Similar ao 502: um gateway expirou aguardando por um servidor upstream. Aparece com frequência sob alta carga ou quando um serviço de terceiro está lento.
Tabela de referência rápida
| Código | Significado | Causa comum em bugs |
|--------|-------------|---------------------|
| 200 | OK | Retornado para criações que deveriam ser 201 |
| 201 | Created | Ausente: API retorna 200 para POST |
| 204 | No Content | Corpo retornado quando não deveria |
| 301 | Redirect Permanente | Tipo errado de redirect |
| 304 | Not Modified | Cache stale exibindo dados desatualizados |
| 400 | Bad Request | Retornado para input válido-mas-errado (deveria ser 422) |
| 401 | Unauthorized | Ausente: vulnerabilidade de bypass de autenticação |
| 403 | Forbidden | Ausente: vulnerabilidade de bypass de autorização |
| 404 | Not Found | 500 retornado para recursos ausentes |
| 409 | Conflict | Ausente: duplicatas criadas silenciosamente |
| 422 | Unprocessable Entity | Confundido com 400 |
| 429 | Too Many Requests | Ausente: força bruta possível |
| 500 | Internal Server Error | Disparado por input inválido (deveria ser 4xx) |
| 503 | Service Unavailable | Sem degradação graciosa no frontend |
Testando status codes com Playwright
test('criar usuário retorna 201', async ({ request }) => {
const response = await request.post('/api/users', {
data: { email: 'novo@teste.com', password: 'SenhaValida1' },
});
expect(response.status()).toBe(201);
});
test('e-mail duplicado retorna 409', async ({ request }) => {
// Criar usuário primeiro
await request.post('/api/users', {
data: { email: 'existente@teste.com', password: 'SenhaValida1' },
});
// Tentar novamente com o mesmo e-mail
const response = await request.post('/api/users', {
data: { email: 'existente@teste.com', password: 'SenhaValida1' },
});
expect(response.status()).toBe(409);
});
test('token ausente retorna 401', async ({ request }) => {
const response = await request.get('/api/profile');
expect(response.status()).toBe(401);
});
test('perfil errado retorna 403', async ({ request }) => {
// Usar token de membro, tentar acessar endpoint de admin
const response = await request.get('/api/admin/users', {
headers: { Authorization: `Bearer ${memberToken}` },
});
expect(response.status()).toBe(403);
});Assertions de status code são os testes de API mais rápidos e confiáveis que você pode escrever. Rodam em milissegundos e capturam bugs de autorização, validação ausente e design incorreto de API.
→ Veja também: Testes de API 101: Tudo que Todo Engenheiro QA Precisa Saber em 2026 | O que é uma API REST? Um Guia Prático para Engenheiros QA | Testes de API com Playwright: Além da Interface | Autenticação em Testes de API: Chaves API, Tokens Bearer, OAuth2, JWT