Execute perp action
Perps Execution
Execute Perp Action
Submit a canonical perpetual action (order, close, cancel, deposit, withdraw, …) previously built by /2/perp/payloads/<action>. Handles both off-chain DEX APIs and signed EVM transaction broadcast.
POST
Execute perp action
Single unified execution endpoint for every perp action. You forward the exact envelope returned by the matching
Rules:
/2/perp/payloads/<action> call plus a signature that proves the caller approved this specific payload at this specific timestamp.
Flow
- Call
POST /2/perp/payloads/<action>(see left-hand nav) → receive{ action, dex, chainId, marketId?, transport, payloadStr }. - For Gains
transport: "evm-tx"only: parsepayloadStr, extractpayload.data, sign the EVM transaction locally → obtainsignedTx. - Sign the execute-v2 authentication message (see Authentication below).
POST /2/perp/execute-v2with the envelope fields, signature, timestamp, and (when required)signedTx.
Request Body
Canonical action name. One of
withdraw, create-account, deposit, create-order, close-position, cancel-order, update-margin, edit-order. Must match the action inside payloadStr.gains or lighter. Must match payloadStr.Chain of the action. Must match
payloadStr.Mobula market identifier. If provided, must match
payloadStr.marketId.offchain-api — server submits to the DEX off-chain API using the user’s signature.evm-tx — server broadcasts the user-signed EVM transaction supplied in signedTx. Must match payloadStr.JSON-stringified canonical envelope returned by
/2/perp/payloads/<action>.Envelope metadata (action, dex, chainId, transport, marketId) must be forwarded unchanged — it is cross-checked against the request fields.payload sub-fields are action-specific and some flows require mutating them before signing execute-v2:deposit(Lighter route with EVM bridge steps) — sign every tx inpayload.steps[].items[].dataand write the hex results intopayload.signedTxsas an array of strings.withdrawon Lighter — signpayload.MessageToSign, set the hex result onpayload.L1Sig, then deletepayload.MessageToSign.
Unix timestamp in milliseconds, within 30 seconds of server time.
Hex signature of the message
api/2/perp/execute-v2-{timestamp}-{payloadStr}. The recovered signer address must match the payload.data.from address for actions that carry a from (e.g., create-order, close-position). Single-use: a second call with the same signature is rejected.Hex-encoded single signed EVM transaction. Used for Gains single-tx actions (
create-order, close-position, cancel-order, edit-order, update-margin) whose response has transport: "evm-tx". The server broadcasts it via eth_sendRawTransaction on chainId.Do not use this field for multi-tx flows (Lighter deposit bridge route) — those inject signed txs into payloadStr under payload.signedTxs instead.Response
Errors
| Status | message | Cause |
|---|---|---|
| 400 | payloadStr is not valid JSON | payloadStr is not parseable |
| 400 | invalid payloadStr | envelope fails schema validation (see errors) |
| 400 | payloadStr metadata does not match request metadata | action/dex/transport/chainId mismatch between envelope and request |
| 400 | payloadStr marketId does not match request marketId | marketId mismatch |
| 400 | signedTx execution requires an EVM chainId, received "<chainId>" | transport: "evm-tx" with a non-EVM chain |
| 403 | timestamp expired | timestamp more than 30s from server clock |
| 403 | signature already used | Replay of an earlier request |
| 403 | signature signer does not match payload.from | Signer address ≠ payload.data.from for actions that carry a from |
| 500 | Failed to broadcast signed transaction on <chainId> | RPC rejected signedTx (see errors list for details) |
| 500 | DEX-specific reason | Adapter-level failure returned by the DEX |
Authentication
The execute-v2 signature binds the exact payloadStr to the exact timestamp:payloadStrin the signed message is the same string you put in the request body. If the flow requires injecting fields (depositsignedTxs, Lighter withdrawL1Sig), do the injection + re-stringify before signing — sign the final string, not the original.- For actions whose envelope carries
payload.data.from(Gains EVM txs, Lighter orders), the signer must equalfrom. Deposit/withdraw envelopes that don’t expose afromskip this check. - Signatures are single-use for 30 seconds after the timestamp.
Transport & signing matrix
Thetransport returned by /2/perp/payloads/<action> is authoritative — forward it as-is. What the client must sign depends on both the DEX and the action:
| DEX | Action | Transport | Client signing |
|---|---|---|---|
| Lighter | create-order, close-position, cancel-order, edit-order, update-margin | offchain-api | execute-v2 signature only — forward payloadStr byte-for-byte |
| Lighter | create-account | offchain-api | If the response carries payload.MessageToSign: sign it, set payload.L1Sig, delete payload.MessageToSign, re-stringify. Otherwise no mutation. |
| Lighter | deposit | evm-tx | Sign each tx in payload.steps[].items[].data (each item’s data is a tx object: to, data, value, chainId, gas?, fee fields). Inject results into payload.signedTxs: string[], re-stringify, then sign execute-v2 over the new string. Do not send top-level signedTx. |
| Lighter | withdraw | offchain-api | Sign payload.MessageToSign, set payload.L1Sig, delete payload.MessageToSign, re-stringify, then sign execute-v2 over the new string. |
| Gains | create-order, close-position, cancel-order, edit-order, update-margin | evm-tx | Read the tx object at payload.data (fields: to, callData (not data), value, chainId, nonce?, gas?, fee fields). Sign as a type-2 EVM tx → submit as top-level signedTx. payloadStr is forwarded unchanged. |
Body
application/json
Available options:
withdraw, create-account, deposit, create-order, close-position, cancel-order, update-margin, edit-order Available options:
gains, lighter Available options:
offchain-api, evm-tx JSON-stringified canonical envelope. Envelope metadata must match the request fields.
Hex signature of api/2/perp/execute-v2-{timestamp}-{payloadStr}.
Hex-encoded single signed EVM transaction (Gains single-tx actions with transport evm-tx).