Mobile API Best Practices · Designing APIs for Mobile Clients
Errors Mobile Clients Can Act On
Stable machine-readable codes, localized messages and retry hints.
A mobile app needs to decide what to do with an error: retry, re-authenticate, show a field error, ask the user to update, or give up. Use RFC 9457 problem details with a stable type/code the app branches on, field-level errors for forms, a retryable hint or Retry-After, and a request ID users can quote to support. Keep user-facing text localizable: either the server localizes via Accept-Language or the app maps codes to its own strings (safer for old versions, which keep their mapping).
Error → client action
| Error | Status | Client action |
|---|---|---|
| Validation | 422 + errors[] | Highlight fields; no retry |
| Access token expired | 401 + invalid_token | Refresh once, replay request |
| Refresh token invalid | 401 | Log out, show sign-in |
| Rate limited / overloaded | 429 / 503 + Retry-After | Wait, then retry |
| Version unsupported | 426 + upgrade-required | Show upgrade screen |
| Conflict / stale version | 409 / 412 | Fetch latest, rebase or ask user |
| Server bug | 500 + request id | Generic message; report with request id |
HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json
X-Request-Id: req_7Hq2…
{
"type": "https://api.example.com/problems/validation",
"title": "Some fields are invalid",
"status": 422,
"errors": [{"pointer": "/delivery/postcode", "code": "postcode_invalid"}],
"request_id": "req_7Hq2…"
}
when (problem.type.substringAfterLast('/')) {
"validation" -> showFieldErrors(problem.errors)
"upgrade-required" -> navigateToUpgrade()
"rate-limited" -> scheduleRetry(problem.retryAfter)
else -> showGeneric(problem.requestId) // unknown codes: safe fallback
}
Common pitfalls
- Apps parsing English error messages.
- Changing error codes between releases.
- 200 OK with an error body.
Key points
- Stable codes, not messages
- Field-level errors + request IDs
- Unknown code → safe fallback
Further reading: RFC 9457: Problem Details for HTTP APIs
Practice questions
Why should apps branch on error codes rather than messages?
Answer
Messages change and get localized; codes are a stable contract that old app versions can keep relying on.
How should a mobile client handle a 401 for an expired access token?
Answer
Refresh the token once (serializing concurrent refreshes) and replay the original request; if refresh fails, sign the user out.
Open in the app to mark lessons complete, take notes and track your progress.