Core answer: Route every API error by status code — 4xx means the client side (401 unauthenticated, 403 forbidden, 429 too many requests), 5xx means the server side (502 upstream down, 503 overloaded, 504 timeout). Decode a failing JWT locally and read exp first. A 99.9% SLA equals 43.8 minutes of downtime per month.

Status code decision tree

  1. 4xx? The request side: parameters, auth, permissions, rate
  2. 5xx? The service side: check the status page before retrying
  3. No status code (CORS/network)? The request never arrived or the browser blocked the response — read the console, the API itself may be fine

High-frequency codes table

CodeMeaningFirst move
400Malformed requestCheck field types against the docs
401Not authenticatedToken expired or missing
403No permissionCheck scope/role/IP whitelist
404Path not foundCheck URL spelling and version prefix
429Rate limitedExponential backoff; read Retry-After
500Server exceptionReport with the trace id
502Upstream downCheck upstream process liveness
504Gateway timeoutSlow queries / timeout config

Search all 26 codes with the [HTTP status lookup](/c/dev/http-status).

JWT structure and expiry

A JWT is xxxxx.yyyyy.zzzzz, three Base64URL segments: header (algorithm), payload (claims — exp/iat/nbf as Unix seconds), signature. Paste a token into the [JWT decoder](/c/dev/jwt) to read header and payload locally; exp converts to local time with a live countdown. Decoding is not verifying — anyone can read a payload, so never put sensitive data inside a JWT.

SLA downtime budget table

SLAPer yearPer monthTypical use
99%3.65 days7.3 hInternal tools
99.9%8.77 h43.8 minGeneral commercial
99.95%4.38 h21.9 minE-commerce
99.99%52.6 min4.38 minPayments
99.999%5.26 min26.3 sCarrier grade

Each extra nine cuts the budget by 10× and multiplies architecture cost — multi-region active-active is the entry ticket to 99.99%.

Example: five steps for a 502

curl https://api.example.com/pay returns 502: ① retry from another network — still 502; ② check the status page — nothing posted; ③ curl -v shows an nginx server header — the gateway is alive, the upstream is down; ④ ss -lptn on the gateway — the upstream port is not listening, the app crashed; ⑤ the app log ends with OOM killed — restart, cap memory, add alerting.

Example: hunting a JWT 401

Front end gets 401 from /api/orders: ① decode the token — exp was 2 hours ago, expired; ② why did refresh not fire? The refresh call also 401s; ③ the refresh token decodes fine → inspect the request header → Authorization was concatenated without the space after "Bearer". Tools used: JWT decoder for time, [URL parser](/c/dev/url-parser) for query parameters, status lookup for 401 vs 403 semantics.

Common mistakes

  • Using 401 as 403: 401 = "who are you" (missing/expired credentials), 403 = "I know you, and no". Mixing them breaks front-end login redirects.
  • Retrying 5xx without backoff: blind retries during an outage are a self-DDoS. Use exponential backoff with jitter and a circuit breaker.
  • Storing personal data in JWT: the payload is only Base64 — readable by anyone. A JWT is not an encryption container.
  • Promising four nines casually: 99.99% is 52 minutes per year; one careless restart can spend the whole budget.