# Guide: Build and Execute a Swap

Use `getSwap` from `sushi/evm` to build transaction data for an EVM swap route.

```ts twoslash
import { ChainId } from 'sushi'
import { getSwap } from 'sushi/evm'

declare const apiKey: string | undefined

const swap = await getSwap({
  chainId: ChainId.ETHEREUM,
  tokenIn: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
  tokenOut: '0x6B3595068778DD592e39A122f4f5a5cF09C90fE2',
  amount: 1_000_000_000_000_000_000n,
  sender: '0x0000000000000000000000000000000000000000',
  maxSlippage: 0.005,
  apiKey,
})
```

## Request fields

| Field | Required | Description |
|---|---:|---|
| `chainId` | Yes | Supported EVM swap API chain ID. |
| `tokenIn` | Yes | Input token address. |
| `tokenOut` | Yes | Output token address. |
| `amount` | Yes | Raw input amount in token base units. |
| `sender` | Yes | Address that will send the transaction. |
| `maxSlippage` | Yes | Maximum slippage as a decimal number. |
| `recipient` | No | Address receiving output tokens. Defaults to sender. |
| `source` | No | Liquidity source selection. |
| `fee`, `feeReceiver`, `feeBy` | No | Integration fee fields. |
| `referrer` | No | Custom referrer string. |
| `simulate` | No | Request simulated gas/validation data. |
| `validate` | No | Validate transaction when simulation is enabled. |
| `apiKey` | No | Sushi API key. Keep server-side. |
| `baseUrl` | No | Override API base URL. |

## Simulate and send

```ts twoslash
import { getSwap } from 'sushi/evm'
import { createPublicClient, createWalletClient, http } from 'viem'
import { mainnet } from 'viem/chains'

const publicClient = createPublicClient({ chain: mainnet, transport: http() })
const walletClient = createWalletClient({ chain: mainnet, transport: http() })

const swap = await getSwap({
  chainId: 1,
  tokenIn: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
  tokenOut: '0x6B3595068778DD592e39A122f4f5a5cF09C90fE2',
  amount: 1_000_000_000_000_000_000n,
  sender: '0x0000000000000000000000000000000000000000',
  maxSlippage: 0.005,
  simulate: true,
})

if (swap.status === 'Success') {
  await publicClient.call({
    account: swap.tx.from,
    to: swap.tx.to,
    data: swap.tx.data,
    value: swap.tx.value,
  })

  await walletClient.sendTransaction({
    account: swap.tx.from,
    to: swap.tx.to,
    data: swap.tx.data,
    value: swap.tx.value,
  })
}
```

When `simulate` is enabled, successful responses may include `tx.gas`.

## Notes

* ERC-20 swaps require allowance before execution.
* Native token inputs do not require ERC-20 approval.
* `sender` is the transaction sender. `recipient` is the output token recipient.
* See [API Errors](/api/errors) for insufficient allowance, insufficient balance, gas estimate, API key, rate limit, and validation errors.
