GET /perpetual/exchangeInfo
Retrieve exchange information for perpetuals markets including available markets and their details.Authentication: Not required
Status Codes:
200- Exchange information retrieved successfully500- Internal server error
Perpetuals Calculation Formulas
For frontend display (margin ratio, break-even price, ROI %, etc.), seeperpetuals-frontend-formulas-from-code.md. Key formulas:
- Cross margin ratio:
margin_ratio = total_account_equity / total_maintenance_margin(fromGET /perpetual/accountorGET /perpetual/accounts) - Break-even price: Long
entry_price - realized_pnl/amount, Shortentry_price + realized_pnl/amount(derived, not returned) - Liquidation price: Returned by API and WebSocket
position_updatefor cross-margin positions
Historical and current funding rates for perpetual markets.
Per-market history
Retrieve the full funding-rate timeline for a single perpetual symbol. Each entry includes the funding rate, premium index, mark price, and index price at that interval. Supports cursor- or page-based pagination for long histories, with short-lived response caching for high-frequency polling.Current-rate snapshot
Retrieve the latest funding rate for all active perpetual markets in a single call — useful for dashboards and pre-trade checks.Endpoints, request parameters, and response schemas follow the same conventions as the rest of the Perpetuals Trading API.
List pagination
Perpetual list endpoints use opaque cursor pagination.1
First request
Send
use_cursor=true (optionally with page_size). The response returns the first page plus a next_cursor token and a has_more flag.2
Next pages
While
has_more is true, send the previous response’s next_cursor value as the cursor query parameter to fetch the following page.3
End
When
has_more is false, next_cursor is empty and there are no more pages.
Response fields:
Errors: Malformed
cursor → 400 with "error": "invalid_cursor".
GET /perpetual/account/market-fee-rate
Retrieve the effective maker/taker fee rate for a single market on a perpetuals app session.Authentication: Required (read:futures scope)
Response:
Status Codes:
200- Account fee rate retrieved successfully400- Missingapp_session_idormarketparameter401- Authentication failed
GET /perpetual/accounts
Retrieve all perpetuals accounts for the authenticated user.Authentication: Required
Status Codes:
200- Accounts retrieved successfully401- Authentication failed500- Internal server error
POST /perpetual/account
Create a new perpetuals account with a specified app_session_id.Authentication: Required
200. The account does not exist immediately; poll GET /perpetual/account until it returns a result (typically a few seconds).
Request Body:
Response:
Status Codes:
200- Account creation initiated successfully400- Invalid request parameters (missing app_session_id, invalid owner address)401- Authentication failed403- Forbidden (owner mismatch - trying to create account for different wallet)500- Internal server error
- The
app_session_idshould typically match the user’s spot account ID to allow seamless transfers - The account becomes available shortly after this request completes
- Attempting to create an account with an existing
app_session_idwill return an error
GET /perpetual/account
Retrieve detailed information for a specific perpetuals account including all balances, positions, and account-level metrics.Authentication: Required
Request:
/perpetual/accounts response (single account object), including optional initial_leverages and transferable_balances.
Note on available_balance vs transfers: The name appears in two places—(1) at the account root: aggregate balance available for new positions; (2) inside each balances[] element: available for that asset. Both include unrealized PnL (formula: total − allocated/locked + unrealized PnL). For perp→spot transfer limits, use transferable_balances (account root) or balances[].max_transfer_out per asset—these match WebSocket perpetuals_account.account_update and account for closing-fee reserve and cross-margin transfer caps.
Status Codes:
200- Account retrieved successfully400- Missing app_session_id parameter401- Authentication failed404- Account not found500- Internal server error
POST /perpetual/warning/mute
Mute this perpetuals account’s liquidation warnings for 24 hours.Authentication: Required (trade:futures scope)
Response (200):
Status Codes:
200- Liquidation warnings muted successfully400- Invalid request body or missingapp_session_id401- Authentication failed404- Account not found500- Internal server error503- Service temporarily unavailable
GET /perpetual/balance
Retrieve collateral balances for a specific perpetuals account.Authentication: Required
Request:
Status Codes:
200- Balances retrieved successfully400- Missing app_session_id parameter401- Authentication failed404- Account not found500- Internal server error
GET /perpetual/transfer-assets
Retrieve the system-level perpetual transfer asset configuration. This endpoint returns which assets are configured for spot/perps transfer at the platform level.Only assets that are both active and marked as stablecoin are returned.
It does not represent user-level transferability (e.g., user balance availability).
Authentication: Not required (public endpoint)
Only assets that are both active and stablecoin are included (stablecoin flag is not repeated in the JSON).
Status Codes:
200- Transfer assets retrieved successfully500- Internal server error
GET /perpetual/transaction/history
Retrieve unified perpetual transaction history for a wallet + app session. This endpoint aggregates balance-changing events (funding payments, internal transfers, fees, realized PnL, liquidations, ADL, etc.) into a single paginated history from the user’s perspective. Each row is one(transaction_id, asset) pair:
- Positive
amount→ balance increase - Negative
amount→ balance decrease
Authentication: Required
type filter mapping:
""(empty / omitted): User-facing types only (excludes internal order bookkeeping such asORDER_*,DEPOSIT,WITHDRAWAL, etc.)"funding_fee": Funding payments (maps toFUNDING_FEE_IN,FUNDING_FEE_OUT)"transfer": Internal asset transfers (maps toTRANSFER_IN,TRANSFER_OUT)"fee": Trading fee-related events (maps toFEE,FEE_WAIVER_DISTRESSED_CLOSE,POSITION_OPEN_FEE,POSITION_CLOSE_FEE)"realized_pnl": Realized PnL events (maps toREALIZED_PNL)"liquidation": Liquidation events (maps toLIQUIDATION,LIQUIDATION_COMPLETE)"adl": ADL events (maps toADL_COUNTERPARTY_CLOSE,ADL_TAKEN_OVER_CLOSE)- Compatibility note: ADL events are intentionally separated from the
liquidationfilter; clients that want all forced-deleveraging events should query bothtype=liquidationandtype=adl.
start_time and end_time are applied unchanged. When bounds are omitted (or sent as 0), the backend applies a default window of the last 30 days ending at now (UTC):
The time window is applied on the transaction time of each event.
Request (explicit time range):
start_time and end_time; cursor first page):
use_cursor=true on the first request, then follow next_cursor while has_more is true (see List pagination). Malformed cursor → 400 / "error": "invalid_cursor".
Response Fields:
Status Codes:
200- Transaction history retrieved successfully400- Invalid query parameters (including malformedcursor) (e.g., missingapp_session_id, invalidtype, malformedcursor)401- Authentication failed500- Internal server error
GET /perpetual/positions
Retrieve all open positions for a specific perpetuals account. Position mode: Each row’sdirection is long or short (stored leg). A market may return two rows (one long, one short), since long and short legs are tracked separately.
Authentication: Required
Request:
Status Codes:
200- Positions retrieved successfully400- Missing app_session_id parameter401- Authentication failed404- Account not found500- Internal server error
POST /perpetual/positions/close
Batch-submit market IOC close orders for every open position leg on the account that has available size greater than zero. Each leg uses the same path asPOST /perpetual/order.
- If
marketis omitted or empty: all matching legs across markets are closed. - If
marketis set: only positions for that market (case-insensitive match; symbol is normalized to uppercase for validation against exchange info). - Legs are processed with bounded parallelism (worker pool) for lower latency.
- Safety cap: at most 50 closable legs are submitted per request; when more legs exist, the response includes
remaining_countandpartial=true.
direction long or short with reduce_only: true. A market may have separate long and short legs, which are closed independently.
Authentication: Required (trade scope). Ownership of
app_session_id is verified.
Response (200):
When there are no closable legs (all
available_amount is zero), the endpoint returns 200 with positions_submitted: 0 and an explanatory message.
Status Codes:
200- Request completed (checkfailedfor partial failures)400- Invalid JSON, missingapp_session_id, or unknownmarket(when provided and exchange info is available)401- Authentication failed403- Permission denied for(wallet_address, app_session_id)404- Perpetual account not found502- Backend request failed503- Service temporarily unavailable
POST /perpetual/leverage
Sets initial leverage per account and market. Order creation does not accept leverage; it is resolved from stored settings when matching orders. Use this endpoint (or the default, typically10) before trading if you need a specific multiplier.
How to read current leverage: GET /perpetual/accounts returns initial_leverages (market → leverage string). Positions and orders also expose an effective leverage field.
Restrictions & behavior:
- Open orders: Changing leverage is rejected while any open order exists for that market (
errore.g.order_exists). Cancel or fill those orders first. - Open positions: Changing leverage is allowed. The new leverage is applied atomically: position
allocated_marginis recalculated from notional ÷ leverage, and locked balance is adjusted. The call may still fail if the account does not have enough free collateral for a higher required margin, or if the new margin would fall below maintenance for a position (set_leverage_failedor a similar message). - Validation:
leverage >= 1is required, andleverage <= max_allowed_leveragefor that market (leverage_exceeds_max).
Authentication: Required (JWT or API Key). The wallet address must be present in the auth context; ownership of
app_session_id is verified.
Response (200):
Error responses (non-exhaustive;
success is false when HTTP status is not 200):
Error body (400 from business rules):
200- Leverage set successfully400- Validation or business rule failure (see table)401- Not authenticated or missing wallet in context503- Service temporarily unavailable500- Internal server error
GET /perpetual/position-history
Retrieve closed position history with pagination. Only returns positions that have been fully closed. Default ordering matchessort_by=closed_at and sort_dir=desc with a stable secondary sort on internal row id.
Authentication: Required
Request:
cursor → 400 / invalid_cursor.
Response Fields:
Note: for legacy closed positions created before these fields were persisted,
max_held and initial_margin can be 0, which means historical values are unavailable rather than actual zero exposure.Note: for positions that were already open when max-held/initial-margin persistence was introduced,
initial_margin reflects migration-time/live-update value rather than the original open-time margin.
Status Codes:
200- Position history retrieved successfully400- Invalid query parameters (including malformedcursor) (e.g. unparsable time strings,opened_fromafteropened_to,closed_fromafterclosed_to, invalidsort_by/sort_dir, orpage_sizeout of 1–100 when supplied)401- Authentication failed or missing wallet in context403- Permission denied (authenticated wallet is not the owner ofapp_session_id)404- Account not found500- Internal server error
GET /perpetual/position-history/
Retrieve fill-level history for a single closed position (one UUID fromGET /perpetual/position-history). Results are cursor-paginated over the underlying trade fills for that position (chronological order). Summary fields for the position itself are available on the list endpoint item with the same id.
Authentication: Required (JWT or API Key,
read:futures scope). Owner is the authenticated wallet; must match the perpetuals account for app_session_id.
Query Parameters:
Pagination (
cursor / next_cursor):
- The server advances in trade execution order (
executed_atascending, then stableidtie-break). next_cursoris a tuple string:<RFC3339Nano>|<uint64 trade row id>(UTC in the timestamp part). Pass it back ascursorto fetch the next window.has_moreistruewhen more trades exist after this page; whenfalse,next_cursoris typically empty.
Status Codes:
200- Position history detail retrieved successfully400- Missingapp_session_id, missing pathid, invalidpage_size(non-positive when supplied), or invalid position UUID401- Authentication failed or missing wallet in context403- Permission denied (wallet not owner ofapp_session_id, or position belongs to another account)404- Position not found (or no history payload)409- Position is not closed (failed_precondition— open positions have no fill history on this route)500- Internal server error (including malformedcursorin some deployments)
POST /perpetual/order
Create a new perpetuals order.Authentication: Required
direction is long or short):
direction to the leg you are trading and use reduce_only to close.
Request Parameters:
Leverage: Also configured via
POST /perpetual/leverage before the first order. Inspect GET /perpetual/accounts (initial_leverages) for current settings.
> Margin mode: All perpetual positions use cross margin. Passing margin_mode in the order request is not accepted.
Response:
Status Codes:
200- Order created successfully400- Invalid request parameters, validation failed, or the order was rejected (e.g. insufficient margin)401- Authentication failed500- Internal server error
400 — validation or rejection, same family as other trading routes):
error: Machine-readable code (snake_case), e.g.insufficient_margin,lock_funds_rejected,validation_failed.message: Human-readable detail.
DELETE /perpetual/order
Cancel an existing perpetuals order. > Known Issue: The API returns200 with success message, but the order may remain in wait state. Cancel functionality is not reliably working.
Authentication: Required
Response:
200- Cancellation request sent successfully400- Invalid request or missing parameters401- Authentication failed500- Internal server error
DELETE /perpetual/orders
Cancel all open perpetuals orders for an account, optionally limited to one market.Authentication: Required
Behavior: The server lists open orders, then dispatches a cancellation for each one. Trigger orders in
trigger_wait / trigger_triggered are also cancelled (same pattern as DELETE /perpetual/order).
Response (200):
Status Codes:
200- Listing and dispatch completed (checkfailed_countfor partial publish failures)400- Invalid JSON or missingapp_session_id401- Authentication failed500- Failed to list open orders
GET /perpetual/orders
Retrieve perpetuals order history with pagination. Each order’sdirection is stored as returned (long or short) — same idea as GET /perpetual/open_orders.
Authentication: Required
Request:
Status Codes:
200- Orders retrieved successfully400- Invalid query parameters (including malformedcursor)401- Authentication failed500- Internal server error
GET /perpetual/open_orders
Retrieve open (unfilled) perpetuals orders. Returns only orders that are currently active in the order book.direction on each row is long or short.
Authentication: Required
Request:
Note: This endpoint only returns orders with open states (
wait, pending). For complete order history including filled and cancelled orders, use /perpetual/orders.
Status Codes:
200- Open orders retrieved successfully400- Invalid query parameters (including malformedcursor)401- Authentication failed500- Internal server error
GET /perpetual/trades
Retrieve perpetuals trade history with pagination. Returns only the user’s own trades with privacy-focused response format.Authentication: Required
Request:
Note: The API response only exposes the user’s own order UUID and does not expose counterparty information for privacy reasons. User-relative flags (
is_buyer, is_maker) indicate the user’s role in the trade.
Status Codes:
200- Trades retrieved successfully400- Invalid query parameters (including malformedcursor)401- Authentication failed500- Internal server error
GET /perpetual/funding-rate/:symbol
Retrieve the current funding rate for a specific perpetuals market, plus the previous funding interval when available.Authentication: Not required (public endpoint)
Request:
Status Codes:
200- Funding rate retrieved successfully400- Invalid symbol or validation failed500- Internal server error
GET /perpetual/funding-rates
Retrieve funding rate history with pagination.Authentication: Not required (public endpoint)
Request (cursor first page):
Status Codes:
200- Funding rates retrieved successfully400- Invalid query parameters (including malformedcursor)500- Internal server error
GET /perpetual/account/funding-payments
Retrieve funding payment history for the specified app session with pagination.Authentication: Required
Request:
Status Codes:
200- Funding payments retrieved successfully400- Invalid query parameters (including malformedcursor) or missing app_session_id401- Authentication failed500- Internal server error
GET /perpetual/position/funding-payments
Retrieve funding payment history for a specific position within the specified app session, with pagination.Authentication: Required
Request:
/perpetual/account/funding-payments (array of funding payment objects with pagination metadata)
Status Codes:
200- Funding payments retrieved successfully400- Invalid query parameters (including malformedcursor) or missing position_id/app_session_id401- Authentication failed500- Internal server error