> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hyperprop.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Get account lockout status

> Returns whether the specified account is currently locked out from trading, and if so, which mode is active (`timed`, `session`, `trade_clock`, `hours`, `trading_day`), when it started, when it ends, and how many minutes remain.

For `trade_clock` mode, also returns `trade_clock_active` which indicates whether the account currently has live exposure (open positions or working orders).

Use this to show lockout banners, countdown timers, or trade-clock indicators in the UI.



## OpenAPI

````yaml /api-reference/trade-openapi.json get /trade/account/lockout
openapi: 3.0.3
info:
  contact:
    name: Hyperprop
    url: https://hyperprop.com
  description: >
    # Hyperprop Trade API


    Authenticated trading API for prop firm evaluations. Execute trades, manage
    positions, and monitor account performance in real-time.


    ---


    ## Introduction


    The Hyperprop Trade API is a **high-performance trading engine** built from
    the ground up in **Rust** — the same language powering mission-critical
    systems at Discord, Cloudflare, and AWS. We chose Rust for one reason:
    **speed without compromise**.


    ### Why Rust?


    | Metric | Hyperprop (Rust) | Traditional APIs |

    |--------|------------------|------------------|

    | Engine processing | **< 1ms** | 5-20ms |

    | Typical end-to-end | **10-50ms** | 50-200ms |

    | Memory safety | **Guaranteed** | Runtime errors |

    | Concurrent users | **Thousands** | Hundreds |


    Our engine processes orders with **sub-millisecond internal latency**,
    handles thousands of concurrent WebSocket connections, and enforces trading
    rules in real-time — all while maintaining zero-copy memory efficiency.


    ### Architecture Highlights


    - **Zero-allocation hot path**: Order execution avoids memory allocation for
    maximum throughput

    - **Lock-free data structures**: Concurrent access without blocking

    - **Real-time rule enforcement**: P&L limits, drawdown checks, and position
    limits evaluated on every tick

    - **WebSocket-first design**: Instant event streaming with < 5ms delivery

    - **Async I/O**: Built on Tokio for efficient handling of 10,000+
    simultaneous connections


    ### What You Can Do


    - **Execute trades** with market, limit, and stop orders

    - **Monitor positions** with real-time P&L updates

    - **Stream events** via WebSocket for instant order fills, position changes,
    and rule violations

    - **Track multiple accounts** across different prop firms simultaneously


    ---


    ## Quick Start


    ```javascript

    // 1. Get your JWT token from your auth provider

    const token = 'your-jwt-token';


    // 2. Fetch your accounts

    const res = await fetch('/trade/accounts', {
      headers: { 'Authorization': `Bearer ${token}` }
    });

    const { data: accounts } = await res.json();


    // 3. Place a trade

    const order = await fetch('/trade/order', {
      method: 'POST',
      headers: { 
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        account_id: accounts[0].id,
        contract: 'ESH6',
        side: 'buy',
        quantity: 1
      })
    });

    ```


    ---


    ## Authentication


    All endpoints require a valid JWT token.


    **Header (recommended):**

    ```http

    Authorization: Bearer <your-jwt-token>

    ```


    **Query parameter (for WebSocket):**

    ```text

    /trade/ws?token=<your-jwt-token>

    ```


    ---


    ## Response Format


    All responses follow this structure:


    ### Success Response

    ```json

    {
      "success": true,
      "data": { ... },
      "error": null,
      "code": null
    }

    ```


    ### Error Response

    ```json

    {
      "success": false,
      "data": null,
      "error": "Human readable error message",
      "code": "ERROR_CODE"
    }

    ```


    ---


    ## Error Codes


    ### Authentication & Access


    | Code | HTTP Status | Description |

    |------|-------------|-------------|

    | `UNAUTHORIZED` | 401 | Invalid or missing JWT token |

    | `FORBIDDEN` | 403 | Account does not belong to you |

    | `NO_ACCOUNT` | 404 | No trading account found for user |

    | `NOT_FOUND` | 404 | Resource not found (order, position, command, etc.) |

    | `ENGINE_AT_CAPACITY` | 400 | Too many commands are already in flight; the
    order was NOT accepted. Retry after a short backoff — the same
    `x-idempotency-key` is safe to reuse because nothing was queued. |


    ### Trading


    | Code | HTTP Status | Description |

    |------|-------------|-------------|

    | `TRADING_DISABLED` | 403 | Account status prevents trading (passed or
    failed) |

    | `MARKET_NOT_ENABLED` | 403 | Account does not have access to this
    contract's exchange (e.g., trying to trade COMEX contract on a CME-only
    account) |

    | `INVALID_SIDE` | 400 | Side must be `buy` or `sell` |

    | `INVALID_CONTRACT` | 400 | Contract symbol is unknown or not active |

    | `INVALID_QUANTITY` | 400 | Quantity must be greater than 0 |

    | `MISSING_PRICE` | 400 | Limit/stop orders require a `price` field |

    | `INVALID_TAKE_PROFIT` | 400 | Take-profit price is invalid (<=0, bad tick,
    or wrong side relative to entry) |

    | `INVALID_STOP_LOSS` | 400 | Stop-loss price is invalid (<=0, bad tick, or
    wrong side relative to entry) |

    | `BRACKET_ATTACH_FAILED` | 400 | Bracket order validation failed (invalid
    TP/SL combination) |

    | `INVALID_REQUEST` | 400 | Missing or invalid request fields |


    ### Lockout


    | Code | HTTP Status | Description |

    |------|-------------|-------------|

    | `LOCKOUT_ACTIVE` | 403 | Account is currently locked — trading actions are
    blocked |

    | `INVALID_LOCKOUT_MODE` | 400 | Mode must be one of: `hours`,
    `trading_day`, `timed`, `session`, `trade_clock` |

    | `INVALID_LOCKOUT_DURATION` | 400 | Duration is invalid (e.g. hours <= 0,
    or unknown timed_duration value) |

    | `LOCKOUT_NOT_REMOVABLE` | 403 | Lockout cannot be removed by user — either
    it is timed (wait for expiry), trade_clock with open exposure, or
    admin-locked |


    ### Idempotency & Infrastructure


    | Code | HTTP Status | Description |

    |------|-------------|-------------|

    | `DUPLICATE_REQUEST` | 409 | Same `x-idempotency-key` was already used for
    this operation |

    | `RATE_LIMITED` | 429 | Too many requests — account exceeded the allowed
    rate for this action |

    | `REDIS_UNAVAILABLE` | 503 | Internal command queue unavailable — the
    command was not accepted; retry with backoff |

    | `INTERNAL_ERROR` | 500 | Unexpected server error (check logs) |


    ---


    ## Order Types


    | Type | Description | Required Fields |

    |------|-------------|-----------------|

    | `market` | Execute immediately at best price | account_id, contract, side,
    quantity |

    | `limit` | Execute when price reaches level | + price |

    | `stop` | Trigger market order at stop price | + price |


    ### Order Request Examples


    **Market Order:**

    ```json

    {
      "account_id": "550e8400-e29b-41d4-a716-446655440000",
      "contract": "ESH6",
      "side": "buy",
      "quantity": 2
    }

    ```


    **Limit Order:**

    ```json

    {
      "account_id": "550e8400-e29b-41d4-a716-446655440000",
      "contract": "ESH6",
      "side": "sell",
      "quantity": 1,
      "order_type": "limit",
      "price": 6050.25
    }

    ```


    **Stop Order:**

    ```json

    {
      "account_id": "550e8400-e29b-41d4-a716-446655440000",
      "contract": "ESH6",
      "side": "sell",
      "quantity": 1,
      "order_type": "stop",
      "price": 6000.00
    }

    ```


    ### Order Response

    ```json

    {
      "success": true,
      "data": {
        "id": "order-uuid",
        "user_id": "user-uuid",
        "account_id": "account-uuid",
        "contract": "ESH6",
        "side": "buy",
        "order_type": "market",
        "quantity": 2,
        "filled_quantity": 2,
        "limit_price": null,
        "stop_price": null,
        "status": "filled",
        "filled_price": 6045.50,
        "filled_at": "2024-01-15T10:30:00Z",
        "processed_at": "2024-01-15T10:30:00Z",
        "reject_reason": null
      }
    }

    ```


    ---


    ## Account Status


    The engine returns these status values via REST and WebSocket. The database
    stores equivalent aliases shown in the DB column.


    | API Status | DB Value | Can Trade | Description |

    |------------|----------|-----------|-------------|

    | `Active` | `not_started` | ✅ | Account created, not yet traded |

    | `InProgress` | `in_progress` | ✅ | Actively trading |

    | `Completed` | `passed` | ❌ | Profit target reached — account passed
    (flat-confirmed) |

    | `Violated` | `failed` | ❌ | Rule violation — auto-liquidated, trading
    disabled |

    | `Violated` | `expired` | ❌ | Account expired — treated same as failed |


    ---


    ## Position Schema


    ```json

    {
      "user_id": "user-uuid",
      "account_id": "account-uuid",
      "contract": "ESH6",
      "quantity": 2,
      "avg_entry_price": 6045.50,
      "unrealized_pnl": 125.00,
      "realized_pnl": 0.00,
      "opened_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-01-15T10:35:00Z"
    }

    ```


    - `quantity`: Positive = long, negative = short

    - `unrealized_pnl`: Current P&L if closed now

    - `realized_pnl`: Gross P&L from partial closes (does NOT include fees)


    ---


    ## Trade Schema


    ```json

    {
      "id": "trade-uuid",
      "user_id": "user-uuid",
      "account_id": "account-uuid",
      "order_id": "order-uuid",
      "contract": "ESH6",
      "side": "buy",
      "price": 6045.50,
      "quantity": 2,
      "realized_pnl": 0.00,
      "timestamp": "2024-01-15T10:30:00Z"
    }

    ```


    ---


    ## WebSocket


    Real-time streaming of trading events.


    ### Connection


    ```text

    wss://{host}/trade/ws?token=JWT_TOKEN

    wss://{host}/trade/ws?token=JWT_TOKEN&account_id=ACCOUNT_UUID

    ```


    Replace `{host}` with your current domain (e.g., `api.hyperprop.com` or
    `localhost:8080`).


    ### Commands


    | Command | Description |

    |---------|-------------|

    | `{"action": "subscribe", "account_id": "uuid"}` | Filter to specific
    account |

    | `{"action": "subscribe", "account_id": "*"}` | Receive all accounts
    (default) |

    | `{"action": "unsubscribe", "account_id": "uuid"}` | Stop receiving account
    events |

    | `{"action": "ping"}` | Keep-alive |


    ### Events


    **Welcome (on connect):**

    ```json

    {
      "type": "Welcome",
      "user_id": "user-uuid",
      "accounts": [
        {"id": "acc-1", "account_number": "HP-12345", "balance": 50000, "status": "Active"}
      ],
      "subscribed_to": "*",
      "open_positions": 1,
      "pending_orders": 0
    }

    ```


    **OrderSubmitted:**

    ```json

    {
      "type": "OrderSubmitted",
      "user_id": "user-uuid",
      "account_id": "account-uuid",
      "order": {
        "id": "order-uuid",
        "contract": "ESH6",
        "product": "CME",
        "symbol": "ES",
        "side": "buy",
        "order_type": "market",
        "quantity": 1,
        "status": "filled",
        "filled_price": 6045.50,
        "reason": "User submitted market order"
      }
    }

    ```


    **OrderFilled:**

    ```json

    {
      "type": "OrderFilled",
      "user_id": "user-uuid",
      "account_id": "account-uuid",
      "order": {
        "id": "order-uuid",
        "contract": "ESH6",
        "product": "CME",
        "symbol": "ES",
        "side": "buy",
        "order_type": "limit",
        "quantity": 1,
        "status": "filled",
        "filled_price": 6045.50,
        "reason": "Limit price reached"
      },
      "trade": { "id": "trade-uuid", "price": 6045.50, "quantity": 1, "realized_pnl": 0 }
    }

    ```


    **OrderCancelled:**

    ```json

    {
      "type": "OrderCancelled",
      "user_id": "user-uuid",
      "account_id": "account-uuid",
      "order": {
        "id": "order-uuid",
        "contract": "ESH6",
        "product": "CME",
        "symbol": "ES",
        "side": "buy",
        "order_type": "limit",
        "quantity": 1,
        "status": "cancelled",
        "reason": "User requested cancellation"
      }
    }

    ```


    **PositionUpdate:**

    ```json

    {
      "type": "PositionUpdate",
      "user_id": "user-uuid",
      "account_id": "account-uuid",
      "position": { "contract": "ESH6", "quantity": 1, "unrealized_pnl": 125.00, ... }
    }

    ```


    **AccountUpdate:**

    ```json

    {
      "type": "AccountUpdate",
      "user_id": "user-uuid",
      "account_id": "account-uuid",
      "current_balance": 50000.00,
      "equity": 50125.00,
      "high_water_mark": 50125.00,
      "unrealized_pnl": 125.00,
      "total_pnl": 125.00,
      "daily_pnl": 125.00,
      "current_drawdown": 0.00,
      "status": "InProgress",
      "violation_reason": null
    }

    ```


    **RuleViolation:**

    ```json

    {
      "type": "RuleViolation",
      "user_id": "user-uuid",
      "account_id": "account-uuid",
      "rule": "max_loss",
      "reason": "Max Loss exceeded: $2500 loss >= $2500 limit"
    }

    ```


    **Notification:**

    ```json

    {
      "type": "Notification",
      "user_id": "user-uuid",
      "account_id": "account-uuid",
      "level": "warning",
      "title": "Copy Trade Failed",
      "message": "Failed to copy BUY 1 ESH6 to follower account: Order would exceed max contracts limit (15 > 10)",
      "category": "copy_trade"
    }

    ```


    Notification levels: `info`, `warning`, `error`


    Notification categories:

    - `copy_trade` - Copy trading events (failed copies, sync issues)

    - `order` - Order-related notifications (rejections, modifications)

    - `risk` - Risk management alerts (approaching limits)

    - `system` - System notifications (maintenance, updates)


    ### Example Client


    ```javascript

    const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';

    const ws = new
    WebSocket(`${protocol}//${location.host}/trade/ws?token=${jwt}&account_id=${accountId}`);


    ws.onopen = () => console.log('Connected');


    ws.onmessage = (e) => {
      const msg = JSON.parse(e.data);
      
      switch (msg.type) {
        case 'Welcome':
          console.log('Accounts:', msg.accounts);
          break;
        case 'OrderFilled':
          console.log(`Filled: ${msg.order.side} ${msg.order.quantity} ${msg.order.contract} @ ${msg.trade.price}`);
          break;
        case 'PositionUpdate':
          console.log(`P&L: $${msg.position.unrealized_pnl.toFixed(2)}`);
          break;
        case 'AccountUpdate':
          console.log(`Equity: $${msg.equity.toFixed(2)}, Drawdown: $${msg.drawdown.toFixed(2)}`);
          break;
        case 'RuleViolation':
          alert(`⚠️ ${msg.reason}`);
          break;
        case 'Notification':
          // Display notification to user based on level
          const icon = msg.level === 'error' ? '❌' : msg.level === 'warning' ? '⚠️' : 'ℹ️';
          console.log(`${icon} ${msg.title}: ${msg.message}`);
          // Show toast/notification in UI
          break;
      }
    };


    // Switch accounts dynamically

    ws.send(JSON.stringify({ action: 'subscribe', account_id:
    'other-account-uuid' }));

    ```


    ---


    ## Trading Rules


    Each account has rules that are checked in real-time:


    | Rule | Type | Description |

    |------|------|-------------|

    | `profit_target` | $ | Target profit to pass evaluation |

    | `max_loss` | $ | Maximum total loss allowed |

    | `daily_loss` | $ | Maximum loss per day |

    | `max_drawdown` | % | Max drawdown from high water mark |

    | `daily_drawdown` | % | Max daily drawdown |

    | `max_contracts` | # | Maximum position size in mini-equivalent units |

    | `micro_conversion_ratio` | # | How many micros count as 1 unit toward
    `max_contracts` (default 10; e.g. 5 or 1 per firm plan) |


    When a rule is violated, positions are auto-liquidated and the account is
    marked as `Violated` or `Completed`.


    ---


    ## Contracts


    Supported CME futures contracts used by the engine:


    | Symbol | Name | Tick Size | Point Value |

    |--------|------|-----------|-------------|

    | ESH6 | E-mini S&P 500 | 0.25 | $12.50 |

    | NQH6 | E-mini Nasdaq | 0.25 | $5.00 |

    | YMH6 | E-mini Dow | 1.00 | $5.00 |

    | RTH6 | E-mini Russell | 0.10 | $5.00 |


    ---


    ## Data Persistence


    All trading data is persisted to ensure consistency and auditability:


    | Data | Storage | When |

    |------|---------|------|

    | **Order Snapshot** | Durable database | Latest state per `order_id`
    (upsert) |

    | **Order Events (Audit)** | Durable database | Every lifecycle transition
    (append-only) |

    | **Account State** | Durable database | On position close, rule violation,
    account completion |

    | **Positions** | In-memory | Real-time only (rebuilt from order history on
    restart) |


    ### Order Fields Persisted


    Every order includes:

    - `id`, `user_id`, `account_id`

    - `contract`, `product`, `symbol` (e.g., "ESH6", "CME", "ES")

    - `side`, `order_type`, `quantity`, `filled_quantity`

    - `limit_price`, `stop_price`, `filled_price`

    - `status`
    (pending_submit/new/working/pending/.../filled/cancelled/rejected)

    - `reason` (human-readable explanation)

    - `processed_at`, `engine_updated_at`, `filled_at`


    ---


    ## Rate Limits


    Rate limits are enforced **per trading account** using an in-memory token
    bucket algorithm. Each action category has its own independent bucket, so
    order submissions don't compete with cancellations.


    ### Limits by Action


    | Action | Burst Capacity | Refill Rate | Applies To |

    |--------|---------------|-------------|------------|

    | Order Submit | 10 | 10/sec | `POST /trade/order` |

    | Order Modify | 10 | 10/sec | `POST /trade/order/modify`,
    `/order/attach-bracket`, `/order/detach-bracket` |

    | Order Cancel | 20 | 20/sec | `POST /trade/order/cancel`,
    `/orders/cancel-all` |

    | Position Close | 5 | 2/sec | `POST /trade/position/close`,
    `/position/reverse`, `/close-all`, `/flatten` |

    | Copy Config | 10 | 2/sec | `POST /trade/copy/*` (create, update, toggle,
    delete) |

    | Lockout | 5 | 1/sec | `POST /trade/account/lockout`, `DELETE
    /trade/account/lockout` |


    Read endpoints (GET) are **not** rate limited.


    ### How It Works


    Each account starts with a full bucket (e.g., 10 tokens for order submit).
    Every request consumes 1 token. Tokens refill continuously at the specified
    rate. If the bucket is empty, the request is rejected with HTTP 429.


    ### Rate Limit Response (HTTP 429)


    ```json

    {
      \"success\": false,
      \"data\": null,
      \"error\": \"Rate limit exceeded for order submissions. Max 10 requests per second per account. Retry after 0.1 seconds.\",
      \"code\": \"RATE_LIMITED\"
    }

    ```


    ### Headers


    Successful requests do not include rate limit headers to minimize overhead.
    On 429 responses, inspect the error message for retry timing.


    ### Organization Overrides


    Organizations can have custom rate limits (e.g., higher limits for copy
    trading leaders). Contact the Hyperprop team for custom configurations.


    ### Important Notes


    - Limits are per **account**, not per user. A user with 5 accounts has 5
    independent buckets per action.

    - Different action categories have independent buckets. Exhausting order
    submit tokens does not affect cancellation tokens.

    - WebSocket events are **not** rate limited (server → client push).
  license:
    name: Proprietary
  title: Hyperprop Trade API
  version: 1.0.0
servers:
  - url: https://api.hyperprop.com
    description: Production
security: []
tags:
  - description: Trading account management - balances, equity, P&L, rules
    name: Account
  - description: Order submission, cancellation, and history
    name: Orders
  - description: Open positions and P&L tracking
    name: Positions
  - description: Real-time streaming of trading events
    name: WebSocket
  - description: >-
      Live engine metrics feeds. Metrics are kept in memory only and rendered by
      the operator dashboard at /trade/admin
    name: Metrics
paths:
  /trade/account/lockout:
    get:
      tags:
        - Account
      summary: Get account lockout status
      description: >-
        Returns whether the specified account is currently locked out from
        trading, and if so, which mode is active (`timed`, `session`,
        `trade_clock`, `hours`, `trading_day`), when it started, when it ends,
        and how many minutes remain.


        For `trade_clock` mode, also returns `trade_clock_active` which
        indicates whether the account currently has live exposure (open
        positions or working orders).


        Use this to show lockout banners, countdown timers, or trade-clock
        indicators in the UI.
      operationId: getAccountLockoutStatus
      parameters:
        - description: Trading account id
          in: query
          name: account_id
          required: true
          schema:
            format: uuid
            type: string
      responses:
        '200':
          content:
            application/json:
              example:
                code: null
                data:
                  account_id: 550e8400-e29b-41d4-a716-446655440000
                  active: true
                  ends_at: '2026-03-12T14:30:00Z'
                  locked_by: user
                  mode: timed
                  reason: Initiated by user
                  remaining_minutes: 25
                  starts_at: '2026-03-12T14:00:00Z'
                  trade_clock_active: null
                error: null
                success: true
              schema:
                $ref: '#/components/schemas/AccountLockoutStatus'
          description: Current lockout status
        '401':
          content:
            application/json:
              example:
                code: UNAUTHORIZED
                data: null
                error: Invalid or missing JWT token
                success: false
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
          description: Authentication required
        '403':
          content:
            application/json:
              example:
                code: FORBIDDEN
                data: null
                error: Account does not belong to you
                success: false
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
          description: Account does not belong to user
      security:
        - bearer: []
components:
  schemas:
    AccountLockoutStatus:
      description: Lockout status response
      properties:
        account_id:
          format: uuid
          type: string
        active:
          type: boolean
        ends_at:
          nullable: true
          type: string
        locked_by:
          nullable: true
          type: string
        mode:
          nullable: true
          type: string
        reason:
          nullable: true
          type: string
        remaining_minutes:
          format: int64
          nullable: true
          type: integer
        starts_at:
          nullable: true
          type: string
        trade_clock_active:
          nullable: true
          type: boolean
      required:
        - account_id
        - active
      type: object
    ApiErrorResponse:
      description: Standard API error response
      example:
        code: ERROR_CODE
        data: null
        error: Error message describing what went wrong
        success: false
      properties:
        code:
          description: Machine-readable error code
          example: NO_ACCOUNT
          nullable: true
          type: string
        data:
          description: Always null for errors
          nullable: true
        error:
          description: Human-readable error message
          example: No trading account found for this user
          nullable: true
          type: string
        success:
          description: Always false for errors
          example: false
          type: boolean
      required:
        - success
      type: object

````

## Related topics

- [Get lockout status for account](/platform-api/organization/get-lockout-status-for-account.md)
- [Get daily lockout activity](/platform-api/organization/get-daily-lockout-activity.md)
- [Remove lockout from account](/platform-api/organization/remove-lockout-from-account.md)
- [Update active lockout](/platform-api/organization/update-active-lockout.md)
- [List all active lockouts](/platform-api/organization/list-all-active-lockouts.md)
