Skip to main content

Spot swap (submit signed permits)

POST 

/v1/actions/swap/spot

Same parameters as GET. The JSON body carries the two-call permit contract: permits (signed offers from a previous response) and optionally builds (the previous response's buildIds, spliced without re-quoting).

Permit flow (permit=auto): the response additionally carries actions.signatures[] (an EIP-712 permit to sign instead of the approve — the spot spender is always the 1delta composer, so ONE signature covers every alternative) and a buildId per quote row. Sign, then POST the same endpoint with {permits: [{permitId, signature}], builds: [buildId]} — the cached builds are re-headed with the permit and answered without re-quoting; the approve permission disappears. BUILD_EXPIRED (builds live ~3 min) means re-quote and resubmit the SAME signature. Without builds, a POST with permits re-quotes and threads the permit into the fresh calldata.

Plain-text reference — POST /v1/actions/swap/spot

Parameters

ParameterInTypeRequiredDescription
chainIdquerystringyesChain ID See the ChainId schema for the full set of supported chains.
tokenInquerystringyesInput token address
tokenOutquerystringyesOutput token address
amountquerystringyesAmount in wei
slippagequerynumberyesSlippage tolerance (basis points)
accountquerystringnoAccount address. Include to build transaction, omit for quote-only.
receiverquerystringnoReceiver address
tradeTypequery0, 1noTrade type (0=EXACT_INPUT, 1=EXACT_OUTPUT)
usePendleMintRedeemquerybooleannoUse Pendle mint/redeem
permitqueryoff, auto, requirednoPermit mode: 'off' (default) approve-only; 'auto' additionally offers a permit signature when the token supports one; 'required' fails with PERMIT_UNAVAILABLE when none exists.

Request body

FieldTypeRequiredDescription
permitsobject[]noSigned permits from a previous response of the SAME endpoint.
permits[].permitIdstringyesThe permitId from signatures[]
permits[].signaturestringyesThe eth_signTypedData_v4 signature (0x-hex)
buildsstring[]nobuildIds from the previous response's quote rows. When present alongside permits, the cached builds are re-headed with the permit — no re-quote, the price you saw is the price you execute. Builds expire after ~3 minutes; a BUILD_EXPIRED error means re-quote and resubmit the SAME signature (the permit binds token/spender/value, not the route).

Response 200

FieldTypeDescription
successTrue
dataobjectFull build response for spot swap (account provided).
data.currencyInobjectInput currency info
data.currencyOutobjectOutput currency info
data.quotesobject[]Candidate routes, best output first. Execute exactly one.
data.quotes[].aggregatorstring
data.quotes[].tradeInputnumber
data.quotes[].tradeOutputnumber
data.quotes[].txobjectAn EVM transaction ready to sign and broadcast. Send to, data and value as-is; do not re-encode them.
data.quotes[].tx.chainTypeevmWhich 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.
data.quotes[].tx.tostringTarget contract address
data.quotes[].tx.datastringEncoded calldata
data.quotes[].tx.valuestringETH value to send with the transaction
data.quotes[].tx.descriptionstringHuman-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").
data.quotes[].buildIdstringPresent when permit=auto|required produced a signature offer. Send it back in the POST body (builds[]) together with the signed permit to splice this exact build — no re-quote. Expires after ~3 minutes.
data.permissionTxnsobject[]Approvals needed for this specific quote. Most integrators should use the deduplicated envelope-level actions.permissions instead.
data.permissionTxns[].tostringTarget contract address
data.permissionTxns[].datastringEncoded calldata
data.permissionTxns[].valuestringETH value
data.permissionTxns[].descriptionstringHuman-readable description of the approval (e.g. "Approve borrow for AAVE_V3", "Approve ERC20")
data.permissionTxns[].spenderstringERC-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.
data.permissionTxns[].typeERC20, LenderWhat kind of grant this is. A signatures[] offer names the type it replaces via its replaces field.
actionsobjectTransaction calldata and approvals. Null for quote-only responses (no account provided).
actions.transactionsobject[]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[].chainTypeevmWhich 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[].tostringTarget contract address
actions.transactions[].datastringEncoded calldata
actions.transactions[].valuestringETH value to send with the transaction
actions.transactions[].descriptionstringHuman-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.alternativesobject[]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[].chainTypeevmWhich 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[].tostringTarget contract address
actions.alternatives[].datastringEncoded calldata
actions.alternatives[].valuestringETH value to send with the transaction
actions.alternatives[].descriptionstringHuman-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.permissionsobject[]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[].tostringTarget contract address
actions.permissions[].datastringEncoded calldata
actions.permissions[].valuestringETH value
actions.permissions[].descriptionstringHuman-readable description of the approval (e.g. "Approve borrow for AAVE_V3", "Approve ERC20")

Example response

{
"success": true,
"data": {
"currencyIn": {},
"currencyOut": {},
"quotes": [
{
"aggregator": "string",
"tradeInput": 1.0,
"tradeOutput": 1.0,
"tx": {
"chainType": "evm",
"to": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string"
},
"buildId": "string"
}
],
"permissionTxns": [
{
"to": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string",
"spender": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"type": "ERC20"
}
]
},
"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"
}
],
"permitSkipped": [
{
"replaces": "string",
"reason": "string"
}
]
}
}

Request

Responses

Spot swap build with the permit spliced in