# Auth - X-Radius API

> Base URL: https://x-radius.com/api/v1
> Auth: Authorization: Bearer xrt_...  (a manager API token)
> Envelope: {"data": ...}; lists add {"meta":{page,page_size,total,has_next}}
> Errors: {"error":{"code","message","request_id"}} - branch on code, never on message
> Timestamps: yyyy-MM-dd HH:mm:ss, UTC
> Money: a bare JSON number in major units, with an ISO-4217 currency code beside it
> Idempotency: redeem and activate endpoints take a client-supplied request_id (UUID)
>
> This page: https://x-radius.com/docs/api/auth
> Every group: https://x-radius.com/llms.txt

24 endpoints in 1 resource groups. 5 carry a hand-written reference entry with examples; the remaining 19 are generated from the running router and carry method, path, authentication, permission and rate-limit bucket, but no request or response example.

### GET /api/v1/auth/account

`GET /api/v1/auth/account`

- Authentication: manager session (JWT) or API token
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### PATCH /api/v1/auth/account

`PATCH /api/v1/auth/account`

- Authentication: manager session (JWT) or API token
- Rate limit bucket: `t_mutate`
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### POST /api/v1/auth/account/2fa/disable

`POST /api/v1/auth/account/2fa/disable`

- Authentication: manager session (JWT) or API token
- Rate limit bucket: `account_reauth`
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### POST /api/v1/auth/account/2fa/enable

`POST /api/v1/auth/account/2fa/enable`

- Authentication: manager session (JWT) or API token
- Rate limit bucket: `t_mutate`
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### POST /api/v1/auth/account/2fa/recovery-codes

`POST /api/v1/auth/account/2fa/recovery-codes`

- Authentication: manager session (JWT) or API token
- Rate limit bucket: `account_reauth`
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### POST /api/v1/auth/account/2fa/setup

`POST /api/v1/auth/account/2fa/setup`

- Authentication: manager session (JWT) or API token
- Rate limit bucket: `t_mutate`
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### POST /api/v1/auth/account/avatar

`POST /api/v1/auth/account/avatar`

- Authentication: manager session (JWT) or API token
- Rate limit bucket: `t_mutate`
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### GET /api/v1/auth/account/limits

`GET /api/v1/auth/account/limits`

- Authentication: manager session (JWT) or API token
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### POST /api/v1/auth/account/password

`POST /api/v1/auth/account/password`

- Authentication: manager session (JWT) or API token
- Rate limit bucket: `account_reauth`
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### GET /api/v1/auth/account/sessions

`GET /api/v1/auth/account/sessions`

- Authentication: manager session (JWT) or API token
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### POST /api/v1/auth/account/sessions/revoke-others

`POST /api/v1/auth/account/sessions/revoke-others`

- Authentication: manager session (JWT) or API token
- Rate limit bucket: `t_mutate`
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### DELETE /api/v1/auth/account/sessions/{jti}

`DELETE /api/v1/auth/account/sessions/{jti}`

- Authentication: manager session (JWT) or API token
- Rate limit bucket: `t_mutate`
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### Classify the host before signing in

`GET /api/v1/auth/context`

Tells a login page which flow to render: whether the host it was loaded on is a tenant subdomain, the instance apex, or unknown, plus the public tenant descriptor when it resolves. Unauthenticated, and always 200. It exposes only the public tenant slug, name and branding, and tenant is null for apex and unknown hosts.

- Authentication: none


### POST /api/v1/auth/impersonation/exit

`POST /api/v1/auth/impersonation/exit`

- Authentication: manager session (JWT) or API token
- Rate limit bucket: `t_mutate`
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### Sign a manager in

`POST /api/v1/auth/login`

Exchanges an email or username and a password for a tenant-scoped session token. The tenant is taken from the host when you call a tenant subdomain, and a selector in the body is discarded in that case.

- Authentication: none
- Rate limit bucket: `login`

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `email` | body | string | yes | Email or username. |
| `password` | body | string | yes | The manager's password. |
| `totp_code` | body | string | no | Six-digit code or a recovery code. Sent on the second attempt, after the first returns mfa_required. |
| `tenant_slug` | body | string | no | Honoured only when the host carries no tenant. Ignored outright on a tenant subdomain. |
| `refresh` | body | boolean | no | Opt in to the refresh-token flow. Omitting it returns one long-lived token and no refresh fields at all. |

#### Request

```json
{
  "email": "ops@acme.example",
  "password": "a-strong-password"
}
```

#### Response — 200 OK

```json
{
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "user_id": 41,
    "tenant_id": 12,
    "tenant_slug": "acme",
    "roles": ["support"],
    "expires_at": 1758358800
  }
}
```

#### Errors

| Code | Status | When |
| --- | --- | --- |
| `ERR_VALIDATION` | 400 | the host carries no tenant and no selector was supplied — details.reason tenant_required |
| `ERR_UNAUTHORIZED` | 401 | wrong credentials (invalid_credentials), two-factor needed (mfa_required), or a bad code (mfa_invalid) |
| `ERR_RATE_LIMITED` | 429 | too many consecutive failures on this account — details.reason login_locked |
| `ERR_UNAVAILABLE` | 503 | the tenant's portal has been switched off — details.reason site_offline |

#### Note

mfa_required is a 401 with the same code as a wrong password. Branch on details.reason, never on the status or the message: six different login outcomes share ERR_UNAUTHORIZED and only the reason tells them apart. expires_at is unix SECONDS, not milliseconds and not a formatted timestamp.


### End the current session

`POST /api/v1/auth/logout`

Revokes the calling session's token id, so it stops working immediately rather than at expiry.

- Authentication: manager session (JWT) or API token
- Not available to API tokens: this route requires an interactive manager session

#### Response — 200 OK

```json
{
  "data": { "ok": true }
}
```

#### Errors

| Code | Status | When |
| --- | --- | --- |
| `ERR_FORBIDDEN` | 403 | the caller holds an API token — this route refuses machine credentials |

#### Note

Best-effort by design: it answers ok even if the revocation write failed, because the worst case is a token that dies at its natural expiry. Do not treat ok true as proof the token is dead.


### Who am I, and what may I do

`GET /api/v1/auth/me`

The one-shot bootstrap call: the current manager, their roles, the resolved permission codes, and the tenant settings a client needs before it can render anything. Authenticated but not permission-gated, so any working credential reaches it.

- Authentication: manager session (JWT) or API token

#### Response — 200 OK

```json
{
  "data": {
    "version": "0.2.34",
    "manager": {
      "id": 41,
      "tenant_id": 12,
      "email": "ops@acme.example",
      "username": "ops",
      "status": "active",
      "two_factor_enabled": true
    },
    "roles": ["support"],
    "permissions": ["prm_users_index", "prm_users_update"],
    "is_admin": false,
    "settings": {
      "currency": "EGP",
      "timezone": "Africa/Cairo",
      "default_language": "en",
      "pos_undo_window_seconds": 60
    },
    "tenant": {
      "license_status": "active",
      "license_expires_at": "2027-01-31 00:00:00",
      "max_users": 5000,
      "users_count": 812,
      "blocked": false,
      "blocked_reason": ""
    }
  }
}
```

#### Note

For an API token, permissions is the INTERSECTION of the token's scope with its owner's live permissions, and is_admin is forced to false even when the owner is a tenant administrator. That is the authoritative answer to what the credential may do — gate your client on this array, not on the owner's role names. max_users null means unlimited; 0 means blocked, not unlimited.


### DELETE /api/v1/auth/push-tokens

`DELETE /api/v1/auth/push-tokens`

- Authentication: manager session (JWT) or API token
- Rate limit bucket: `t_mutate`
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### POST /api/v1/auth/push-tokens

`POST /api/v1/auth/push-tokens`

- Authentication: manager session (JWT) or API token
- Rate limit bucket: `t_mutate`
- Not available to API tokens: this route requires an interactive manager session

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### Exchange a refresh token

`POST /api/v1/auth/refresh`

Issues a new session token from a refresh token. Only available when the original login asked for one.

- Authentication: none
- Rate limit bucket: `refresh`

#### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `refresh_token` | body | string | yes | The refresh token returned by login. Shown once; only its hash is stored. |

#### Request

```json
{
  "refresh_token": "wA7k2Jd9..."
}
```

#### Errors

| Code | Status | When |
| --- | --- | --- |
| `ERR_UNAUTHORIZED` | 401 | the session was signed out (session_revoked), or the token is unknown or expired (invalid_credentials) |

#### Note

An expired refresh token and an unknown one answer identically, on purpose. A revoked session is the one case that is distinguished, because the remedy differs: sign in again rather than retry.


### POST /api/v1/auth/register/complete

`POST /api/v1/auth/register/complete`

- Authentication: none
- Rate limit bucket: `register_complete`

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### POST /api/v1/auth/register/resend

`POST /api/v1/auth/register/resend`

- Authentication: none
- Rate limit bucket: `register_resend`

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### POST /api/v1/auth/register/start

`POST /api/v1/auth/register/start`

- Authentication: none
- Rate limit bucket: `register_start`

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


### POST /api/v1/auth/register/verify

`POST /api/v1/auth/register/verify`

- Authentication: none
- Rate limit bucket: `register_verify`

_This endpoint has no hand-written reference entry yet. The method, path, authentication, permission and rate limit above are generated from the running router and are accurate; there is no request or response example._


