Perpetuals Trading API
Perpetuals API: positions, orders, leverage, margin, funding, and history.
The perpetuals trading API provides endpoints for managing cross-margin perpetual futures accounts, placing and canceling orders, monitoring positions, and retrieving trade history. All perpetuals accounts use cross-margin model where collateral is shared across all positions.
GET /perpetual/exchangeInfo
Retrieve exchange information for perpetuals markets including available markets and their details.
Authentication: Not required
maker_fee_rate and taker_fee_rate here are outdated. The values returned in exchangeInfo are static, indicative defaults and do not reflect the fees actually applied to your account (fee tiers, promotions, etc.). For the authoritative, account-specific rates always use GET /perpetual/account/market-fee-rate.
Response:
{
"timezone": "UTC",
"server_time": 1640995200000,
"symbols": [
{
"symbol": "BTCYTEST.USD-PERP",
"status": "active",
"base_asset_name": "Bitcoin",
"base_asset": "BTC",
"quote_asset_name": "US Dollar",
"quote_asset": "USD",
"amount_precision": 8,
"price_precision": 8,
"amount_display_precision": 8,
"price_display_precision": 8,
"maker_fee_rate": "0.001",
"taker_fee_rate": "0.002",
"max_allowed_leverage": "100",
"maintenance_margin_rate": "0.007",
"filters": [
{"filter_type": "PRICE_FILTER", "config": {"tick_size": "0.01", "price_min_ratio": "0.9", "price_max_ratio": "1.1"}},
{"filter_type": "LOT_SIZE", "config": {"step_size": "0.001", "min_qty": "0.001", "max_qty": "999999999"}},
{"filter_type": "MIN_NOTIONAL", "config": {"min_notional": "1"}},
{"filter_type": "DEPTH_MERGE", "config": {"depth_level": ["0.001", "0.01", "0.1", "1"]}}
]
}
]
}Response Fields:
timezone
string
Exchange timezone
server_time
integer
Current server timestamp in milliseconds
symbols
array
Array of available perpetuals markets
symbols[].symbol
string
Trading symbol name (e.g., "BTCYTEST.USD-PERP")
symbols[].status
string
Market status (e.g., "active")
symbols[].base_asset_name
string
Display name for base asset
symbols[].base_asset
string
Base asset symbol (e.g., "BTC")
symbols[].quote_asset_name
string
Display name for quote asset
symbols[].quote_asset
string
Quote asset symbol (e.g., "USD")
symbols[].amount_precision
integer
Decimal precision for amount (base asset)
symbols[].price_precision
integer
Decimal precision for price (quote asset)
symbols[].amount_display_precision
integer
Display precision for amount in UI
symbols[].price_display_precision
integer
Display precision for price in UI
symbols[].maker_fee_rate
decimal string
⚠️ Outdated — static indicative default, not your account's effective rate. Use GET /perpetual/account/market-fee-rate.
symbols[].taker_fee_rate
decimal string
⚠️ Outdated — static indicative default, not your account's effective rate. Use GET /perpetual/account/market-fee-rate.
symbols[].max_allowed_leverage
decimal string
Max allowed leverage (e.g., "100")
symbols[].maintenance_margin_rate
decimal string
Maintenance margin rate (MMR) for this market (e.g., "0.007" = 0.7%). Tiered maintenance on positions may still compute maintenance_margin from brackets.
symbols[].filters
array
Trading rules (PRICE_FILTER, LOT_SIZE, MIN_NOTIONAL, DEPTH_MERGE)
Status Codes:
200- Exchange information retrieved successfully500- Internal server error
Perpetuals Calculation Formulas
For frontend display (margin ratio, break-even price, ROI %, etc.), see perpetuals-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
List pagination
Perpetual list endpoints use opaque cursor pagination.
Query parameters (where noted on each endpoint):
use_cursor
boolean
No
true
Set true to use cursor pagination (on the first request)
cursor
string
No
—
Opaque continuation token from the previous response's next_cursor. Omit on the first page
page_size
integer
No
see each endpoint
Items per page
Response fields:
next_cursor
string
Token to pass as cursor for the next page; empty when no more pages
has_more
boolean
Whether another page exists
page_size
integer
Items per page
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)
Query Parameters:
app_session_id
string
Yes
—
Perpetuals account app session ID
market
string
Yes
—
Market symbol (e.g., BTCUSDT)
Response:
Response Fields:
The response is a JSON array containing a single object for the requested market:
app_session_id
string
Application session identifier (from request parameter)
market
string
Market symbol
maker_fee_rate
decimal string
Effective maker fee rate
taker_fee_rate
decimal string
Effective taker fee rate
source
string
Origin of the effective fee rate (e.g., fee_tier)
fee_tier_version
integer
Version of the fee tier configuration applied
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
Response:
Response Fields:
id
string
Unique perpetuals account identifier (UUID)
app_session_id
string
Application session identifier
owner
string
Owner's Ethereum wallet address
state
string
Account state (active, closed)
opened_at
string
Account creation timestamp
total_account_balance
decimal string
Sum of all collateral balances
total_unrealized_pnl
decimal string
Total unrealized PnL across all positions
total_account_equity
decimal string
Total account equity (balance + unrealized PnL)
total_allocated_margin
decimal string
Total margin allocated to positions (historical name; same numeric value as total_locked_balance)
total_locked_balance
decimal string
Sum of locked collateral across all assets (orders + position margin); same value as total_allocated_margin
total_maintenance_margin
decimal string
Total maintenance margin required
available_balance
decimal string
(Account-level.) Balance available for new positions or withdrawals. Includes unrealized PnL (total balance − allocated/locked + unrealized PnL). Not the max you can transfer perp→spot; use transferable_balances or balances[].max_transfer_out for that cap.
transferable_balances
object
(optional) Map of asset_symbol → decimal string: max amount the user may transfer perpetuals → spot for that collateral asset (closing-fee reserve; 80% cap when cross-margin positions exist). Omitted when there are no balance rows.
balances
array
Array of collateral balances
balances[].asset_symbol
string
Collateral asset symbol (e.g., "USDT")
balances[].asset_name
string
Display name (when known)
balances[].total_balance
decimal string
Total balance for this asset
balances[].allocated_balance
decimal string
Margin allocated to positions (historical name; same numeric value as locked_balance)
balances[].locked_balance
decimal string
Locked collateral for this asset (orders + position margin); same value as allocated_balance
balances[].available_balance
decimal string
(Per-asset.) Available for this asset. Includes unrealized PnL (total − locked + unrealized PnL; in single-collateral the PnL is attributed to that asset).
balances[].max_transfer_out
decimal string
Max user perp→spot transfer for this asset (may be lower than available_balance when open positions require a closing-fee reserve or cross-margin transfer cap applies).
balances[].total_balance_usd
decimal string
Total balance valued in stablecoin (USD/USDT); "0" when no price
balances[].allocated_balance_usd
decimal string
Allocated/locked margin valued in stablecoin; "0" when no price
balances[].locked_balance_usd
decimal string
Same as allocated_balance_usd (locked collateral in USD terms)
balances[].available_balance_usd
decimal string
Available balance valued in stablecoin; "0" when no price
balances[].last_updated
string
Last balance update timestamp
initial_leverages
object
(optional) Map of market → leverage string (e.g. "10"). Only present when the account has per-market settings.
positions
array
Array of open positions. May include two rows for the same market (one long, one short), since long and short legs are tracked separately.
positions[].uuid
string
Unique position identifier (always present)
positions[].market
string
Trading market (e.g., "BTCYTEST.USD-PERP")
positions[].direction
string
Position direction (long or short)
positions[].amount
decimal string
Position size (always positive)
positions[].entry_price
decimal string
Average entry price
positions[].mark_price
decimal string
Current mark price
positions[].notional_value
decimal string
Current notional value (amount x mark_price)
positions[].leverage
decimal string
Leverage multiplier
positions[].unrealized_pnl
decimal string
Unrealized profit/loss
positions[].realized_pnl
decimal string
Realized profit/loss from this position
positions[].total_pnl
decimal string
Total profit/loss (unrealized + realized)
positions[].allocated_margin
decimal string
Margin allocated to this position
positions[].maintenance_margin
decimal string
Maintenance margin requirement
positions[].liquidation_price
decimal string
Liquidation price (calculated by backend for cross-margin positions)
positions[].margin_asset
string
Collateral asset for margin calculation
positions[].locked_amount
decimal string
Amount currently locked
positions[].available_amount
decimal string
Amount available
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
Account creation completes shortly after this call returns
200. The account does not exist immediately; pollGET /perpetual/accountuntil it returns a result (typically a few seconds).
Request Body:
Request Parameters:
app_session_id
string
Yes
—
Application session ID for the new perpetual account (typically same as spot account ID)
owner
string
No
default: authenticated user
Owner wallet address
Response:
Response Fields:
app_session_id
string
The app session ID of the created account
owner
string
Owner wallet address
message
string
Status message
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
Notes:
The
app_session_idshould typically match the user's spot account ID to allow seamless transfersThe 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
Query Parameters:
app_session_id
string
Yes
—
Perpetuals account app session ID
Request:
Response:
Response Fields: Same as /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)
Request Body:
Request Fields:
app_session_id
string
Yes
—
Perpetuals account app session ID
Response (200):
Response Fields:
app_session_id
string
Application session identifier (from request body)
muted_until
string
RFC3339 UTC timestamp until which liquidation warnings are muted
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
Query Parameters:
app_session_id
string
Yes
—
Perpetuals account app session ID
Request:
Response:
Response Fields:
asset_symbol
string
Collateral asset symbol
asset_name
string
Display name (when known)
total_balance
decimal string
Total balance for this asset
allocated_balance
decimal string
Margin allocated to positions (historical name; same numeric value as locked_balance)
locked_balance
decimal string
Locked collateral for this asset (orders + position margin); same value as allocated_balance
available_balance
decimal string
Balance available for new positions (includes unrealized PnL share for this asset)
max_transfer_out
decimal string
Max user perp→spot transfer for this asset (same as transferable_balances[asset] on GET /perpetual/account)
total_balance_usd
decimal string
Total balance valued in stablecoin (USD/USDT); "0" when no price
allocated_balance_usd
decimal string
Allocated/locked margin valued in stablecoin; "0" when no price
locked_balance_usd
decimal string
Same as allocated_balance_usd (locked collateral in USD terms)
available_balance_usd
decimal string
Available balance valued in stablecoin; "0" when no price
last_updated
string
Last balance update timestamp
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)
Request:
Response:
Response Fields:
symbol
string
Asset symbol
name
string
Display name
decimals
integer
Decimal precision for min transfer amount logic (10^(-decimals))
is_active
boolean
Whether this asset is currently enabled for transfer
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 increaseNegative
amount→ balance decrease
Authentication: Required
Query Parameters:
app_session_id
string
Yes
—
Perpetuals account app session ID
type
string
No
"", funding_fee, transfer, fee, realized_pnl, liquidation, adl
High-level transaction type filter (see mapping below)
market
string
No
—
Market filter (e.g. BTC-USDT-PERP)
asset
string
No
—
Asset symbol to filter by (e.g. margin asset symbol)
start_time
integer
No
Unix timestamp in seconds (UTC)
Inclusive range start. See Time range below.
end_time
integer
No
Unix timestamp in seconds (UTC)
Inclusive range end. See Time range below.
cursor
string
No
—
Opaque continuation token from the previous response's next_cursor. Omit on the first page.
page_size
integer
No
default 50, max 100
Number of items per page
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.
Time range:
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):
Neither start_time nor end_time
[now − 30d, now]
start_time only
[start_time, now]
end_time only
[end_time − 30d, end_time]
Both
[start_time, end_time] (if start_time > end_time, start is reset to end_time − 30d)
The time window is applied on the transaction time of each event.
Request (explicit time range):
Request (default last 30 days — omit start_time and end_time; cursor first page):
Request (cursor page 2):
Response:
Pagination: Cursor only. Send 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:
items
array
Array of transaction history records
items[].transaction_id
integer
Internal transaction identifier
items[].transaction_time
string
Transaction timestamp in RFC3339 format
items[].transaction_type
string
Low-level transaction type (e.g., FUNDING_FEE_IN, TRANSFER_OUT, FEE, REALIZED_PNL, LIQUIDATION, ADL_COUNTERPARTY_CLOSE)
items[].market
string
Related market symbol when applicable; empty string for non-market-specific events (e.g. some transfers)
items[].asset
string
Asset symbol impacted by the transaction
items[].amount
decimal string
Signed amount from the user's perspective (positive = balance increase, negative = balance decrease)
has_more
boolean
Whether another page exists
next_cursor
string
Opaque next-page token (empty when no more pages)
page_size
integer
Number of items requested per page
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’s direction 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
Query Parameters:
app_session_id
string
Yes
—
Perpetuals account app session ID
Request:
Response:
Response Fields:
uuid
string
Unique position identifier (always present)
market
string
Trading market (e.g., "BTCYTEST.USD-PERP")
direction
string
Position direction (long or short)
amount
decimal string
Position size (always positive)
entry_price
decimal string
Average entry price
mark_price
decimal string
Current mark price used for PnL calculation
notional_value
decimal string
Current notional value (amount x mark_price)
leverage
decimal string
Leverage multiplier
unrealized_pnl
decimal string
Current unrealized profit/loss
realized_pnl
decimal string
Realized profit/loss from partial closes
total_pnl
decimal string
Total profit/loss (unrealized + realized)
allocated_margin
decimal string
Margin allocated to this position
maintenance_margin
decimal string
Maintenance margin requirement
liquidation_price
decimal string
Liquidation price (calculated by backend for cross-margin positions)
margin_asset
string
Collateral asset (e.g., "USDT")
margin_mode
string
Margin mode (always cross)
locked_amount
decimal string
Amount currently locked
available_amount
decimal string
Amount available
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 as POST /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.
Position mode: Each closable leg uses 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.
Request Body:
Request Fields:
app_session_id
string
Yes
—
Perpetuals account app session ID
market
string
No
—
When present, only this market's positions are closed; must exist in perpetuals exchange info when the market cache is configured
Response (200):
Response Fields:
message
string
Summary for the client
positions_submitted
integer
Number of close orders successfully dispatched
failed_count
integer
Number of legs that failed validation or submission (see failed)
remaining_count
integer
Number of additional closable legs not processed due to per-request cap
partial
boolean
true when remaining_count > 0 (caller should invoke again to continue)
orders
array
Successful items
orders[].market
string
Market of the submitted close order (from the position row)
orders[].direction
string
Position direction (long or short)
orders[].margin_mode
string
Margin mode (always cross)
orders[].order_uuid
string
UUID of the submitted order
failed
array
Per-leg failures
failed[].market
string
Market of the failed leg
failed[].direction
string
(optional) Position direction (long or short)
failed[].margin_mode
string
(optional) Margin mode (always cross)
failed[].error
string
Failure description
failed[].error_code
string
(optional) Client-visible error code, same idea as POST /perpetual/order
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, typically 10) 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.
Request Body:
Request Fields:
app_session_id
string
Yes
—
Perpetuals account app session ID
market
string
Yes
—
Market symbol (e.g., BTCYTEST.USD-PERP). Trimmed and uppercased by the server
leverage
number or string
Yes
>= 1 and <= max_allowed_leverage for the market
Leverage multiplier (e.g., 20 or "20")
Response (200):
Response Fields:
success
boolean
Whether the operation succeeded
message
string
Human-readable message
market
string
Market symbol for which leverage was set
leverage
decimal string
Confirmed leverage
Error responses (non-exhaustive; success is false when HTTP status is not 200):
HTTP
error (when present)
Meaning
400
invalid_request_format
Malformed JSON
400
missing_app_session_id
app_session_id empty
400
missing_market
market empty
400
invalid_leverage_value
Leverage < 1
400
no_permitted
Account not found or not accessible for this wallet
400
leverage_exceeds_max, order_exists, insufficient_balance, leverage_exceeds_safe_margin, account_not_active, set_leverage_failed, …
See message for detail.
401
missing_wallet_address
Authenticated context has no wallet
503
service_unavailable
Service temporarily unavailable for this user
500
internal_error
Internal server error
Error body (400 from business rules):
Status Codes:
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 matches sort_by=closed_at and sort_dir=desc with a stable secondary sort on internal row id.
Authentication: Required
Query Parameters:
app_session_id
string
Yes
—
Perpetuals account app session ID
market
string
No
—
Exact market symbol filter; normalized to uppercase before lookup (e.g. btcytest.usd-perp matches BTCYTEST.USD-PERP)
opened_from
string
No
RFC3339 or RFC3339Nano
Inclusive lower bound on opened_at
opened_to
string
No
RFC3339 or RFC3339Nano
Inclusive upper bound on opened_at
closed_from
string
No
RFC3339 or RFC3339Nano
Inclusive lower bound on closed_at
closed_to
string
No
RFC3339 or RFC3339Nano
Inclusive upper bound on closed_at
sort_by
string
No
opened_at, closed_at (default closed_at)
Sort field; other values → 400
sort_dir
string
No
asc, desc (default desc)
Sort direction; other values → 400
cursor
string
No
—
Opaque continuation token from the previous response's next_cursor. Omit on the first page.
page_size
integer
No
1–100 (default 50)
Number of positions per page; out-of-range when supplied → 400
Request:
Response:
Pagination: Cursor only (see List pagination). Malformed cursor → 400 / invalid_cursor.
Response Fields:
positions
array
Array of closed position objects
positions[].id
string
Position ID (UUID)
positions[].perps_account_id
string
Perpetuals account ID (UUID)
positions[].market
string
Trading market
positions[].direction
string
Position direction (long or short)
positions[].amount
decimal string
Position size (amount)
positions[].entry_price
decimal string
Average entry price
positions[].leverage
decimal string
Leverage multiplier used
positions[].allocated_margin
decimal string
Margin that was allocated
positions[].realized_pnl
decimal string
Final realized profit/loss
positions[].close_reason
string
Close reason (normal, liquidated, adl)
positions[].exit_price
decimal string
Weighted-average close price over all close fills
positions[].closed_quantity
decimal string
Total quantity closed for the position lifecycle
positions[].max_held
decimal string
Peak absolute held quantity during the position lifecycle
positions[].initial_margin
decimal string
Margin at first open (used for ROI)
positions[].total_trading_fee
decimal string
Sum of linked trade fees for this position lifecycle
positions[].net_funding_fee
decimal string
Signed cumulative funding for this position lifecycle (positive = received by user, negative = paid by user)
positions[].liquidation_price
decimal string
Liquidation trigger snapshot for liquidated positions (else zero/empty)
positions[].margin_mode
string
Margin mode (always cross)
positions[].pnl_ratio
decimal string
Realized ROE% = realized_pnl / initial_margin * 100
positions[].opened_at
string
Position open timestamp
positions[].updated_at
string
Last update timestamp
positions[].closed_at
string
Position close timestamp
next_cursor
string
Opaque next-page token (empty when no more pages)
has_more
boolean
Whether another page exists
page_size
integer
Number of positions per page
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/{id}
Retrieve fill-level history for a single closed position (one UUID from GET /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.
Path Parameters:
id
string
Yes
—
Closed position UUID
Query Parameters:
app_session_id
string
Yes
—
Perpetuals account app session ID
page_size
integer
No
positive integer, default 200, values above 500 clamped to 500
Number of underlying trades loaded per request
cursor
string
No
RFC3339Nano|uint64 (pipe-separated)
Opaque pagination cursor from the previous response's next_cursor. Omit on the first page. Malformed values typically surface as 500 from the backend rather than 400.
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.
Request (first page):
Request (next page):
Response:
Response Fields:
fills
array
Per-fill rows derived from trades in the current window (open and close perspectives are combined in one list; each row's kind is open or close)
fills[].id
string
Trade UUID
fills[].direction
string
Position leg direction (long or short)
fills[].amount
decimal string
Fill amount
fills[].price
decimal string
Fill price
fills[].pnl
decimal string
Fill realized PnL (0 for open fills)
fills[].fee
decimal string
Fee paid for that fill from this account perspective
fills[].fee_currency
string
Fee currency
fills[].exec_type
string
Execution source (trade, liquidation, liquidation_takeover, adl)
fills[].kind
string
Fill role (open or close)
fills[].executed_at
string
Fill execution timestamp (RFC3339 / RFC3339Nano)
next_cursor
string
Cursor for the next request (empty when there is no next page)
has_more
boolean
Whether more trades exist after this page
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
Request Body (direction is long or short):
Position legs: Long and short legs are tracked separately. Set
directionto the leg you are trading and usereduce_onlyto close.
Request Parameters:
app_session_id
string
Yes
—
Perpetuals account app session ID
market
string
Yes
—
Trading market (e.g., "BTCYTEST.USD-PERP")
side
string
Yes
buy, sell
Order side
direction
string
Yes
long, short
Position leg direction
type
string
Yes
limit, market, trigger_limit, trigger_market
Order type
amount
string
Yes
—
Order amount in base asset (decimal format)
price
string
No
required for limit orders
Limit price
leverage
string
Yes
—
Sent with the request; effective margin rules still follow account/market settings from POST /perpetual/leverage
time_in_force
string
No
gtc, ioc, fok (default gtc for limit orders)
Time in force — Good-Till-Cancelled, Immediate-Or-Cancel, Fill-Or-Kill
reduce_only
boolean
No
default false
If true, order can only reduce/close an existing position
client_order_id
string
No
—
Client-supplied order id
trigger_price
string
No
—
For trigger / stop / take-profit style orders (see OpenAPI)
trigger_type
string
No
—
For trigger / stop / take-profit style orders (see OpenAPI)
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_modein the order request is not accepted.
Response:
Response Fields:
order_uuid
string
UUID of the created order
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
Error response (typical for 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 returns
200with success message, but the order may remain inwaitstate. Cancel functionality is not reliably working.
Authentication: Required
Request Body:
Request Parameters:
app_session_id
string
Yes
—
Perpetuals account app session ID
market
string
Yes
—
Trading market
order_uuid
string
Yes
—
UUID of the order to cancel
Response:
Status Codes:
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
Request Body:
Request Fields:
app_session_id
string
Yes
—
Perpetuals account app session ID
market
string
No
—
When empty or omitted, open orders in all markets are targeted; when set, only orders for that exact market string (as stored on open orders)
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):
When there are no open orders:
Response Fields:
message
string
Summary
total_orders
integer
Open orders found in the listing pass (omitted when count is zero in the "no open orders" response)
canceled_count
integer
Cancel requests successfully dispatched
failed_count
integer
Cancel requests that failed to dispatch
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’s direction is stored as returned (long or short) — same idea as GET /perpetual/open_orders.
Authentication: Required
Query Parameters:
app_session_id
string
Yes
—
Perpetuals account app session ID
market
string
No
—
Exact filter by trading market
market_like
string
No
—
Fuzzy filter by market (contains, case-insensitive)
cursor
string
No
—
Opaque continuation token from the previous response's next_cursor. Omit on the first page.
page_size
integer
No
default 50, max 100
Number of orders per page
Request:
Response:
Response Fields:
orders
array
Array of order objects
orders[].id
string
Internal order record ID
orders[].order_id
string
Order UUID
orders[].app_session_id
string
Perpetuals account app session ID
orders[].market
string
Trading market
orders[].price
decimal string
Order price
orders[].amount
decimal string
Current order amount (remaining to fill)
orders[].origin_amount
decimal string
Original order amount
orders[].fill_amount
decimal string
Amount that has been filled
orders[].notional
decimal string
Notional value (origin_amount x price)
orders[].side
string
Order side (buy or sell)
orders[].type
string
Order type (limit, market)
orders[].state
string
Order state (pending, wait, done, canceled)
orders[].event
string
Last order event
orders[].reason
string
Reason for last state change
orders[].leverage
decimal string
Leverage multiplier
orders[].created_at
string
Order creation timestamp
orders[].updated_at
string
Last update timestamp
orders[].completed_at
string
Completion timestamp (empty for open orders)
page_size
integer
Number of items per page
next_cursor
string
Cursor pagination token (empty when no more pages)
has_more
boolean
Whether another page exists
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
Query Parameters:
app_session_id
string
Yes
—
Perpetuals account app session ID
market
string
No
—
Exact filter by trading market
market_like
string
No
—
Fuzzy filter by market (contains, case-insensitive)
cursor
string
No
—
Opaque continuation token from the previous response's next_cursor. Omit on the first page.
page_size
integer
No
default 50, max 100
Number of orders per page
Request:
Response:
Response Fields:
orders
array
Array of open order objects (same format as /perpetual/orders)
orders[].id
string
Internal order record ID
orders[].order_id
string
Order UUID
orders[].app_session_id
string
Perpetuals account app session ID
orders[].market
string
Trading market
orders[].price
decimal string
Order price
orders[].amount
decimal string
Current order amount (remaining to fill)
orders[].origin_amount
decimal string
Original order amount
orders[].fill_amount
decimal string
Amount that has been filled
orders[].notional
decimal string
Notional value (origin_amount x price)
orders[].side
string
Order side (buy or sell)
orders[].type
string
Order type (limit, market)
orders[].state
string
Order state (typically wait for open orders)
orders[].event
string
Last order event
orders[].reason
string
Reason for last state change
orders[].leverage
decimal string
Leverage multiplier
orders[].created_at
string
Order creation timestamp
orders[].updated_at
string
Last update timestamp
orders[].completed_at
string
Completion timestamp (empty for open orders)
page_size
integer
Number of items per page
next_cursor
string
Cursor pagination token (empty when no more pages)
has_more
boolean
Whether another page exists
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
Query Parameters:
app_session_id
string
Yes
—
Perpetuals account app session ID
market
string
No
—
Exact filter by trading market
market_like
string
No
—
Fuzzy filter by market (contains, case-insensitive)
start_time
string
No
RFC3339 or RFC3339Nano
Filter executed_at >= start_time
end_time
string
No
RFC3339 or RFC3339Nano
Filter executed_at <= end_time
cursor
string
No
—
Opaque continuation token from the previous response's next_cursor. Omit on the first page.
page_size
integer
No
default 50, max 100
Number of trades per page
Request:
Response:
Response Fields:
trades
array
Array of trade objects
trades[].id
string
Trade record ID
trades[].order_uuid
string
User's own order UUID in this trade (matches create order response)
trades[].market
string
Trading market
trades[].base_asset
string
Base asset symbol (e.g., "BTC")
trades[].quote_asset
string
Quote asset symbol (e.g., "USD")
trades[].amount
decimal string
Trade amount in base asset
trades[].price
decimal string
Trade execution price
trades[].is_buyer
boolean
Whether the user was the buyer
trades[].is_maker
boolean
Whether the user was the maker/liquidity provider
trades[].fee
decimal string
Trading fee charged to the user
trades[].exec_type
string
Execution source: trade (normal matched trade), liquidation (IOC liquidation fill or cross liquidation netting), liquidation_takeover (position taken over for force-settlement during liquidation), adl (auto-deleveraging)
trades[].executed_at
string
Trade execution timestamp
trades[].created_at
string
Trade record creation timestamp
page_size
integer
Number of items per page
next_cursor
string
Cursor pagination token (empty when no more pages)
has_more
boolean
Whether another page exists
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)
Path Parameters:
symbol
string
Yes
—
Trading symbol (e.g., "BTCYTEST.USD-PERP")
Request:
Response:
Response Fields:
current_funding_rate
object
Current funding rate object
current_funding_rate.market
string
Trading market symbol
current_funding_rate.funding_rate
decimal string
Current funding rate
current_funding_rate.premium_index
decimal string
Premium index value
current_funding_rate.mark_price
decimal string
Current mark price
current_funding_rate.index_price
decimal string
Current index price
current_funding_rate.interval_start
string
Start of the current funding interval (ISO 8601 format)
current_funding_rate.interval_end
string
End of the current funding interval (ISO 8601 format)
current_funding_rate.created_at
string
When the current funding rate was recorded (ISO 8601 format)
previous_funding_rate
object
Previous funding interval object (may be omitted if not available)
previous_funding_rate.market
string
Trading market symbol
previous_funding_rate.funding_rate
decimal string
Previous interval funding rate
previous_funding_rate.premium_index
decimal string
Previous interval premium index
previous_funding_rate.mark_price
decimal string
Mark price used for previous interval
previous_funding_rate.index_price
decimal string
Index price used for previous interval
previous_funding_rate.interval_start
string
Start of the previous funding interval (ISO 8601 format)
previous_funding_rate.interval_end
string
End of the previous funding interval (ISO 8601 format)
previous_funding_rate.created_at
string
When the previous funding rate was recorded (ISO 8601 format)
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)
Query Parameters:
symbol
string
No
—
Filter by trading market
cursor
string
No
—
Opaque continuation token from the previous response's next_cursor. Omit on the first page.
page_size
integer
No
default 50, max 100
Number of rates per page
Request (cursor first page):
Request (next page):
Response:
Response Fields:
funding_rates
array
Array of funding rate objects (same structure as /perpetual/funding-rate/:symbol)
page_size
integer
Number of rates per page
next_cursor
string
Cursor pagination token (empty when no more pages)
has_more
boolean
Whether another page exists
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
Query Parameters:
app_session_id
string
Yes
—
App session identifier passed by frontend
interval_start
string
No
ISO 8601 format
Filter by funding interval start time
cursor
string
No
—
Opaque continuation token from the previous response's next_cursor. Omit on the first page.
page_size
integer
No
default 50, max 100
Number of payments per page
Request:
Response:
Response Fields:
funding_payments
array
Array of funding payment objects
funding_payments[].id
string
Funding payment ID (UUID)
funding_payments[].market
string
Trading market
funding_payments[].account_id
string
Perpetuals account ID (UUID)
funding_payments[].position_id
string
Position ID (UUID)
funding_payments[].side
string
Position side (long or short)
funding_payments[].position_size
decimal string
Position size at the time of funding payment
funding_payments[].mark_price
decimal string
Mark price at the time of funding payment
funding_payments[].funding_rate
decimal string
Funding rate applied
funding_payments[].funding_amount
decimal string
Funding payment amount (positive for long positions receiving payment, negative for paying)
funding_payments[].interval_start
string
Start of the funding interval (ISO 8601 format)
funding_payments[].interval_end
string
End of the funding interval (ISO 8601 format)
funding_payments[].created_at
string
When the funding payment was recorded (ISO 8601 format)
next_cursor
string
Opaque next-page token (empty when no more pages)
has_more
boolean
Whether another page exists
page_size
integer
Number of payments per page
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
Query Parameters:
app_session_id
string
Yes
—
App session identifier passed by frontend
position_id
string
Yes
—
Position ID (UUID)
interval_start
string
No
ISO 8601 format
Filter by funding interval start time
cursor
string
No
—
Opaque continuation token from the previous response's next_cursor. Omit on the first page.
page_size
integer
No
default 50, max 100
Number of payments per page
Request:
Response: Same format as /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
Last updated
Was this helpful?