# Admin and Risk Limit Management

## Generate API auth token

<mark style="color:green;">`POST`</mark> `/api/reset_auth_token/`

Delete old token, generate and return new token.

{% tabs %}
{% tab title="500: Internal Server Error Unknown server error" %}

```json
{
    "error": "Internal server error"
}
```

{% endtab %}

{% tab title="200: OK Success" %}

```json
{
    "new_token": "4b933af81699070ae624ed4651eea343910108ec"
}
```

{% endtab %}

{% tab title="422: Unprocessable Entity Unexpected failure to persist changes" %}

```json
{
    "error": "Error message."
}
```

{% endtab %}
{% endtabs %}

## Risk Limits

These endpoints allow administrators to programmatically manage trading restrictions (pair blocks and notional limits). All endpoints require admin privileges - the authenticated user must be `is_staff` or `is_superuser`.

All endpoints require the `Authorization: Token <API_KEY>` header. Write operations also require `Content-Type: application/json`.

If your organization has the **approval workflow** enabled (`REQUIRE_TRADING_LIMIT_APPROVAL`), create/edit/delete operations will not apply immediately. Instead, they create pending change requests that must be approved by a different admin via the review endpoint.

***

### Approval workflow

If the approval workflow is enabled, restriction changes require approval from a **different** admin user before taking effect.

This means programmatic automation requires **two API tokens** belonging to two different staff/superuser accounts:

**Step 1 - Request a change (Token A)**

Submit a create, edit, or delete call. The restriction is not yet active. You receive a `202 Accepted` response with a `request_id`.

```
POST /api/admin/trading_restrictions
Authorization: Token <TOKEN_A>
Content-Type: application/json

{
    "restriction_type": "PAIR_BLOCK",
    "pair": "BTC-USDT",
    "venue": "binance",
    "reason": "Trading halt"
}
```

```json
{
    "request_created": true,
    "request_id": "b2c3d4e5-6789-01bc-defg-2345678901bc",
    "message": "Restriction submitted for approval"
}
```

**Step 2 - Approve the change (Token B, different user)**

A second admin reviews and approves the pending request. The restriction is now applied.

```
POST /api/admin/trading_restriction_change_requests/b2c3d4e5-6789-01bc-defg-2345678901bc/review
Authorization: Token <TOKEN_B>
Content-Type: application/json

{
    "action": "approve"
}
```

```json
{
    "message": "Change request approved and applied",
    "request_id": "b2c3d4e5-6789-01bc-defg-2345678901bc"
}
```

> **Key rules:**
>
> * A user **cannot approve their own request** - the API returns `400` if attempted.
> * A user **can reject (withdraw) their own request** - the pending request is deleted.
> * If approval is **not enabled**, create/edit/delete calls apply immediately and return `200`/`201` as normal.

***

### Get trading restrictions

`GET` `/api/admin/trading_restrictions`

Returns all active trading restrictions, with optional filtering.

**Query Parameters**

| Name               | Type   | Description                                          |
| ------------------ | ------ | ---------------------------------------------------- |
| `restriction_type` | string | Filter by type: `PAIR_BLOCK` or `MAX_ORDER_NOTIONAL` |
| `pair`             | string | Filter by pair (e.g., `BTC-USDT`). Case-insensitive. |
| `venue`            | string | Filter by venue (e.g., `binance`). Case-insensitive. |

**200: OK**

```json
{
    "restrictions": [
        {
            "id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
            "restriction_type": "MAX_ORDER_NOTIONAL",
            "pair": "BTC-USDT",
            "venue": null,
            "user_id_scope": null,
            "user_scope_username": null,
            "account_id_scope": null,
            "account_name": null,
            "value": "50000.00000000",
            "metadata": null,
            "reason": "Risk limit for BTC",
            "is_active": true,
            "pending_request": null,
            "created_by": "admin",
            "created_by_id": 1,
            "created_at": "2026-01-15T10:30:00Z",
            "updated_by": null,
            "updated_at": null
        }
    ],
    "count": 1,
    "requires_approval": false
}
```

**403: Forbidden**

```json
{
    "error": "You are not authorized to perform this action"
}
```

***

### Create trading restriction

`POST` `/api/admin/trading_restrictions`

Create a new trading restriction. If the approval workflow is enabled, this creates a pending change request instead (HTTP 202).

**Request Body**

| Name               | Type          | Required    | Description                                                                                                    |
| ------------------ | ------------- | ----------- | -------------------------------------------------------------------------------------------------------------- |
| `restriction_type` | string        | Yes         | `PAIR_BLOCK` or `MAX_ORDER_NOTIONAL`                                                                           |
| `pair`             | string        | Conditional | Trading pair (e.g., `BTC-USDT`) or base asset (e.g., `BTC`). Required for `PAIR_BLOCK`. Omit for global scope. |
| `venue`            | string        | No          | Exchange name (e.g., `binance`, `okx`). Omit to apply across all venues.                                       |
| `user_id_scope`    | integer       | No          | User ID to scope restriction to a specific user. Omit to apply to all users.                                   |
| `account_id_scope` | string (UUID) | No          | Account UUID to scope restriction to a specific account. Omit to apply to all accounts.                        |
| `value`            | decimal       | Conditional | Maximum notional value. Required and must be positive for `MAX_ORDER_NOTIONAL`. Ignored for `PAIR_BLOCK`.      |
| `reason`           | string        | No          | Human-readable explanation for the restriction.                                                                |
| `metadata`         | object        | No          | Arbitrary JSON object for additional context.                                                                  |

**Pair matching behavior:** A full pair like `BTC-USDT` matches that exact pair. A base asset like `BTC` (no hyphen) matches any pair where the base asset is BTC (e.g., `BTC-USDT`, `BTC-USDC`). Omitting `pair` creates a global restriction across all pairs.

**201: Created** - Restriction applied immediately (approval workflow disabled)

```json
{
    "id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
    "restriction_type": "PAIR_BLOCK",
    "pair": "BTC-USDT",
    "venue": "binance",
    "user_id_scope": null,
    "user_scope_username": null,
    "account_id_scope": null,
    "account_name": null,
    "value": null,
    "metadata": null,
    "reason": "Trading halt on BTC-USDT",
    "is_active": true,
    "pending_request": null,
    "created_by": "admin",
    "created_by_id": 1,
    "created_at": "2026-01-15T10:30:00Z",
    "updated_by": null,
    "updated_at": null
}
```

**202: Accepted** - Submitted for approval (approval workflow enabled)

```json
{
    "request_created": true,
    "request_id": "b2c3d4e5-6789-01bc-defg-2345678901bc",
    "message": "Restriction submitted for approval"
}
```

**400: Bad Request** - Validation error

```json
{
    "error": "restriction_type must be one of: ['PAIR_BLOCK', 'MAX_ORDER_NOTIONAL']"
}
```

```json
{
    "error": "pair is required for PAIR_BLOCK restrictions"
}
```

```json
{
    "error": "value is required for MAX_ORDER_NOTIONAL restrictions"
}
```

```json
{
    "error": "value must be a positive number"
}
```

**409: Conflict** - Duplicate restriction

```json
{
    "error": "An active restriction with the same scope already exists",
    "existing_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab"
}
```

**403: Forbidden**

```json
{
    "error": "You are not authorized to perform this action"
}
```

***

### Update trading restriction

`PATCH` `/api/admin/trading_restrictions/{id}`

Update an existing restriction's value, reason, or metadata. If the approval workflow is enabled, this creates a pending edit request instead (HTTP 202).

**Path Parameters**

| Name | Type | Description        |
| ---- | ---- | ------------------ |
| `id` | UUID | The restriction ID |

**Request Body**

At least one field must be provided.

| Name       | Type    | Description                                       |
| ---------- | ------- | ------------------------------------------------- |
| `value`    | decimal | Updated maximum notional value. Must be positive. |
| `reason`   | string  | Updated reason.                                   |
| `metadata` | object  | Updated metadata.                                 |

**200: OK** - Restriction updated immediately (approval workflow disabled)

```json
{
    "id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
    "restriction_type": "MAX_ORDER_NOTIONAL",
    "pair": "BTC-USDT",
    "venue": null,
    "value": "75000.00000000",
    "reason": "Increased limit",
    "is_active": true,
    "updated_by": "admin",
    "updated_at": "2026-01-16T14:00:00Z"
}
```

**202: Accepted** - Submitted for approval (approval workflow enabled)

```json
{
    "request_created": true,
    "request_id": "c3d4e5f6-7890-12cd-efgh-3456789012cd",
    "message": "Edit submitted for approval"
}
```

**404: Not Found**

```json
{
    "error": "Restriction not found"
}
```

**409: Conflict** - Pending edit exists

```json
{
    "error": "A pending edit request already exists. Withdraw it first.",
    "pending_request_id": "c3d4e5f6-7890-12cd-efgh-3456789012cd"
}
```

***

### Delete trading restriction

`DELETE` `/api/admin/trading_restrictions/{id}`

Soft-delete (deactivate) a trading restriction. If the approval workflow is enabled, this creates a pending delete request instead (HTTP 202).

**Path Parameters**

| Name | Type | Description        |
| ---- | ---- | ------------------ |
| `id` | UUID | The restriction ID |

**200: OK** - Restriction deactivated

```json
{
    "message": "Restriction deactivated",
    "id": "a1b2c3d4-5678-90ab-cdef-1234567890ab"
}
```

**202: Accepted** - Submitted for approval (approval workflow enabled)

```json
{
    "request_created": true,
    "request_id": "d4e5f6g7-8901-23de-fghi-4567890123de",
    "message": "Delete submitted for approval"
}
```

**404: Not Found**

```json
{
    "error": "Restriction not found"
}
```

**409: Conflict** - Pending delete exists

```json
{
    "error": "A pending delete request already exists",
    "pending_request_id": "d4e5f6g7-8901-23de-fghi-4567890123de"
}
```

***

### Get change requests

`GET` `/api/admin/trading_restriction_change_requests`

List pending, approved, or rejected change requests. Only relevant when the approval workflow is enabled.

**Query Parameters**

| Name     | Type   | Description                                                               |
| -------- | ------ | ------------------------------------------------------------------------- |
| `status` | string | Filter by status: `PENDING`, `APPROVED`, or `REJECTED`. Case-insensitive. |

**200: OK**

```json
{
    "requests": [
        {
            "id": "b2c3d4e5-6789-01bc-defg-2345678901bc",
            "action": "create",
            "restriction_id": null,
            "payload": {
                "restriction_type": "PAIR_BLOCK",
                "pair": "BTC-USDT",
                "venue": "binance",
                "user_id_scope": null,
                "account_id_scope": null,
                "value": null,
                "metadata": null,
                "reason": "Trading halt"
            },
            "status": "PENDING",
            "requested_by": "admin",
            "requested_by_id": 1,
            "requested_at": "2026-01-15T10:30:00Z",
            "reviewed_by": null,
            "reviewed_by_id": null,
            "reviewed_at": null,
            "review_notes": null
        }
    ],
    "count": 1
}
```

**Payload contents by action type:**

| Action   | Payload contains                                                                                                                 |
| -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `create` | Full restriction fields: `restriction_type`, `pair`, `venue`, `user_id_scope`, `account_id_scope`, `value`, `metadata`, `reason` |
| `edit`   | Only changed fields: `value`, `reason`, `metadata`                                                                               |
| `delete` | Empty object `{}`                                                                                                                |

**403: Forbidden**

```json
{
    "error": "You are not authorized to perform this action"
}
```

***

### Review change request

`POST` `/api/admin/trading_restriction_change_requests/{id}/review`

Approve or reject a pending change request. Approval executes the restriction change. A user can reject (withdraw) their own request, but cannot approve their own request.

**Path Parameters**

| Name | Type | Description           |
| ---- | ---- | --------------------- |
| `id` | UUID | The change request ID |

**Request Body**

| Name     | Type   | Required | Description            |
| -------- | ------ | -------- | ---------------------- |
| `action` | string | Yes      | `approve` or `reject`  |
| `notes`  | string | No       | Optional review notes. |

**200: OK** - Approved

```json
{
    "message": "Change request approved and applied",
    "request_id": "b2c3d4e5-6789-01bc-defg-2345678901bc",
    "restriction": {
        "id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
        "restriction_type": "PAIR_BLOCK",
        "pair": "BTC-USDT",
        "venue": "binance",
        "is_active": true
    }
}
```

**200: OK** - Rejected

```json
{
    "message": "Change request rejected",
    "request_id": "b2c3d4e5-6789-01bc-defg-2345678901bc"
}
```

**200: OK** - Withdrawn (self-rejection)

```json
{
    "message": "Change request withdrawn",
    "request_id": "b2c3d4e5-6789-01bc-defg-2345678901bc"
}
```

**400: Bad Request**

```json
{
    "error": "action must be 'approve' or 'reject'"
}
```

```json
{
    "error": "Cannot approve your own request"
}
```

```json
{
    "error": "Request is already APPROVED"
}
```

**404: Not Found**

```json
{
    "error": "Change request not found"
}
```

***

### Useful endpoints for scoping restrictions

If your automation needs user or account IDs to scope restrictions:

| Endpoint                   | Purpose                                  |
| -------------------------- | ---------------------------------------- |
| `GET /api/users/`          | Get user IDs for `user_id_scope`         |
| `GET /api/admin/accounts/` | Get account UUIDs for `account_id_scope` |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tread.fi/interacting-with-the-api/api-reference/admin-and-risk-limit-management.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
