Skip to main content
All mutating operations follow the create -> sign -> execute pattern through two unified endpoints. The action field determines the operation.
These endpoints are intended to be used via @lifi/perps-sdk. The typed data signing and submission flow is complex and best handled by the SDK.

POST /createAction

Build action payloads for signing. Returns an array of typedData payloads that must be signed before executing via POST /executeAction.
POST /v1/perps/createAction

Request Body

{
  "provider": "hyperliquid",
  "address": "0x1234567890abcdef1234567890abcdef12345678",
  "signerAddress": "0x5678901234abcdef5678901234abcdef56789012",
  "action": "placeOrder",
  "params": {
    "market": { "marketId": "BTC", "categoryId": "hyperliquid" },
    "side": "BUY",
    "type": "MARKET",
    "size": "0.1",
    "price": "95500.00",
    "leverage": 10,
    "takeProfit": { "triggerPrice": "100000.00" },
    "stopLoss": { "triggerPrice": "90000.00", "limitPrice": "89800.00" }
  }
}

Request Fields

FieldTypeRequiredDescription
providerstringYesProvider identifier (e.g. hyperliquid)
addressstringYesUser’s wallet address (account owner)
signerAddressstringNoAddress that will sign the payloads. For agent-signed actions (Hyperliquid trading) this must be the agent address. Defaults to address.
actionstringYesAction type (see table below)
paramsobjectYesAction-specific parameters

Action Types

ActionDescriptionParams
placeOrderPlace a new orderPlaceOrderParams
placeTriggerOrderPlace standalone TP/SLPlaceTriggerOrderParams
cancelOrderCancel one or more ordersCancelOrderParams
cancelAllOrdersCancel every open order on the accountCancelAllOrdersParams
modifyOrderModify existing ordersModifyOrderParams
updateLeverageChange leverage (and optionally margin mode) for a marketUpdateLeverageParams
updatePositionMarginAdd/remove position marginUpdatePositionMarginParams
withdrawalWithdraw fundsWithdrawalParams
depositFund the account via an L1 bridge transactionDepositParams
approveAgentAuthorize an agent walletApproveAgentParams
approveBuilderFeeApprove builder fee{} (empty)
accountModeSwitch the account’s operating mode (e.g. Hyperliquid abstraction variant, Lighter UTA/Simple). Accepts either signer; the backend dispatches to the right typed-data builder based on which key signs the request.AccountModeParams
accountTypeSwitch the account’s fee/latency tier (e.g. Lighter standard/premium). Omitted by providers with no tiering.AccountTypeParams
registerApiKeyRegister or rotate a Lighter API-key slotRegisterApiKeyParams
sendAssetTransfer assets between sub-exchangesSendAssetParams

MarketRef

Many action params use a market field with the MarketRef type:
FieldTypeRequiredDescription
marketIdstringYesProvider’s canonical, stringified market id that uniquely identifies the trading instrument (e.g., "BTC", "xyz:PURR", "@142"; numeric on Lighter)
categoryIdstringYesProvider category id (e.g., "hyperliquid", "xyz", "spot")

PlaceOrderParams

FieldTypeRequiredDescription
marketMarketRefYesTarget market
sidestringYesBUY or SELL
typestringYesOrderType — one of MARKET, LIMIT, STOP_MARKET, STOP_LIMIT, TAKE_PROFIT_MARKET, TAKE_PROFIT_LIMIT, TRIGGER_ONLY. Required — there is no default order type.
sizestringYesOrder size
pricestringYesLimit price (LIMIT) or slippage limit (MARKET). Required.
leverageintegerNoLeverage to set — integer ≥ 1 (generates updateLeverage action if different). Some providers require it when marginMode is set.
marginMode'ISOLATED' | 'CROSS'NoMargin mode for the position. Optional — the default when omitted differs per provider (see the provider’s section). Set explicitly to be unambiguous across providers.
reduceOnlybooleanNoOnly reduce position (default false)
timeInForcestringNoGTC (default), IOC, POST_ONLY, GTT
expiresAtstringNoUnix ms timestamp expiry for GTT orders
takeProfitTriggerOrderInputNoTake profit trigger
stopLossTriggerOrderInputNoStop loss trigger
TriggerOrderInput:
FieldTypeRequiredDescription
triggerPricestringYesPrice at which the order triggers
limitPricestringNoExecution limit price (market order if omitted)

PlaceTriggerOrderParams

Place standalone TP/SL on an existing position.
FieldTypeRequiredDescription
marketMarketRefYesTarget market
sidestringYesBUY or SELL
takeProfitTriggerOrderInputNoTake profit trigger
stopLossTriggerOrderInputNoStop loss trigger

CancelOrderParams

FieldTypeRequiredDescription
idsstring[]YesOrder IDs to cancel

ModifyOrderParams

FieldTypeRequiredDescription
modificationsModifyOrderInput[]YesArray of modifications
Each ModifyOrderInput:
FieldTypeRequiredDescription
idstringYesOrder ID to modify
pricestringNoNew limit price
sizestringNoNew order size
triggerPricestringNoNew trigger price
limitPricestringNoNew trigger limit price

UpdateLeverageParams

FieldTypeRequiredDescription
marketMarketRefYesTarget market
leverageintegerYesNew leverage value (integer ≥ 1)
marginMode'ISOLATED' | 'CROSS'NoMargin mode to apply alongside the leverage change. Optional — the default when omitted differs per provider (see the provider’s section).

UpdatePositionMarginParams

FieldTypeRequiredDescription
marketMarketRefYesTarget market
actionstringYesadd or remove
amountstringYesMargin amount

WithdrawalParams

FieldTypeRequiredDescription
destinationstringYesDestination address (e.g. Arbitrum L1 for Hyperliquid)
amountstringYesAmount to withdraw

ApproveAgentParams

FieldTypeRequiredDescription
agentAddressstringYesAgent wallet address to authorize
agentTtlMsnumberNoAgent approval TTL in milliseconds

AccountModeParams

Generic account-level operating-mode switch (e.g. Hyperliquid abstraction variants, Lighter UTA / Simple). The accepted mode values are provider-specific — read them from the corresponding setup / options descriptor on GET /providers (the descriptor’s params[].values array enumerates them). @lifi/perps-types intentionally does not encode the per-provider value list, so providers can add new modes without a types release.
FieldTypeRequiredDescription
modestringYesProvider-specific mode identifier (e.g. unifiedAccount, dexAbstraction, disabled on Hyperliquid)

AccountTypeParams

Generic account-level fee/latency tier switch (e.g. Lighter standard / premium). Providers without tiering omit the action entirely.
FieldTypeRequiredDescription
tierstringYesProvider-specific tier identifier

CancelAllOrdersParams

FieldTypeRequiredDescription
timeInForcenumberYes0 = immediate (cancel GTC), 1 = scheduled, 2 = abort scheduled
timestampMsnumberNoUnix milliseconds (required for scheduled cancels)

RegisterApiKeyParams

FieldTypeRequiredDescription
apiKeyIndexnumberYesAPI-key slot index to register (0-255). Reusing a fixed slot overwrites the old key.

DepositParams

FieldTypeRequiredDescription
amountstringYesHuman-readable token amount (e.g. "100.5")
tokenAddressstringYesERC-20 token address on the source chain
chainIdnumberYesChain ID of the source chain (e.g. 1 for Ethereum, 42161 for Arbitrum)

SendAssetParams

FieldTypeRequiredDescription
collateralstringYesCollateral type
sourceDexstringYesSource sub-exchange
destinationDexstringYesDestination sub-exchange
amountstringYesAmount to transfer

Response 201

{
  "actions": [
    {
      "action": "updateLeverage",
      "typedData": {
        "domain": { "..." },
        "types": { "..." },
        "primaryType": "...",
        "message": { "..." }
      }
    },
    {
      "action": "placeOrder",
      "typedData": { "..." }
    }
  ]
}
ActionStep is a discriminated union by structural shape — the variant depends on the action’s signingMethod on the provider descriptor:
VariantDiscriminating keyDescription
Eip712ActionSteptypedDataEIP-712 typed data to sign (Hyperliquid and other EVM dexes)
WasmBlobActionStepwasmSignParamsParameters for the provider’s WASM signer (Lighter and zk-rollup dexes)
EvmTxActionSteptxParamsOn-chain EVM transaction the SDK submits (e.g. Lighter deposit)
All variants carry the same action field (the ActionType from the request). The example above shows the EIP-712 variant; the wasmBlob variant carries wasmSignParams and the evmTx variant (e.g. deposit) carries txParams in place of typedData.

Response 400

Validation error.

POST /executeAction

Submit signed payloads from /createAction.
POST /v1/perps/executeAction

Request Body

{
  "provider": "hyperliquid",
  "address": "0x1234567890abcdef1234567890abcdef12345678",
  "action": "placeOrder",
  "actions": [
    {
      "action": "updateLeverage",
      "typedData": { "...typedData from createAction..." },
      "signature": "0xabcd1234..."
    },
    {
      "action": "placeOrder",
      "typedData": { "...typedData from createAction..." },
      "signature": "0xefgh5678..."
    }
  ]
}
FieldTypeRequiredDescription
providerstringYesProvider identifier
addressstringYesUser’s wallet address (account owner)
signerAddressstringNoAddress that signed the payloads. For agent-signed actions (Hyperliquid trading) this must be the agent address. Defaults to address.
actionstringYesAction type from the create request
actionsSignedActionStep[]YesSigned actions from /createAction
SignedActionStep mirrors ActionStep as a discriminated union — each variant carries the original payload plus its signed artefact:
VariantFields
Eip712SignedActionStepaction, typedData, signature (hex)
WasmBlobSignedActionStepaction, wasmSignParams, signedTx: { txType, txInfo, txHash }
EvmTxSignedActionStepaction, txParams, txHash (on-chain)
The example above shows the EIP-712 variant. Submit signed steps in the same shape and order they were returned by /createAction.

Response 202

{
  "results": [
    {
      "action": "updateLeverage",
      "success": true
    },
    {
      "action": "placeOrder",
      "success": true,
      "orderId": "12345678"
    }
  ]
}
Each ActionResult:
FieldTypeDescription
actionstringAction type
successbooleanWhether the action was accepted
orderIdstringOrder ID (for placeOrder and placeTriggerOrder)
errorstringError message if failed

Response 400

Validation error.

Response 401

Authentication error (invalid signature).

Response 422

Insufficient margin for the order.

Order details (SDK)

Single-order lookup is served by the SDK directly from each provider via getOrder — there is no LI.FI HTTP endpoint. The returned Order shape:
{
  "orderId": "12345678",
  "market": {
    "providerId": "hyperliquid",
    "id": "BTC",
    "categoryId": "hyperliquid",
    "baseAsset": { "providerId": "hyperliquid", "id": "BTC", "displaySymbol": "BTC", "logoURI": "https://assets.li.fi/tokens/btc.png" },
    "quoteAsset": { "providerId": "hyperliquid", "id": "USDC", "displaySymbol": "USDC", "logoURI": "https://assets.li.fi/tokens/usdc.png" }
  },
  "side": "BUY",
  "type": "MARKET",
  "price": "95500.00",
  "originalSize": "0.1",
  "remainingSize": "0.0",
  "filledSize": "0.1",
  "timeInForce": "GTC",
  "reduceOnly": false,
  "isTrigger": false,
  "status": "FILLED",
  "averagePrice": "95050.00",
  "createdAt": "2025-01-15T10:30:00Z",
  "updatedAt": "2025-01-15T10:30:01Z"
}

Order Schema

FieldTypeDescription
orderIdstringOrder ID
marketMarketDisplayMarket reference (providerId, id, categoryId, base/quote Asset) — see MarketDisplay
sidestringBUY or SELL
typestringMARKET, LIMIT, STOP_MARKET, STOP_LIMIT, TAKE_PROFIT_MARKET, TAKE_PROFIT_LIMIT, TRIGGER_ONLY
pricestringLimit price or execution price
originalSizestringOriginal order size
remainingSizestringUnfilled quantity
filledSizestringFilled quantity
timeInForcestringGTC, IOC, POST_ONLY, GTT
expiresAtstringExpiration time (GTT orders)
reduceOnlybooleanWhether reduce-only
isTriggerbooleanWhether this is a trigger order (TP/SL)
triggerPricestringTrigger activation price
triggerConditionstringABOVE or BELOW
statusstringOrder status (see below)
averagePricestringAverage fill price
createdAtstringISO 8601 creation timestamp
updatedAtstringISO 8601 last update timestamp

Order Status Values

StatusDescription
PENDINGSubmitted, not yet on orderbook
OPENResting on orderbook
PARTIALLY_FILLEDSome quantity filled
FILLEDFully filled
CANCELLEDCancelled by user
REJECTEDRejected by provider
EXPIREDGTT order expired
TRIGGEREDTrigger order activated (TP/SL)
SDK: getOrder()