Skip to main content

How to Use Swap API

This guide covers the steps required to use Swap API.

About Swap API​

Swap API is the recommended way of interacting with 0x protocol for retail trade. Under the hood, the API performs three tasks:

  • Queries prices of ERC20 assets from multiple decentralized exchanges and market makers
  • Aggregates the liquidity from the queried sources to provide the best price possible
  • Returns the trade in a format that can be easily executed using the Web3 library of your choice

Code Sandbox​

If you prefer diving into code, see how the following steps are implemented in this CodePen sandbox! Otherwise, continue on as we go through the steps needed to use Swap API.

Swap Tokens in 3 Simple Steps​

  1. Get a 0x API key
  2. (If needed) Set token allowance
  3. Fetch a swap quote
  4. Send the transaction to the network

0. Get a 0x API key​

If you are are creating an application on mainnet, you will need to create a 0x account and get a live API key. See the guide here to get setup.

1. Set a Token Allowance​

A token allowance is required if you want a third-party to move funds on your behalf. In short, you are allowing them to move your tokens.

In our case, we would like the 0x Exchange Proxy smart contract to trade our ERC20 tokens for us, so we will need to approve an allowance (a certain amount) for this contract to move a certain amount of our ERC20 tokens on our behalf.

When setting the token allowance, make sure to provide enough allowance for the buy or sell amount as well as the gas.

tip

When setting the token allowance, make sure to provide enough allowance for the buy or sell amount as well as the gas; otherwise, you may receive a 'Gas estimation failed' error.

For implementation details, see How to Set Your Token Allowances

2. Fetch a Swap Quote​

tip

The examples in this guide are for Ethereum mainnet https://api.0x.org/. Refer to the 0x Cheat Sheet for endpoints and addresses appropriate for all other 0x supported blockchains.

Once the token allowance has been set, say you would like to sell 100 DAI for WETH. We encode the trade parameters and fetch the swap quote as follows:

const qs = require('qs');

const params = {
// Not all token symbols are supported. The address of the token should be used instead.
sellToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', //DAI
buyToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', //WETH
// Note that the DAI token uses 18 decimal places, so `sellAmount` is `100 * 10^18`.
sellAmount: '100000000000000000000',
takerAddress: '0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B', //Including takerAddress is highly recommended to help with gas estimation, catch revert issues, and provide the best price
};

const headers = {'0x-api-key: [api-key]'}; // This is a placeholder. Get your live API key from the 0x Dashboard (https://dashboard.0x.org/apps)

const response = await fetch(
`https://api.0x.org/swap/v1/quote?${qs.stringify(params)}`, { headers }
); // Using the global fetch() method. Learn more https://developer.mozilla.org/en-US/docs/Web/API/fetch

console.log(await response.json());

The API response will look like the following (some fields omitted):

{
"sellAmount": "100000000000000000000",
"buyAmount": "2663907000981641103",
"price": "0.002663907000981641",
"guaranteedPrice": "0.002637267930971825",
"to": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
"data": "0xd9627aa40000000000000000000...",
"value": "0",
"gas": "111000",
"gasPrice": "56000000000",
"buyTokenAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"sellTokenAddress": "0x6b175474e89094c44da98b954eedeac495271d0f",
"allowanceTarget": "0xdef1c0ded9bec7f1a1670819833240f027b25eff"
}

A full list of the description of each field is outlined in the Swap API reference.

tip

Note the to field is the contract address to send call data to. This is the 0x Exchange Proxy address corresponding to the network the request was made on. For production-level code, make sure to add verification that checks that the to field returned is actually the 0x Exchange Proxy address as demonstrated in this code example (constructor, swapTarget check).

Specify a Taker Address for Your Swaps​

The takerAddress field is the address that will be performing the trade. While technically optional, we highly recommend providing this parameter if possible so that the API can more accurately estimate the gas required for the swap transaction. Note that this currently only works with non-contract addresses. Read more on how adding the takerAddress helps catch issues.

const params = {
sellToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', //DAI
buyToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', //WETH
sellAmount: '100000000000000000000',
takerAddress: '0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B',
};

const headers = {'0x-api-key: [api-key]'}; // This is a placeholder. Get your live API key from the 0x Dashboard (https://dashboard.0x.org/apps)

// The response will now include a more accurate `gas` field.
const response = await fetch(
`https://api.0x.org/swap/v1/quote?${qs.stringify(params)}`, { headers }
);

Under the hood, 0x API performs an eth_estimateGas using the takerAddress if one is provided. This serves two purposes:

  • to more accurately estimate the gas required for the transaction, and
  • to catch any reverts that would occur if the takerAddress attempts to swap the tokens.

An HTTP response with status 400 will be returned if the eth_estimateGas results in a revert (i.e. the swap would fail), along with reasons for the revert. In particular,

  • the takerAddress needs to have a sufficient balance of the sellToken, and
  • if the sellToken is not ETH, the takerAddress needs to have approved the 0x Exchange Proxy (0xdef1c0ded9bec7f1a1670819833240f027b25eff on mainnet) to transfer their tokens. See below for an example of setting a token approval before sending the API request.

3. Send the Transaction to the Network​

Once you've received the API response, in order to submit the transaction to the network you will need to sign the transaction with your preferred web3 library (web3.js, ethers.js, wagmi, etc).

wagmi​

If you are using React, we recommend using wagmi. You can use a React hooks library like wagmi and use their sendTransaction API. See it implemented in our Next.js 0x Demo App.

If you are using vanilla Javascript, we recommend either web3.js or ether.js.

web3.js​

The fields returned by Swap API's /quote endpoint are designed to overlap with the raw transaction object accepted by web3.js’s sendTransaction() function. What this means is that if you are using web3.js, you can directly pass the entire response from /quote because it contains all the necessary parameters for web3.eth.setTransaction() - _from, to, value, gas, data.

Both options work, up to use case and developer preference.

Option 1 - Submit the entire quote response to web3.eth.sendTransction​

// Fetch the swap quote.
const response = await fetch(
`https://api.0x.org/swap/v1/quote?${qs.stringify(params)}`,
{ headers }
);
quote = await response.json();

//Fill the quote by submitting the entire response to web3
const receipt = await web3.eth.sendTransaction(quote);

Option 2 - Submit only the required parameters to web3.eth.sendTransaction**​

// Fetch the swap quote.
const response = await fetch(
`https://api.0x.org/swap/v1/quote?${qs.stringify(params)}`,
{ headers }
);
quote = await response.json();

// Fill the quote.
const receipt = await waitForTxSuccess(
web3.eth.sendTransaction({
from: taker,
to: quote.to,
data: quote.data,
value: quote.value,
gasPrice: quote.gasPrice,
})
);

ethers.js​

ethers.js is more explicit and requires you to pull out and submit only the required parameters (whereas web3.js allows you to just submit the entire json response or submit only require parameters). So if you use ethers.js, make sure you submit only the required parameters similar to the example below.

Also note that ethers.js separates the concept of Wallet, Providers, and Signers. You can use a Wallet and connect it to a provider to send transactions. If you are using a Wallet such as MetaMask, review the ethers.js documentation on how to access these fields - Connecting to Ethereum: MetaMask.

// get signer from a wallet such as MetaMask

const signer = provider.getSigner();

await signer.sendTransaction({
gasLimit: quote.gas,
gasPrice: quote.gasPrice,
to: quote.to,
data: quote.data,
value: quote.value,
chainId: quote.chainId,
});

Examples​

These examples illustrate how the response payload from 0x API’s swap endpoint can be passed directly into web3.eth.sendTransaction. Note that in a production implementation, there would be some error handling for the API response.

Sell 100 DAI for ETH​

This is the most common use pattern for swapping tokens –– selling a fixed amount of an ERC20 token. Because ERC20 tokens cannot be attached to contract calls the way ETH can, the taker must approve the 0x Exchange Proxy (0xdef1c0ded9bec7f1a1670819833240f027b25eff) to transfer their DAI prior to executing the swap.

const ZERO_EX_ADDRESS = '0xdef1c0ded9bec7f1a1670819833240f027b25eff';
const DAI_ADDRESS = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';

// Selling 100 DAI for ETH.
const params = {
sellToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', //DAI
buyToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', //ETH
// Note that the DAI token uses 18 decimal places, so `sellAmount` is `100 * 10^18`.
sellAmount: '100000000000000000000',
takerAddress: '0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B',
}

const headers = {'0x-api-key: [api-key]'}; // This is a placeholder. Get your live API key from the 0x Dashboard (https://dashboard.0x.org/apps)

// Set up a DAI allowance on the 0x contract if needed.
const dai = new web3.eth.Contract(ERC20_ABI, DAI_ADDRESS);
const currentAllowance = new BigNumber(
dai.allowance(params.takerAddress, ZERO_EX_ADDRESS).call()
);
if (currentAllowance.isLessThan(params.sellAmount)) {
await dai
.approve(ZERO_EX_ADDRESS, params.sellAmount)
.send({ from: params.takerAddress });
}

// Fetch the swap quote.
const response = await fetch(
`https://api.0x.org/swap/v1/quote?${qs.stringify(params)}`, { headers }
);


// Perform the swap.
await web3.eth.sendTransaction(await response.json());

Sell 1 ETH for DAI​

This swaps a fixed quantity of ETH for DAI. Unlike ERC20 tokens, ETH can be β€œattached” to the swap transaction so the taker does not need to set an allowance like in the previous example. The taker must have enough ETH balance to cover both the sellAmount and the gas cost of the transaction.

// Selling 100 ETH for DAI.
const params = {
sellToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', //ETH
buyToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', //DAI
sellAmount: '1000000000000000000', // 1 ETH = 10^18 wei
takerAddress: '0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B',
}

const headers = {'0x-api-key: [api-key]'}; // This is a placeholder. Get your live API key from the 0x Dashboard (https://dashboard.0x.org/apps)

// Fetch the swap quote.
const response = await fetch(
`https://api.0x.org/swap/v1/quote?${qs.stringify(params)}`, { headers }
);

// Perform the swap.
await web3.eth.sendTransaction(await response.json());

Buy 100 DAI with ETH ​

This is similar to the previous example, but instead specifies the amount of DAI to buy, rather than the amount of ETH to sell. Instead of specifying sellAmount in the API request parameters, we provide buyAmount. Note that due to slippage, you may end up with slightly more than the requested buyAmount.

const params = {
buyToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', //DAI
sellToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', //ETH
// Note that the DAI token uses 18 decimal places, so `buyAmount` is `100 * 10^18`.
buyAmount: '100000000000000000000',
takerAddress: '0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B',
}

const headers = {'0x-api-key: [api-key]'}; // This is a placeholder. Get your live API key from the 0x Dashboard (https://dashboard.0x.org/apps)

// Fetch the swap quote.
const response = await fetch(
`https://api.0x.org/swap/v1/quote?${qs.stringify(params)}`, { headers }
);

// Perform the swap.
await web3.eth.sendTransaction(await response.json());

Advanced Options​

Gas Price​

By default, 0x API will choose the median β€œfast” (<30s) gas price (as reported by various sources, such as ETH Gas Station) and compute the quote based around that. However, you can explicitly provide a gas price with the gasPrice query parameter. Just like with other quantities, values for this parameter are in wei (e.g. 9 gwei = 9 * 10^9 wei = 9000000000).

Max Slippage​

0x API aggregates liquidity from various sources, including on-chain AMMs. Whereas the price of 0x orders are β€œlocked in” when they are signed, AMM prices can fluctuate between the time of the API request and the time the swap transaction gets mined (this is known as slippage). If, at the time the swap is executed, the price is below the guaranteedPrice returned in the API response, the transaction will revert.

The slippagePercentage parameter determines the difference between the price returned in the API response and the guaranteedPrice, i.e. the maximum acceptable slippage. It defaults to 1% but this value may not be appropriate. For example one might expect very low slippage for certain stablecoin pairs like USDC-USDT. On the other hand, one might expect (and deem acceptable) relatively high slippage for newly launched tokens with shallow liquidity.

Starter projects​