> ## 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.

# Real-time WebSocket for trading events

> Upgrades to a WebSocket connection for streaming real-time trading events.

**Authentication:** pass JWT via query parameter `?token=YOUR_JWT` or via `Authorization` header.

**Optional filter:** add `&account_id=UUID` to receive events for a single account only.

**Events received:**
- `Welcome` — connection confirmed with account list
- `OrderSubmitted` / `OrderFilled` / `OrderCancelled` — order lifecycle
- `PositionUpdate` — real-time P&L changes on every tick
- `AccountUpdate` — balance, equity, drawdown changes
- `RuleViolation` — trading rule breach with reason
- `Notification` — system/copy-trade alerts

**Commands you can send:**
- `{"action": "subscribe", "account_id": "uuid"}` — filter to one account
- `{"action": "subscribe", "account_id": "*"}` — receive all (default)
- `{"action": "ping"}` — keep-alive



## OpenAPI

````yaml /api-reference/trade-openapi.json get /trade/ws
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/ws:
    get:
      tags:
        - WebSocket
      summary: Real-time WebSocket for trading events
      description: >-
        Upgrades to a WebSocket connection for streaming real-time trading
        events.


        **Authentication:** pass JWT via query parameter `?token=YOUR_JWT` or
        via `Authorization` header.


        **Optional filter:** add `&account_id=UUID` to receive events for a
        single account only.


        **Events received:**

        - `Welcome` — connection confirmed with account list

        - `OrderSubmitted` / `OrderFilled` / `OrderCancelled` — order lifecycle

        - `PositionUpdate` — real-time P&L changes on every tick

        - `AccountUpdate` — balance, equity, drawdown changes

        - `RuleViolation` — trading rule breach with reason

        - `Notification` — system/copy-trade alerts


        **Commands you can send:**

        - `{"action": "subscribe", "account_id": "uuid"}` — filter to one
        account

        - `{"action": "subscribe", "account_id": "*"}` — receive all (default)

        - `{"action": "ping"}` — keep-alive
      operationId: ws_handler
      parameters:
        - description: JWT authentication token (required)
          example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
          in: query
          name: token
          required: true
          schema:
            type: string
        - description: 'Optional: filter to specific account UUID'
          example: 550e8400-e29b-41d4-a716-446655440000
          in: query
          name: account_id
          required: false
          schema:
            nullable: true
            type: string
      responses:
        '101':
          description: >-
            WebSocket connection upgraded successfully. You will receive a
            Welcome message.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
          description: Authentication failed - invalid or missing token
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
          description: >-
            Browser origin not allowed (first-party apps and approved origins
            only)
      x-codeSamples:
        - label: WebSocket Client
          lang: JavaScript
          source: >-
            // Connect to WebSocket

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

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


            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.trade.price}`);
                  break;
                case 'PositionUpdate':
                  console.log(`P&L: $${msg.position.unrealized_pnl}`);
                  break;
                case 'RuleViolation':
                  alert(`⚠️ ${msg.reason}`);
                  break;
              }
            };


            // Subscribe to specific account

            ws.send(JSON.stringify({ action: 'subscribe', account_id:
            'account-uuid' }));
components:
  schemas:
    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

- [Real-time event stream (WebSocket)](/platform-api/organization/real-time-event-stream-websocket.md)
- [WebSocket Stream (Documentation Only)](/market-data-api/websocket/websocket-stream-documentation-only.md)
- [Get open positions with real-time P&L](/trade-api/positions/get-open-positions-with-real-time-p&l.md)
- [Rate limits & quotas](/concepts/rate-limits.md)
- [Register a webhook endpoint](/platform-api/organization/register-a-webhook-endpoint.md)
