Skip to main content
Version: 2.0 (beta)

Upgrading to Swap API v2

0x Swap API has undergone a major upgrade that introduces new features that require a new integration. This new version offers:

API references​

Find the latest API references here.

Summary of design changes​

This section showcases example requests and responses for both the Swap API v1 and v2 endpoints to illustrate updates in the shape of the query and responses made during the API upgrade:

Swap API v1
Swap API v1/quote
Request
curl --request GET
--url https://api.0x.org/swap/v1/quote?buyToken=0x6B175474E89094C44Da98b954EedeAC495271d0F&sellToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&sellAmount=100000&takerAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&slippagePercentage=0.03&feeRecipient=0xa8aac589a67ecfade31efde49a062cc21d68a64e&buyTokenFeePercentage=0.1&feeRecipientTradeSurplus=0xa8aac589a67ecfade31efde49a062cc21d68a64e
--header '0x-api-key: YOUR_API_KEY'
Response
{
"chainId": 1,
"price": "3004.35342",
"grossPrice": "3008.73112",
"estimatedPriceImpact": "0.4902",
"value": "100000",
"gasPrice": "2457320000",
"gas": "358839",
"estimatedGas": "358839",
"protocolFee": "0",
"minimumProtocolFee": "0",
"buyTokenAddress": "0x6b175474e89094c44da98b954eedeac495271d0f",
"buyAmount": "300435342",
"grossBuyAmount": "300873112",
"sellTokenAddress": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"sellAmount": "100000",
"grossSellAmount": "100000",
"sources": [
{
"name": "0x",
"proportion": "0"
},
{
"name": "Uniswap",
"proportion": "0"
},
{"..."}
],
"allowanceTarget": "0x0000000000000000000000000000000000000000",
"sellTokenToEthRate": "1",
"buyTokenToEthRate": "3023.5504768532695617",
"to": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
"from": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
"data": "0x415565b0000000000000000000000000eeeeeeeee....000000000000000000000000000000e7be0bf798e96f437b0d6e8",
"decodedUniqueId": "0x0e7be0bf798e96f437b0d6e8",
"guaranteedPrice": "2914.09148",
"orders": [
{
"type": 0,
"source": "Uniswap_V2",
"makerToken": "0x6b175474e89094c44da98b954eedeac495271d0f",
"takerToken": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"makerAmount": "300873112",
"takerAmount": "100000",
"fillData": {
"tokenAddressPath": [
"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"0x6b175474e89094c44da98b954eedeac495271d0f"
],
"router": "0xf164fc0ec4e93095b804a4795bbe1e041497b92a"
},
"fill": {
"input": "100000",
"output": "300873112",
"adjustedOutput": "1",
"gas": 115000
}
}
],
"fees": {
"zeroExFee": {
"feeType": "volume",
"feeToken": "0x6b175474e89094c44da98b954eedeac495271d0f",
"feeAmount": "437770",
"billingType": "on-chain"
}
},
"auxiliaryChainData": {}
}
Swap API v2
Swap API v2 /quote (Permit2)
Request
curl --request GET
--url https://api.0x.org/swap/permit2/quote?chainId=1&buyToken=0x6B175474E89094C44Da98b954EedeAC495271d0F&sellToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&sellAmount=100000&taker=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&swapFeeBps=10&swapFeeRecipient=0xa8aac589a67ecfade31efde49a062cc21d68a64e&swapFeeToken=0x6B175474E89094C44Da98b954EedeAC495271d0F&tradeSurplusRecipient=0xa8aac589a67ecfade31efde49a062cc21d68a64e&slippageBps=100
--header '0x-api-key: YOUR_API_KEY'
--header '0x-version: v2'
Response
{
"blockNumber": "20264686",
"buyAmount": "300409869",
"buyToken": "0x6b175474e89094c44da98b954eedeac495271d0f",
"fees": {
"integratorFee": {
"amount": "301163",
"token": "0x6b175474e89094c44da98b954eedeac495271d0f",
"type": "volume"
},
"zeroExFee": {
"amount": "451744",
"token": "0x6b175474e89094c44da98b954eedeac495271d0f",
"type": "volume"
},
"gasFee": null
},
"issues": {
"allowance": null,
"balance": null,
"simulationIncomplete": false,
"invalidSourcesPassed": []
},
"liquidityAvailable": true,
"minBuyAmount": "297405770",
"permit2": null,
"route": {
"fills": [
{
"from": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"source": "SushiSwap",
"proportionBps": "10000"
}
],
"tokens": [
{
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"symbol": "WETH"
},
{
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"symbol": "DAI"
}
]
},
"sellAmount": "100000",
"sellToken": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"totalNetworkFee": "415281807360000",
"transaction": {
"to": "0x7f6cee965959295cc64d0e6c00d99d6532d8e86b",
"data": "0x1fff991f000000000000000000000...000000000000",
"gas": "221184",
"gasPrice": "1877540000",
"value": "100000"
}
}
Swap API v2/quote (AllowanceHolder)
Request
curl --request GET
--url https://api.0x.org/swap/allowance-holder/quote?chainId=1&buyToken=0x6B175474E89094C44Da98b954EedeAC495271d0F&sellToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&sellAmount=100000&taker=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&swapFeeBps=10&swapFeeRecipient=0xa8aac589a67ecfade31efde49a062cc21d68a64e&swapFeeToken=0x6B175474E89094C44Da98b954EedeAC495271d0F&tradeSurplusRecipient=0xa8aac589a67ecfade31efde49a062cc21d68a64e&slippageBps=100
--header '0x-api-key: YOUR_API_KEY'
--header '0x-version: v2'
Response
{
"blockNumber": "20264713",
"buyAmount": "300433569",
"buyToken": "0x6b175474e89094c44da98b954eedeac495271d0f",
"fees": {
"integratorFee": {
"amount": "301187",
"token": "0x6b175474e89094c44da98b954eedeac495271d0f",
"type": "volume"
},
"zeroExFee": {
"amount": "451780",
"token": "0x6b175474e89094c44da98b954eedeac495271d0f",
"type": "volume"
},
"gasFee": null
},
"issues": {
"allowance": null,
"balance": null,
"simulationIncomplete": false,
"invalidSourcesPassed": []
},
"liquidityAvailable": true,
"minBuyAmount": "297429233",
"route": {
"fills": [
{
"from": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"source": "Uniswap_V2",
"proportionBps": "10000"
}
],
"tokens": [
{
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"symbol": "WETH"
},
{
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"symbol": "DAI"
}
]
},
"sellAmount": "100000",
"sellToken": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"totalNetworkFee": "783821981250000",
"transaction": {
"to": "0x0000000000001ff3684f28c67538d4d072c22734",
"data": "0x2213bc0b0000000000000000000...00000000",
"gas": "233541",
"gasPrice": "3356250000",
"value": "100000"
}
}

Things to note​

Updated URLs​

Unified endpoint and chain designation​

The chain is no longer designated by the endpoint URL. All chains now use the same api.0x.org endpoint, with the chain set via the new chainId query parameter:

  • Old: https://polygon.api.0x.org/swap/v1/quote
  • New: https://api.0x.org/swap/permit2/quote?chainId=137

API version update​

The API version is no longer set in the endpoint URL. In v2, the API version is a required header parameter.

Updated Parameter Names​

Note the following parameter names have been updated in v2. See the API references for more parameter details:

  • takerAddress has been renamed to taker
  • sellTokenAddress has been renamed to sellToken
  • buyTokenAddress has been renamed to buyToken

Deprecated Parameter​

The buyAmount query parameter has been deprecated in favor of purely sellAmount for more deterministic behavior. When using sellAmount, any unused tokens are refunded to the user, whereas using buyAmount can lead to over-buying due to slippage and varying liquidity source behaviors. Additionally, some liquidity sources (e.g., Kyber) do not support quoting by buyAmount, which limits available liquidity.

Old (v1):

curl --request GET
https://polygon.api.0x.org/swap/v1/quote&buyTokenAddress=0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270&sellTokenAddress=0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174&sellAmount=10000000&takerAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
--header '0x-api-key: YOUR_API_KEY'

New (v2):

curl --request GET
https://api.0x.org/swap/quote?chainId=137&buyToken=0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270&sellToken=0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174&sellAmount=10000000&taker=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
--header '0x-api-key: YOUR_API_KEY'
--header '0x-version: v2'

Enhanced security​

0x V2 enhances security by moving away from unlimited approvals and now sets allowances per trade. You can choose between Permit2 or AllowanceHolder this purpose.

  • Old: https://api.0x.org/swap/v1/quote
  • New: https://api.0x.org/swap/permit2/quote or https://api.0x.org/swap/allowance-holder/quote

Token allowances​

For token allowances, the allowance target will no longer be the 0x Exchange Proxy, but rather either the Permit2 contract or AllowanceHolder contracts, depending on your preferred token allowance path.

Permit2 transactions​

For transactions using Permit2, you will need to sign a Permit2 EIP-712 message from the /quote response and append the signature length and signature data to calldata before submitting the transaction to the network. You can find a guide to do so here.

Changes in API responses​

Liquidity availability​

There is a new liquidityAvailable field that validates the availability of liquidity for a quote request. All other parameters will only be returned when this is set to true.

Validation changes​

We have removed the skipValidation field and will always validate the quote. However, we will always attempt to return a valid quote even when the taker has an insufficient balance or doesn’t have a token allowance set in the Swap API.

Issues object​

To help provide developers a smooth build experience, 0x API v2 will do as much validation as it can and report all issues it finds in the new issues object. This object returns a list of potential validation issues detected with the quote. In rare cases where we are unable to validate the quote, we’ll return true in issues.simulationIncomplete. Learn more about the new issues object and how you can use it to provide a better experience for your users.

Note the following about the issues object for Price and Quote:

  • Price

    • allowance: If this field is not null, prompt the user to set the allowance on issues.allowance.spender
    • balance: If this field is not null, do not proceed to get a quote.
    • simulationIncomplete: This field can be ignored for price since when calling price means aren't close to submitting a transaction (versus calling quote). Typically simulationIncomplete: true won't occur if the taker address is set and the taker has a sufficient balance of the sell token.
  • Quote

    • allowance: This field should not appear if the quote is sent after the token allowance is set.
    • balance: This field will not be returned if the taker has sufficient balance when the quote request is sent.
    • simulationIncomplete: true: This field will not be returned if the taker has sufficient balance when the quote request is sent.

Detailed migration guide​

The following section overviews of how to update Swap API price and quote to handle the new v2 endpoints whether you are using Permit2 or using AllowanceHolder

Using Permit2​

tip

⚑️ See these steps in action in the Permit2 headless example

Step 0. Get 0x API key​

Step 1. Get indicative price​

  • Call /swap/permit2/price (code)
    • Build required price params
      • Add chainId as new param
      • takerAddress has changed to taker
    • In the response: sellTokenAddress changed to sellToken, buyTokenAddress changed to buyToken

Step 2. Set token allowance​

  • Check if taker needs to set an allowance for Permit2. If needed, set token allowance (code)
    • Use the info returned by issues.allowance returned by /price (if taker is set) and /quote which contains details of allowances that the taker must set for the order to execute successfully

Step 3. Get firm quote​

  • Call /swap/permit2/quote (code)
    • Build required quote params (price params + taker address)
      • Add chainId as new param
      • takerAddress has changed to taker
    • In the response: sellTokenAddress changed to sellToken, buyTokenAddress changed to buyToken (code)

Step 4. Sign Permit2 EIP-712 message​

  • Sign the Permit2 EIP-712 message from /quote response
    • signature = await signTypedDataAsync(quote.permit2.eip712); (code)
    • Make sure PriceResponse and QuoteResponse types are up-to-date

Step 5. Append signature length and signature data to transaction.data​

  • Append the signature length and signature data to the transaction.data(code)

Step 6. Submit transaction with Permit2 signature​

  • Submit the transaction with Permit2 signature
    • Use sendTransaction({account, gas, txOptions, data, value, chain) (code)
    • Note that the /quote response structure has changed from v1 to v2, specifically to, gas ,data, value, gasPrice β†’ have moved under quoteResponse.transaction.to, quoteResponse.transaction.gas,quoteResponse.transaction.data, quoteResponse.transaction.value, quoteResponse.transaction.gasPrice (code)

Using AllowanceHolder​

tip

⚑️ See these steps in action in the AllowanceHolder headless example

Step 0. Get 0x API key​

Step 1. Get indicative price​

  • Call /swap/allowance-holder/price (code)
    • Build required price params
      • Add chainId as new param
      • takerAddress has changed to taker
    • In the response: sellTokenAddress changed to sellToken, buyTokenAddress changed to buyToken

Step 2. Set token allowance​

  • Check if taker needs to set an allowance for AllowanceHolder. If needed, set token allowance (code)
    • Use the info returned by issues.allowance returned by /price (if taker is set) and /quote which contains details of allowances that the taker must set for the order to execute successfully

Step 3. Get firm quote​

  • Call /swap/allowance-holder/quote (code)
    • Build required quote params (price params + taker address)
      • Add chainId as new param
      • takerAddress has changed to taker
    • In the response: sellTokenAddress changed to sellToken, buyTokenAddress changed to buyToken (code)

Step 4. Submit transaction​

  • Submit the transaction using sendTransaction() (code)
    • Note that the /quote response structure has changed from v1 to v2, specifically to, gas ,data, value, gasPrice β†’ have moved under quoteResponse.transaction.to, quoteResponse.transaction.gas,quoteResponse.transaction.data, quoteResponse.transaction.value, quoteResponse.transaction.gasPrice (code)