Mermaid code
flowchart TD
Req[Incoming request] --> RL{Under rate limit?}
RL -- No --> R429[429 Too Many Requests]
RL -- Yes --> Auth{Valid token?}
Auth -- No --> R401[401 Unauthorized]
Auth -- Yes --> Perm{Has permission?}
Perm -- No --> R403[403 Forbidden]
Perm -- Yes --> Val{Body passes schema?}
Val -- No --> R400["400 Bad Request<br/>with field errors"]
Val -- Yes --> H[Handler runs business logic]
H --> Ok{Succeeded?}
Ok -- Yes --> R200[200 or 201 with JSON body]
Ok -- Expected failure --> R422[422 Unprocessable Entity]
Ok -- Unexpected error --> R500[500 Internal Server Error]
R500 --> Log[Log with request id and alert] Paste this into any tool that renders Mermaid, or into the editor to change the theme and export PNG or SVG. Syntax reference: Flowchart guide.
What this diagram shows
The request enters at the top and passes through four decision diamonds in a fixed order: rate limit (429), authentication (401), authorization (403), and request body validation (400). The order matters: rate limiting runs before authentication so unauthenticated floods cost nothing, and authorization runs before validation so a forbidden caller learns nothing about the schema. Only a request that passes all four reaches the Handler, whose outcome splits three ways: success (200 or 201), an expected domain failure (422), or an unexpected exception (500) that is logged with a request id and alerted on.
The TD direction gives the chain a top-to-bottom reading order, and putting every error exit on the right-hand side makes the happy path a straight line down the left.
How to adapt it
- Add a
CORS preflight?diamond at the very top if your API is called from browsers, exiting to a204node. - Insert an
Idempotency key seen?check between validation and the handler for POST endpoints that must be safe to retry, exiting to the cached response. - Replace
422 Unprocessable Entitywith409 Conflictif your expected failures are mostly uniqueness violations. - Attach your actual error body shape to the
400node label, for example{ errors: [{ field, message }] }, so clients know what to parse.
FAQ
Why does validation come after authorization?
Returning validation errors to a caller who is not allowed to use the endpoint leaks the schema. Checking permission first means forbidden callers only ever see 403.
How do I draw the error exits on one side?
Mermaid places nodes automatically, but connecting each No branch to a terminal node with no outgoing edges tends to push them to one side. If the layout drifts, give the diamonds short labels and keep the happy-path edges first in the source.