Long or short YU
GET/v1/actions/boros/order
Place one order. IOC (default) takes the book: the API walks it for the expected fill and encodes two on-chain bounds — a limit TICK at the worst level ± slippage, and the contract's average-rate check (desiredMatchRate) at the expected fill ± slippage — so the transaction reverts rather than filling worse. GTC / ALO rest at limitApr (the tick rounds so the posted rate is never worse than asked).
data.quote.terms is the term-sheet side the order takes (headline, description, implications, tags) — show it before signing.
With deposit=auto (default) a margin deposit is prepended when the cross account's free margin is below IM × marginBuffer + taker fee (or below the ~$10 minimum cash on a fresh account); a reducing order deposits nothing. The market is entered in the same call when it is not yet.
Boros trades perp funding rates as fixed-vs-floating swaps (Pendle, Arbitrum 42161). A Yield Unit (YU) on a market is the funding one venue pays on one unit of notional until maturity. LONG receives the floating funding and pays the fixed rate it bought at; SHORT pays floating and receives fixed — the side that LOCKS a funding income.
- Sizes are in the market's COLLATERAL: a USD₮0-margined BTC market sizes in dollars of notional, a WBTC-margined one in BTC. Pass
notionalUsdto let the API convert. - Margin is one cross account per collateral token:
IM = |size| × max(|rate|, floor) × kIM × max(timeToMaturity, 5 days). Liquidation at health ≤ 1. - Fees: taker
|size| × takerFee × TTMonce; settlementsettleFeeannualised on notional every funding period; ~$1 entrance fee per market. Maker orders pay none. - Every transaction is EOA-direct on Arbitrum. The Router's unsigned entry points act on
(msg.sender, account 0)— no agent key, no Boros relayer, no gas balance, and nothing through the 1delta Composer. Deposits approve the Router.
Omit account for a quote (actions: null).
Plain-text reference — GET /v1/actions/boros/order
Parameters
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
account | query | string | no | The wallet. Omit for a quote only |
marketId | query | string | yes | Boros market id |
side | query | long, short | yes | long | short |
size | query | string | no | Notional in the market's collateral units (decimal), or use notionalUsd |
notionalUsd | query | string | no | Notional in USD |
tif | query | ioc, gtc, alo | no | ioc | gtc | alo |
limitApr | query | string | no | Limit APR in percent — required for gtc/alo, an extra bound for ioc |
slippage | query | string | no | Bps of APR (25 = 0.25 percentage points) |
deposit | query | string | no | auto | none | base units |
marginBuffer | query | string | no | Deposit sizing multiple of IM |
exitMarket | query | boolean | no | Exit the market after the order (full close only) |
Response 200
| Field | Type | Description |
|---|---|---|
success | True | |
data | object | Informational data (quotes, simulation results, etc.) |
actions | object | Transaction calldata and approvals. Null for quote-only responses (no account provided). |
actions.transactions | object[] | Pre-trade setup transactions (e.g. e-mode switch, collateral enable). Execute these before the main swap. Empty when no setup is needed. |
actions.transactions[].chainType | evm | Which VM executes this step. ABSENT means evm, which is the only value any endpoint returns today — every EVM response is unchanged. A non-EVM chain would return a different shape (a serialized, PERISHABLE transaction rather than to/data/value) carrying its own chainType, so a client that wants to stay forward-compatible should branch on this field rather than assume to is present. |
actions.transactions[].to | string | Target contract address |
actions.transactions[].data | string | Encoded calldata |
actions.transactions[].value | string | ETH value to send with the transaction |
actions.transactions[].description | string | Human-readable label. For alternatives, this is the aggregator name (e.g. "Paraswap"). For transactions, describes the setup action (e.g. "Switch e-mode to 1"). |
actions.alternatives | object[] | DEX aggregator swap transactions sorted by best output (descending). Each entry's description is the aggregator name. The client should pick one to execute. Present on loop action endpoints. |
actions.alternatives[].chainType | evm | Which VM executes this step. ABSENT means evm, which is the only value any endpoint returns today — every EVM response is unchanged. A non-EVM chain would return a different shape (a serialized, PERISHABLE transaction rather than to/data/value) carrying its own chainType, so a client that wants to stay forward-compatible should branch on this field rather than assume to is present. |
actions.alternatives[].to | string | Target contract address |
actions.alternatives[].data | string | Encoded calldata |
actions.alternatives[].value | string | ETH value to send with the transaction |
actions.alternatives[].description | string | Human-readable label. For alternatives, this is the aggregator name (e.g. "Paraswap"). For transactions, describes the setup action (e.g. "Switch e-mode to 1"). |
actions.permissions | object[] | Approval/delegation transactions that must execute before both transactions and alternatives. Includes ERC20 allowances (targeting the composer contract) and lender borrow/withdrawal delegations (targeting the lending protocol contract directly). Filtered against on-chain state so only missing approvals are returned. Null when no approvals are needed. |
actions.permissions[].to | string | Target contract address |
actions.permissions[].data | string | Encoded calldata |
actions.permissions[].value | string | ETH value |
actions.permissions[].description | string | Human-readable description of the approval (e.g. "Approve borrow for AAVE_V3", "Approve ERC20") |
actions.permissions[].spender | string | ERC-20 approve spender (x-chain permissions). Match it against the selected quote's approvalTarget — several bridges can share one spender, so do not match by description. |
actions.permissions[].type | ERC20, Lender | What kind of grant this is. A signatures[] offer names the type it replaces via its replaces field. |
actions.signatures | object[] | EIP-712 payloads the user can sign INSTEAD of sending the corresponding permissions entry. Only present when the caller opted in with permit=auto|required and a permit path exists. Sign with eth_signTypedData_v4, then POST the same endpoint with {permits: [{permitId, signature}]} (plus builds where the response issued buildIds) — the permit executes inside the main transaction. |
actions.signatures[].permitId | string | Opaque, self-describing handle for this permit. Round-trip it verbatim: POST {permits: [{permitId, signature}]} back to the same endpoint. |
actions.signatures[].kind | erc2612, dai, permit2, aaveCredit, morphoAuth, cometAuth | Permit flavour |
actions.signatures[].typedData | object | Ready for eth_signTypedData_v4 (domain, types incl. EIP712Domain, primaryType, message). All numeric fields are decimal strings. |
actions.signatures[].replaces | string | Which permissions entry this signature replaces (ERC20 | Lender) |
actions.signatures[].spender | string | Who the signature authorises. Match against the permission / quote (approvalTarget) it replaces — on multi-spender responses (x-chain) only routes whose approvalTarget equals this spender are covered by the signature. |
actions.signatures[].description | string | Human-readable label for this entry. |
actions.signatures[].unscoped | boolean | True when the grant is NOT amount-scoped (full position control until revoked) — surface this to the user. |
actions.signatures[].deadline | string | Unix seconds after which the signature is worthless (default: 30 minutes). |
actions.signs | object[] | Messages that MUST be signed before anything can be sent (unlike signatures, which are optional permit offers). When non-empty, transactions and alternatives are EMPTY: sign typedData with eth_signTypedData_v4 (or, for format: personal_sign, message with personal_sign), then call submit with the signature under submit.signatureField, and execute what that answers. permissions may still be present and can be sent before or after signing. Produced by Inverse FiRM loops (/loop/leverage, /loop/close), Morpho Midnight make, Term order-sign and the Lista leg of /rewards/claim. |
actions.signs[].purpose | authorize-action, publish-order, authenticate | authorize-action: the signature authorises an on-chain action and submit answers its transaction (Inverse ALE loops). publish-order: the signature makes an off-chain order and submit publishes it (Midnight make, Term order-sign). authenticate: the signature is a LOGIN to a third-party API that serves the data the transaction needs (Lista reward proofs); it authorises nothing on-chain. |
actions.signs[].format | eip712, personal_sign | eip712: sign typedData with eth_signTypedData_v4. personal_sign: sign the UTF-8 message with personal_sign. |
actions.signs[].typedData | object | format: eip712 only. Ready for eth_signTypedData_v4. All numeric fields are decimal strings. |
actions.signs[].message | string | format: personal_sign only. The exact text to sign; send it back verbatim (it is part of submit.params). |
actions.signs[].signer | string | The address that must sign. The server recovers the signer and refuses any other. |
actions.signs[].deadline | string | Unix seconds after which the signature is worthless. |
actions.signs[].spender | string | Who the signature authorises. |
actions.signs[].description | string | Human-readable label for this entry. |
Example response
{
"success": true,
"data": {},
"actions": {
"transactions": [
{
"chainType": "evm",
"to": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string"
}
],
"alternatives": [
{
"chainType": "evm",
"to": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string"
}
],
"permissions": [
{
"to": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string",
"spender": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"type": "ERC20"
}
],
"signatures": [
{
"permitId": "string",
"kind": "erc2612",
"typedData": {},
"replaces": "string",
"spender": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"description": "string",
"unscoped": true,
"deadline": "string"
}
],
"signs": [
{
"purpose": "authorize-action",
"format": "eip712",
"typedData": {},
"message": "string",
"signer": "string",
"deadline": "string",
"spender": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"description": "string",
"submit": {
"method": "GET",
"endpoint": "string",
"params": {},
"body": {},
"signatureField": "string"
}
}
],
"permitSkipped": [
{
"replaces": "string",
"reason": "string"
}
]
}
}
Request
Responses
- 200
- 400
- 429
- 500
- 502
approve? + deposit? + placeSingleOrder
Validation error
Rate limited. Unauthenticated callers share a per-IP budget; send an x-api-key header to lift it. Retry with exponential backoff.
Unexpected server error. Safe to retry with backoff.
An upstream data source or protocol origin failed (error.code is ORIGIN_FAILED). error.details carries the per-origin status. This is also what a missing or malformed required parameter currently returns, rather than a 400.