GUIDE / api
REST API Status Codes: The Complete Reference for Testers
Master REST API status codes with a complete tester cheat sheet for 2xx, 4xx, and 5xx responses, error validation, and practical test design.
If you test backends, REST API status codes are not trivia. They are the first signal every client, monitor, and automated check uses to decide success, retry, auth failure, or server fault. A 200 that hides an error body, a 500 for bad input, or a 401 that should have been 403 will break integrations even when the JSON looks “mostly right.”
This guide is a practical reference for QA engineers. You will get a clear map of status families, a tester-focused HTTP status codes cheat sheet, deep coverage of 2xx, 4xx, and 5xx behavior, REST API error response validation patterns, worked test cases, and the common mistakes that create false confidence in API suites.
Why REST API Status Codes Matter in Testing
HTTP status codes are part of the contract between producer and consumer. The body describes details. The status describes the outcome class.
When status codes are wrong, several layers fail at once:
- Frontend error handling shows the wrong message or no message.
- Mobile clients retry endlessly or never retry when they should.
- API gateways and load balancers route or throttle incorrectly.
- Observability dashboards count failures as successes.
- Contract and integration tests pass for the wrong reason.
A strong API tester does not only assert expect(status).toBe(200). A strong API tester asks whether the status matches the intent of the operation, the authentication state, the resource state, and the agreed API design.
If you are new to API testing as a discipline, start with the broader workflow in the API testing tutorial, then come back here when you design status and error assertions.
The Five Status Code Families
HTTP status codes are three-digit numbers grouped by the first digit.
| Family | Range | Meaning for testers |
|---|---|---|
| 1xx Informational | 100-199 | Interim responses. Rare in ordinary REST CRUD tests. |
| 2xx Success | 200-299 | Request was accepted and completed successfully from the protocol view. |
| 3xx Redirection | 300-399 | Client must take another action, often follow a new location. |
| 4xx Client error | 400-499 | The request is wrong, unauthorized, forbidden, not found, or otherwise rejected as a client problem. |
| 5xx Server error | 500-599 | The server failed to fulfill a seemingly valid request. |
Your default mental model as a tester:
- 2xx: happy path or accepted processing.
- 4xx: the client should change something.
- 5xx: the server or dependency failed; investigate infrastructure, code, or upstream services.
Do not treat status codes as decoration. Treat them as first-class expected results.
REST API Status Codes Cheat Sheet for Testers
Use this table as a day-to-day reference when designing cases.
| Code | Name | Typical API meaning | Tester focus |
|---|---|---|---|
| 200 | OK | Successful GET, PUT, PATCH, or action with a body | Body shape, fields, headers, caching |
| 201 | Created | Resource created, often after POST | Location header, created entity, id stability |
| 202 | Accepted | Async work accepted but not finished | Job id, polling contract, eventual status |
| 204 | No Content | Success with empty body, often DELETE or update | Empty body, no accidental JSON payload |
| 301/302/307/308 | Redirects | Resource moved or temporary redirect | Follow policy, HTTPS, method preservation |
| 400 | Bad Request | Malformed request or generic client error | Parse errors, missing structure, message quality |
| 401 | Unauthorized | Missing or invalid authentication | WWW-Authenticate, token expiry, refresh |
| 403 | Forbidden | Authenticated but not allowed | Role and scope enforcement |
| 404 | Not Found | Resource missing or not visible | Soft delete, tenancy isolation, IDOR risks |
| 405 | Method Not Allowed | HTTP method not supported for resource | Allow header, method matrix |
| 409 | Conflict | State conflict, duplicate, version clash | Concurrency, unique constraints |
| 410 | Gone | Resource permanently removed | Client cache and retry behavior |
| 412 | Precondition Failed | ETag or If-Match failed | Optimistic locking |
| 415 | Unsupported Media Type | Wrong Content-Type | JSON vs form vs multipart |
| 422 | Unprocessable Entity | Semantic validation failure | Field errors, business rules |
| 429 | Too Many Requests | Rate limit exceeded | Retry-After, limit headers |
| 500 | Internal Server Error | Unhandled server failure | No secrets in body, logging, alerts |
| 502 | Bad Gateway | Upstream invalid response | Dependency failures |
| 503 | Service Unavailable | Temporary outage or maintenance | Retry guidance, health endpoints |
| 504 | Gateway Timeout | Upstream timeout | Timeouts and cascading failure |
Print this mentally before every API exploratory session. Then go deeper on the codes your product actually uses.
2xx Status Codes: Success Is Not One Thing
200 OK
200 OK means the request succeeded and the response usually contains a body. Common for GET, PUT, PATCH, and some POST actions that do not create a new resource identity.
Tester checks:
- Status is 200 only when the business operation truly succeeded.
- Response schema matches the contract.
- Important fields are present, typed correctly, and consistent with the database or secondary reads.
- Pagination metadata is correct when listing resources.
- Sensitive fields are redacted for the caller’s role.
Anti-pattern: returning 200 for every response, including validation failure, and putting "error": true in the body. That design forces every client to reimplement status logic.
201 Created
201 Created is the preferred success code after creating a resource. The response should make the new resource discoverable.
Tester checks:
- Status is 201, not 200, when creation is the main outcome.
Locationheader points to the new resource when the API design includes it.- Body includes the created id and key attributes.
- Repeating the same create request behaves as designed: either another 201, a 409 conflict, or an idempotent 200/201 with the same resource.
202 Accepted
202 Accepted means the server accepted work that will finish later. This is common for exports, bulk imports, video processing, or long report generation.
Tester checks:
- Immediate response includes a job id, status URL, or operation id.
- Polling the status endpoint eventually yields success, failure, or timeout states.
- Clients do not treat 202 as final completion.
- Failed async jobs surface a terminal error state rather than hanging forever.
204 No Content
204 No Content means success with no response body. Common for DELETE and some updates.
Tester checks:
- Body is truly empty.
- Clients that always call
.json()do not crash. - DELETE of an already deleted resource returns the designed code: 204, 404, or 410, consistently.
3xx Status Codes: Redirects in API Land
REST APIs use redirects less often than websites, but they still appear with:
- HTTP to HTTPS upgrades.
- Legacy URL migrations.
- CDN or API gateway routing.
- OAuth authorization endpoints.
Tester checks:
- Whether the HTTP client follows redirects automatically.
- Whether auth headers are stripped or preserved across hosts.
- Whether POST becomes GET after some redirects.
- Whether sensitive tokens appear in redirected query strings.
If your suite silently follows redirects, you can miss a breaking URL change. Add at least one test that inspects the first response status and Location header.
4xx Status Codes: Where Most Functional Defects Live
Client error codes are the richest area for QA design because they encode product rules.
400 Bad Request
Use and expect 400 when the request cannot be processed because it is malformed or otherwise invalid as sent.
Examples:
- Body is not valid JSON.
- Required top-level field is missing.
- Query parameter type is wrong.
- Unsupported combination of filters.
Tester focus:
- Message is actionable without leaking internals.
- Invalid requests never partially commit data.
- Consistent mapping: similar defects produce similar codes.
401 Unauthorized
Despite the historical name, 401 is about authentication failure, not authorization.
Expect 401 when:
- No token or credentials are provided.
- Token is expired, malformed, or signed with the wrong key.
- Basic auth credentials are wrong.
- Session cookie is missing or invalid.
Tester checks:
- Protected routes reject anonymous access.
- Expired JWT returns 401, not 500.
- Error body does not reveal whether a username exists if that is a security requirement.
WWW-Authenticateor documented auth error shape is present when required.
Deepen this area with API authentication testing.
403 Forbidden
403 means the server knows who you are and still refuses the action.
Examples:
- Viewer role tries to delete a project.
- Token scope lacks
orders:write. - Tenant A token tries to read Tenant B data and the API chooses 403 instead of 404.
Security note: some teams intentionally return 404 for cross-tenant access to avoid resource enumeration. Others return 403. Both can be valid. The tester’s job is to verify the chosen policy is consistent and documented.
404 Not Found
404 means the target resource is not available to the caller.
Tester checks:
- Unknown ids return 404.
- Soft-deleted resources behave as designed.
- Nested routes such as
/users/{id}/orders/{orderId}validate ownership. - 404 bodies remain safe and consistent.
405 Method Not Allowed
Expect 405 when a resource exists but the method is wrong, such as DELETE /health or PUT /login.
Tester checks:
- Method matrix matches documentation.
Allowheader lists permitted methods when the API provides it.
409 Conflict
409 is powerful for real systems because state conflicts are common.
Examples:
- Creating a user with an email that already exists.
- Updating a stale version with optimistic locking.
- Transitioning an order from
shippedback todraftillegally.
Tester checks:
- Concurrent updates do not corrupt data.
- Conflict responses identify the conflicting constraint without oversharing.
- Clients can recover: fetch latest version, choose a new unique value, or cancel.
415 Unsupported Media Type
Expect 415 when Content-Type is wrong, such as sending XML to a JSON-only endpoint or forgetting multipart boundaries for uploads.
422 Unprocessable Entity
Many modern APIs use 422 when the request is syntactically valid JSON but fails domain validation.
Examples:
- Password too short.
- End date before start date.
- Quantity below minimum order size.
Whether your API uses 400 or 422, pick one rule and test it everywhere. Inconsistency is itself a defect for client authors.
429 Too Many Requests
Rate limits protect systems and fair use policies.
Tester checks:
- Burst traffic eventually returns 429.
Retry-Afteror rate limit headers are present if documented.- Legitimate traffic still succeeds under normal load.
- Auth endpoints are protected against credential stuffing patterns.
5xx Status Codes: Server Failures and Dependency Pain
500 Internal Server Error
500 means an unexpected server-side failure. It should be rare in stable releases.
Tester checks:
- Forcing invalid server conditions does not expose stack traces, SQL, tokens, or file paths.
- Known bad inputs produce 4xx, not 500.
- 500s are logged with correlation ids.
- Health and readiness probes do not report healthy when critical dependencies are down, if that is the design.
502 Bad Gateway and 504 Gateway Timeout
These usually mean a proxy or gateway received an invalid or slow response from an upstream service.
Tester checks:
- Chaos or dependency-down tests produce the expected gateway behavior.
- Timeouts are bounded.
- Partial upstream failures degrade gracefully where required.
503 Service Unavailable
503 often means temporary overload, maintenance, or intentional shedding.
Tester checks:
- Maintenance mode returns 503 with clear messaging.
- Retry guidance exists when appropriate.
- Critical write paths fail safely without partial commits.
REST API Error Response Validation
Status codes alone are not enough. Pair every important status with body and header checks.
A useful error response often includes:
{
"error": {
"code": "VALIDATION_FAILED",
"message": "Quantity must be at least 1.",
"details": [
{
"field": "quantity",
"issue": "min",
"provided": 0
}
],
"requestId": "req_8f2c1a"
}
}
Validation checklist:
- Status code matches the failure class.
Content-Typeis the documented error media type.- Machine-readable
codeis stable for clients. - Human message is clear and non-leaky.
- Field-level details exist for validation failures.
requestIdor correlation id is present for support.- No stack traces, secrets, hostnames, or raw SQL.
- Localization rules are respected if the product supports them.
For Postman-based execution and scripting patterns, see the Postman tutorial.
Designing Test Cases Around Status Codes
Do not write one giant “status code test.” Write intent-based cases that use status codes as expected results.
Example: Create Order API
| Case | Setup | Request | Expected status | Extra assertions |
|---|---|---|---|---|
| Happy create | Valid buyer token, in-stock SKU | POST valid order | 201 | Body has order id, Location optional |
| Missing auth | No token | POST valid order | 401 | No order created |
| Wrong role | Viewer token | POST valid order | 403 | No order created |
| Unknown SKU | Valid token | POST unknown sku | 404 or 422 | Error code stable |
| Quantity 0 | Valid token | POST quantity 0 | 400 or 422 | Field error on quantity |
| Duplicate idempotency key | Same key twice | POST same payload | 200/201 consistent | Same order id returned |
| Stock race | Last item reserved | Concurrent POSTs | one 201, one 409/422 | Inventory never negative |
| Server forced fault | Dependency down | POST valid order | 503/502/500 as designed | Safe error body |
This table forces the suite to cover auth, validation, conflict, and dependency classes instead of only the happy path.
Method and Status Expectations
Different methods have different common success codes.
| Method | Common success | Common failure codes |
|---|---|---|
| GET | 200 | 401, 403, 404, 429, 500 |
| POST create | 201 or 200 | 400, 401, 403, 409, 422 |
| POST action | 200 or 202 | 400, 401, 403, 409, 422 |
| PUT | 200 or 204 | 400, 401, 403, 404, 412, 422 |
| PATCH | 200 or 204 | 400, 401, 403, 404, 412, 422 |
| DELETE | 200, 204, or 404/410 policy | 401, 403, 404, 409 |
Document the policy your API chose, then test for consistency across resources.
Idempotency and Status Codes
Idempotency changes what status codes are acceptable on retries.
Examples:
- DELETE of an existing resource returns 204. DELETE again returns 204 or 404, depending on design.
- PUT of the same representation twice should not create duplicates.
- POST with an idempotency key should not create two charges.
Tester rule: for every non-safe method that can be retried by clients or gateways, define the second-call status and body. Then automate both first and second calls.
Caching Headers and Status Codes
Status codes interact with caching.
- 200 responses may include
ETag,Cache-Control, orLast-Modified. - Conditional requests may return 304 Not Modified.
- Error responses are often non-cacheable and should say so when needed.
Tester checks:
- Unauthorized responses are not cached as public content.
- 304 clients still have a usable local representation.
- Stale error pages are not served as success.
GraphQL and Status Codes: A Short Contrast
GraphQL often returns HTTP 200 even when the operation contains errors in the errors array. That difference confuses REST-trained testers.
For GraphQL-specific validation of queries, mutations, schema, and errors, use the dedicated guide on how to test GraphQL APIs. Keep REST status semantics for REST endpoints, and do not force GraphQL into a pure REST status model unless your gateway deliberately does so.
Observability: What Status Codes Should Trigger
Status codes are product signals and operational signals.
| Status pattern | Likely action |
|---|---|
| Spike in 401 | Auth outage, bad client deploy, expired secrets |
| Spike in 403 | Permission bug or role misconfiguration |
| Spike in 404 | Bad release links, client bug, data migration issue |
| Spike in 429 | Abuse, missing backoff, too-low limits |
| Spike in 5xx | Regression, dependency failure, capacity problem |
As a tester, include at least one release check that compares status code rates before and after deploy in non-prod or canary environments.
Sample Automated Assertions
Here is a concise pattern many API suites use:
// Example using a generic HTTP client style
const res = await api.post("/orders", {
headers: { Authorization: `Bearer ${buyerToken}` },
body: { sku: "SKU-1", quantity: 1 },
});
expect(res.status).toBe(201);
expect(res.headers["content-type"]).toMatch(/application\/json/);
expect(res.data.id).toMatch(/^ord_/);
expect(res.data.status).toBe("created");
// Negative: missing token
const anon = await api.post("/orders", {
body: { sku: "SKU-1", quantity: 1 },
});
expect(anon.status).toBe(401);
expect(anon.data.error.code).toBe("UNAUTHENTICATED");
expect(JSON.stringify(anon.data)).not.toMatch(/stack|password|secret/i);
Notice the assertions cover status, headers, business fields, and safety of the error payload.
Common Mistakes With REST API Status Codes
Mistake 1: Asserting Only the Happy Path Status
A suite that only checks 200/201 will miss auth holes, validation gaps, and conflict bugs. Add negative and state-based cases early.
Mistake 2: Treating All 4xx as Equivalent
401, 403, 404, and 422 imply different client fixes. Collapsing them into “client error” loses diagnostic value and weakens contract tests.
Mistake 3: Returning 500 for Bad Input
If a missing field crashes the server, that is a defect. Invalid client input should usually become a controlled 4xx response.
Mistake 4: Success Status With Failure Body
200 OK plus "success": false breaks standard HTTP tooling. Prefer correct status families.
Mistake 5: Inconsistent Codes Across Similar Endpoints
If /users returns 422 for validation and /orders returns 400 for the same class of problem, client authors will need special cases forever. Consistency is a quality attribute.
Mistake 6: Leaky 5xx Bodies
Stack traces, internal hostnames, and SQL fragments in 500 responses are security and reliability issues. Assert their absence.
Mistake 7: Ignoring Rate Limits and Async Codes
Teams often forget 202 and 429 until production traffic hits them. Include at least smoke coverage for async acceptance and throttling if those features exist.
Mistake 8: No Correlation Between Status and Side Effects
A 201 must create. A 4xx must not create. A failed payment should not leave an order marked paid. Always verify side effects, not only the status line.
Practical Testing Workflow
Use this workflow when a new endpoint lands:
- Read the OpenAPI or docs for declared status codes.
- List success codes by method.
- List auth failure, permission failure, not found, validation, and conflict cases.
- Map each case to an expected status and body shape.
- Add side-effect checks for writes.
- Add safety checks for error payloads.
- Automate the stable high-value cases.
- Exploratory-test weird combinations: duplicate headers, wrong Accept, stale ETags, replayed requests.
- Compare observed codes with monitoring dashboards in lower environments.
For deliberate practice, open a QABattle API challenge in the battle arena and score yourself on whether you predicted the correct status family before you saw the response.
Status Codes in Contract Testing
Consumer-driven contracts should include status expectations, not only payload shapes. A consumer that expects 201 and receives 200 may still parse the body and then fail in production edge paths.
When services evolve independently, contract tests catch status drift early. If your architecture is moving toward microservices, pair this reference with contract testing with Pact.
Interview and Review Language You Can Reuse
When reviewing an API design or answering interview questions, use precise phrases:
- “401 means authentication failed. 403 means authorization failed.”
- “I validate status, body schema, headers, and side effects together.”
- “Invalid input should not become 500.”
- “Idempotent retries need an explicit second-response policy.”
- “Error bodies need stable machine codes and safe human messages.”
That language signals senior API testing judgment.
Checklist: REST API Status Codes Before Release
- Documented status codes match implemented behavior.
- Happy path uses the correct 2xx code for the method.
- Missing auth returns 401 on protected routes.
- Wrong role or scope returns 403 or the documented isolation code.
- Unknown resources return 404 or 410 as designed.
- Validation failures return 400 or 422 consistently.
- Conflicts return 409 where state clashes are possible.
- Rate limits return 429 with retry guidance when applicable.
- Async accepts return 202 with a status tracking mechanism.
- 5xx responses never leak secrets or stack traces.
- Write failures do not partially commit critical data.
- Monitoring alerts exist for abnormal 4xx and 5xx rates.
Final Takeaways
REST API status codes are a shared language for product behavior under success and failure. Testers who master them find higher severity defects faster because they can spot semantic mismatches, not only schema mismatches.
Remember the core rules:
- Status family must match outcome class.
- Body and headers must support the status.
- Side effects must agree with success or failure.
- Consistency across endpoints is part of quality.
- Safety matters as much as correctness for error responses.
Use this reference while designing cases, reviewing OpenAPI files, writing automation, and triaging production incidents. When the status line tells the truth, every client above the API becomes easier to build, test, and trust.
If you want structured practice across API scenarios, create an account on QABattle sign-up and work through API track battles that force you to justify expected codes before you run the request.
FAQ
Questions testers ask
What are the most common HTTP status codes?
The most common HTTP status codes testers meet are 200 OK, 201 Created, 204 No Content, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 422 Unprocessable Entity, 429 Too Many Requests, 500 Internal Server Error, and 503 Service Unavailable. Learn the meaning of each family, then verify the body and headers with the status.
What is the difference between 401 and 403?
401 Unauthorized means the request lacks valid authentication, so the client should sign in or send a valid token. 403 Forbidden means the server understood the identity but refuses the action, usually because of permissions, roles, or policy. 401 is about who you are. 403 is about what you are allowed to do.
When should an API return 400 vs 422?
400 Bad Request usually means the request is malformed: invalid JSON, wrong types, missing required structure, or a client message the server cannot parse. 422 Unprocessable Entity is often used when syntax is valid but business validation fails, such as an email already registered or a date in the past. Many APIs still map both cases to 400, so test against the actual contract.
What is the difference between 404 and 410?
404 Not Found means the resource does not exist or is not visible to the caller. 410 Gone means the resource used to exist and has been permanently removed. Use 410 when clients should stop requesting the URL. Use 404 when the resource is missing, hidden, or never existed.
Should failed validation return 200 with an error body?
No. Successful HTTP status codes should not carry business failure. Returning 200 with {"success": false} hides failures from clients, monitors, and automated tests that trust status families. Prefer a 4xx status plus a structured error body. If a legacy API still returns 200 for failures, document that behavior and assert both status and payload.
How should testers validate REST API error responses?
Validate the status code, Content-Type, error code or type, human-readable message, field-level details when relevant, correlation or request IDs, and absence of stack traces or secrets. Then check that retries, logging, and client handling behave correctly for that status family.
RELATED GUIDES
Continue the route
API Testing Tutorial: A Beginner's Complete Guide
API testing tutorial for beginners: learn REST API checks, CRUD test cases, tools, status codes, and a practical checklist for reliable API quality.
Postman Tutorial: UI, Collections, Environments, and Tests
Postman tutorial for beginners: learn the Postman UI, collections, environments, variables, Tests tab, pre-request scripts, Collection Runner, and Newman.
How to Test GraphQL APIs
Learn how to test GraphQL APIs: queries, mutations, schema validation, error handling, Postman tips, subscriptions, and introspection risks.
API Authentication Testing: OAuth, JWT, and API Keys
Learn API authentication testing for OAuth 2.0, JWT expiry and refresh flows, API keys vs bearer tokens, and broken authentication test cases.