# Request/Response Pattern

<small>Written by Rohman Beny Riyanto</small>

Every endpoint on this API follows the same shape, and this page explains
why - useful if you're wondering why a request body always looks like
`{"command"/"query": "...", "data": {...}}` instead of just posting fields
directly.

This whole reference site is itself generated from the live API's own
description of its endpoints - it's read directly off the server, not
hand-written and kept in sync manually. That's why every field you see on
an [API Reference](/api/auth) page (path, method, auth requirement,
permission, validation rules) is guaranteed to match what the server
actually enforces: there's no separate "docs" to fall out of date.

## Commands vs. queries

Every endpoint is one of two kinds, kept deliberately separate:

- **Command** - anything that changes state: create, update, delete,
  login, grant a permission, etc. The request body wraps its payload as
  `{"command": "<name>", "data": {...}}`.
- **Query** - anything that only reads state, and can support pagination.
  The request body wraps its payload as `{"query": "<name>", "data": {...}}`.

The server checks that the `command`/`query` name in the body matches the
endpoint you're actually calling, so a request can't accidentally be
processed as if it were a different operation.

A handful of endpoints don't take a `data` payload at all (nothing to
send beyond the wrapper, or nothing to send at all) - each endpoint's own
**Request fields** table on its [API Reference](/api/auth) page tells you
whether this applies to it.

## Auth runs before permission checks, always

For any endpoint that needs both, the order is fixed: your token is
validated and identified first, and only then is the specific permission
check evaluated. A permission check never runs against a request that
hasn't already been authenticated - so a `403` (permission denied) always
implies the token itself was valid; if the token were the problem you'd
get a `401`/`423` instead. See
[FE Auth Error Handling](/guide/auth-error-handling) for the full
breakdown of which failure produces which code.

```mermaid
flowchart LR
    A[Request] --> B["Auth check\n(is this a valid, non-expired token\nof the right account type?)"]
    B -- fails --> B1["401 / 423"]
    B -- passes --> C{"Does this endpoint\nrequire a specific permission?"}
    C -- yes --> D["Permission check\n(does this account hold it?)"]
    C -- no --> F[Handler runs]
    D -- fails --> D1["403"]
    D -- passes --> F
    F --> G[Response]
```
