action field determines the operation.
These endpoints are intended to be used via
@lifi/perps-sdk. The SDK is the supported integration path: it satisfies setup steps, exposes the recommended option of each choice without applying it, runs the steps in sequence, and makes the client-side venue calls. If you cannot use the SDK, see Integrating without the SDK.relay in GET /providers. Submit a signed step to POST /executeAction only when its action declares relay: API. A step with relay: CLIENT goes from the client to the venue, and nothing reaches LI.FI. See Integrating without the SDK for each CLIENT step.
POST /createAction
Build provider-specific authorization steps. Signed EIP-712, WASM, EVM, and HMAC steps continue toPOST /executeAction; a SiweActionStep or a client-only session step is completed directly by the provider plugin and never submitted to /executeAction.
Every provider action requires the address to have accepted the current terms. Until it has, createAction and executeAction fail with 401 / 2012 (TermsNotAccepted). Accept them first with metaAcceptTerms or metaOnboard, sent with provider: "meta".
Request Body
Request Fields
provider: "meta" routes metaAcceptTerms, metaOnboard, and metaCreateReferralCode to a provider-independent handler instead of a venue plugin. No other action accepts the "meta" provider.Action Types
MarketRef
Many action params use amarket field with the MarketRef type:
PlaceOrderParams
TriggerOrderInput:
Each provider reads
type and limitPrice as follows:
The backend does no slippage calculation. To calculate the
limitPrice of a Lighter MARKET leg, see Trigger Orders.
PlaceTriggerOrderParams
Place standalone TP/SL on an existing position.PlaceTwapOrderParams
Place a TWAP parent order that executes over a fixed duration.market, side, size, durationSeconds, and reduceOnly are provider-independent; the remaining fields are extras honoured only by the provider that advertises them on its placeTwapOrder action’s params descriptors (GET /providers) — a provider that does not advertise an extra ignores it.
CancelOrderParams
CancelTwapOrderParams
ModifyOrderParams
Lighter requiresid and size on every modification. It also requires a price: price for a regular order, or limitPrice for a trigger order. A Lighter modify transaction replaces the resting order wholesale. Lighter accepts 1 to 100 modifications per call. Lighter rejects type and rejects a modification that has both price and limitPrice.
Each
ModifyOrderInput:
UpdateLeverageParams
UpdatePositionMarginParams
WithdrawalParams
Lighter also accepts the legacy
assetId and route fields, and rejects them together with source.
ApproveAgentParams
AccountModeParams
Generic account-level operating-mode switch (Hyperliquid:disabled, unifiedAccount, portfolioMargin; Lighter: simpleTradingAccount, unifiedTradingAccount). The accepted mode values are provider-specific — read them from the params.mode of each entry in the options array of the corresponding setup step on GET /providers. @lifi/perps-types intentionally does not encode the per-provider value list, so providers can add new modes without a types release.
AccountTypeParams
Generic account-level fee tier switch (Lighterplus or premium). Providers without tiering omit the action entirely.
RevokeAgentParams
{}. The backend selects the target agent: LI.FI’s own leftover agent first, otherwise the earliest-expiring named agent. It returns no step when an agent slot is already free.
UpdateAssetCollateralParams
OnboardParams
CreateReferralCodeParams
CancelAllOrdersParams
RegisterApiKeyParams
DepositParams
SendAssetParams
Response 201
In this example, each typedData value is a string placeholder. The real value is an EIP-712 object with the keys domain, types, primaryType, and message.
ActionStep is a discriminated union by structural shape — the variant depends on the action’s signingMethod on the provider descriptor:
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. HmacActionStep is signed and submitted via executeAction. SiweActionStep and SessionActionStep carry no material submitted to executeAction: a signed SiweActionStep is exchanged for a venue session client-side, and a SessionActionStep carries no signable material at all — the SDK performs the venue call directly with its session token in both cases and skips executeAction. Ondo’s setReferrer is session-signed like a SessionActionStep, but is wire-shaped as a request-bearing HmacActionStep — the SDK submits its request directly with the session credential instead of HMAC-signing it, and also skips executeAction.
Responses
POST /executeAction
Submit signed payloads from/createAction.
Request Body
In this example, eachtypedData value is a string placeholder for the typedData object that /createAction returned for the same step. Each signature value is a placeholder for the hex signature of that object.
SignedActionStep mirrors ActionStep as a discriminated union — each variant carries the original payload plus its signed artefact:
The example above shows the EIP-712 variant. Submit signed steps in the same shape and order they were returned by
/createAction. SiweSignedActionStep (action, siwe, signature hex personal_sign) and SessionActionSteps are not submitted here — the SDK exchanges a signed SiweSignedActionStep for a venue session client-side, and a SessionActionStep carries no signable material at all; both skip /executeAction. Submitting action: 'siweLogin' to /executeAction is rejected with 400/2002 (ValidationError).
Response 202
The backend returns 202 Accepted with one ActionResult for every step that it attempted. Three separate axes describe the outcome:
ActionResult:
There is no boolean
success field. Read status.
Statuses
The lifecycle has five values.created is a stored state that never appears in a result.
A
failed result with a classified cause is a confirmed rejection. After the backend verifies a step, the stored status of a submitted or indeterminate step can change to accepted or failed. The 202 response does not change after the backend sends it, and the API does not push this change to the caller.
Which steps have a result
- The list holds only the steps that the backend attempted, in execution order. A step that was not attempted stays
createdand has no result. - Execution stops at the first step that is
failedorindeterminate. Later steps staycreated, so you can execute the remaining steps again. The backend refuses to execute anindeterminatestep again, because the first send can have reached the venue. - Every member of an attempted atomic batch has its own result. Lighter sends an order and its trigger orders as one batch, so all of them share one status.
- Two steps with the same
actionkeep two results. Do not key the results byaction. - Results of earlier acknowledged steps stay in the list after a later step fails.
- If the first step fails before the backend sends it, the request returns an error response, for example
400or409, and not a list of results.
Examples
Acknowledged, then failed. The leverage step was sent. The order was refused because the margin was too low. The result for the leverage step stays in the report:indeterminate result:
indeterminate:
Responses
Order details (SDK)
Single-order lookup is served by the SDK directly from each provider viagetOrder — there is no LI.FI HTTP endpoint. It returns an Order, the same union getOrders returns:
Order is RegularOrder | TriggerOrder | TwapOrder, discriminated on type. Trigger orders add triggerPrice, triggerCondition, and limitPrice?; regular orders carry price?, timeInForce, and expiresAt?; TWAP orders carry durationSeconds and startedAt. See Order fields, OrderType, and OrderStatus for the full field and status tables.
SDK: getOrder()