Skip to content
APIs3 min read

HTTP Status Codes Cheatsheet: What to Return & When

Developer HTTP status code reference: 2xx, 3xx, 4xx, 5xx meanings, when to return each code, and REST API error-handling best practices.

By IvyIvy TeamPublished Updated
#http#rest#api#status-codes#backend

2xx — Success

CodeMeaningReturn when
200 OKStandard successGET / PUT / PATCH succeeded
201 CreatedResource createdPOST created something; include Location header
202 AcceptedQueuedAsync job started (webhook, export)
204 No ContentSuccess, empty bodyDELETE succeeded, or toggle with nothing to return
HTTP/1.1 201 Created
Location: /api/users/42
Content-Type: application/json

{ "id": 42, "email": "ada@example.com" }

3xx — Redirection

CodeMeaningNote
301Permanent redirectUse for canonical moves (/blog → /cheatsheets)
302 / 307Temporary redirect307 preserves method; 302 may switch POST→GET
304Not ModifiedWith ETag / If-None-Match caching

4xx — Client Errors

CodeMeaningReturn when
400Bad RequestMalformed JSON, validation failed
401UnauthorizedMissing/invalid credentials — client must auth
403ForbiddenAuthenticated but not allowed (admin-only)
404Not FoundUnknown route or hidden existence
405Method Not AllowedPOST on a read-only route
409ConflictDuplicate email, version mismatch
422Unprocessable EntityWell-formed but semantically wrong (Laravel/Rails style)
429Too Many RequestsRate limit hit — include Retry-After
// Consistent error shape clients can rely on
return Response.json(
  {
    error: {
      code: 'VALIDATION_ERROR',
      message: 'Email is already registered.',
      fields: { email: ['taken'] },
    },
  },
  { status: 409 }
);

5xx — Server Errors

CodeMeaning
500Unexpected failure — log with request ID, never leak stack traces
502Upstream dependency failed (proxy/gateway)
503Temporarily unavailable — include Retry-After during deploys
504Upstream timed out

Best Practices

  1. 401 vs 403: unauthenticated → 401; authenticated but unauthorized → 403.
  2. 404 vs 403 on private resources: return 404 if the caller should not learn the resource exists.
  3. Always include a machine-readable code (RATE_LIMITED, PLAN_LIMIT) alongside the HTTP status.
  4. Cache correctly: GET responses may be cached; POST/PATCH must not be cached by default.
  5. Document every code you return — an undocumented 418 is a bug report waiting to happen.

Quick Debug Reference (cURL)

curl -i https://ivyivy.com/cheatsheets/git-commands/
curl -s -o /dev/null -w "%{http_code}\n" https://tools.ivyivy.com/health