> For the complete documentation index, see [llms.txt](https://docs.swapkit.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.swapkit.dev/swapkit-api/v3-swap-obtain-swap-transaction-details.md).

# /v3/swap - Obtain swap transaction details

**Method:** `POST`\
**URL:** `https://api.swapkit.dev/v3/swap`

After the user has accepted a quote, perform a request to the `/swap` endpoint to obtain transaction details. Use a quote's `routeId` to identify it (it is cached for 5 minutes), providing additional details about the involved addresses.

### Request Schema

<table><thead><tr><th width="244">Parameter</th><th width="92">Type</th><th width="96">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>routeId</code></td><td><code>string</code></td><td>Yes</td><td>The ID of the route to swap. Obtained from a previous <code>/v3/quote</code> response</td></tr><tr><td><code>sourceAddress</code></td><td><code>string</code></td><td>Yes</td><td>Blockchain address to send the asset from. Must be a valid address for the sell asset's chain</td></tr><tr><td><code>destinationAddress</code></td><td><code>string</code></td><td>Yes</td><td>Recipient blockchain address to send the asset to. Must be a valid address for the buy asset's chain</td></tr><tr><td><code>disableBuildTx</code></td><td><code>boolean</code></td><td>No</td><td>Whether to skip providing a built transaction, ready to sign by the wallet.</td></tr><tr><td><code>disableBalanceCheck</code></td><td><code>boolean</code></td><td>No</td><td>Whether to skip balance validation. If <code>false</code> or omitted, checks that source address has sufficient balance. Do not use without consulting SwapKit devs first. Default: <code>false</code></td></tr><tr><td><code>disableEstimate</code></td><td><code>boolean</code></td><td>No</td><td>Whether to skip on-chain gas estimation when building the transaction. Default: <code>false</code></td></tr><tr><td><code>allowSmartContractSender</code></td><td><code>boolean</code></td><td>No</td><td>Whether to allow the source address to be a smart contract. Do not use without consulting SwapKit devs first.  Default: <code>false</code></td></tr><tr><td><code>allowSmartContractReceiver</code></td><td><code>boolean</code></td><td>No</td><td>Whether to allow the destination address to be a smart contract. Do not use without consulting SwapKit devs first. Default: <code>false</code></td></tr><tr><td><code>disableSecurityChecks</code></td><td><code>boolean</code></td><td>No</td><td>Whether to bypass address format validation and security checks. Default: <code>false</code></td></tr><tr><td><code>overrideSlippage</code></td><td><code>boolean</code></td><td>No</td><td>Whether to bypass the 5% output amount deviation check when the quote is refreshed. Default: <code>false</code></td></tr><tr><td><code>disableSweep</code></td><td><code>boolean</code></td><td>No</td><td>Whether to disable max-spend sweep behaviour for UTXO assets (BTC, LTC, DOGE, BCH). Set to <code>true</code> to send exactly <code>sellAmount</code> and pay the fee separately instead. Default: <code>false</code></td></tr></tbody></table>

{% hint style="warning" %}
When you test your integration, use an address with enough `sellAsset` balance to cover the swap. This will ensure you receive complete responses with a valid transaction object.
{% endhint %}

For example, the request could be as simple as this (this `routeId` will not work for you, as it has now expired):

{% tabs %}
{% tab title="cURL" %}

```sh
curl -X 'POST' \
  'https://api.swapkit.dev/v3/swap' \
  -H 'Content-Type: application/json' \
  -H "x-api-key: YOUR_VARIABLE_HERE" \
  -d '{
    "routeId": "85bb4fa2-3a65-4d22-b20b-e43d028d83e6",
    "sourceAddress": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    "destinationAddress": "357a3So9CbsNfBBgFYACGvxxS6tMaDoa1P"
}'
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
A fresh quote is fetched on every `/swap` call to refresh price and slippage. Route IDs are cached for 5 minutes\
If the `routeId` is older than 5 minutes, it will not be cached anymore and won't be recognized by the swap endpoint.
{% endhint %}

#### Disabling transaction building

* `disableBuildTx` is the most effective filter. Data on where to send the tokens to swap will be provided, but the transaction building won't be performed. This avoids all balance checks and errors derived from it.
* `disableBalanceChecks` still tries to build a transaction without checking the balance of the address. This works on some chains, like EVM, but will fail on UTXO chains because building a transaction requires checking the balance (the flag is not applied).

Using them together ensures no errors from wallet balance or other transaction building errors are returned. This is only recommended for advanced integrations, where you are sure you can build the transaction yourselves.

### Swap Response Schema

<table><thead><tr><th width="271">Field</th><th width="85">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>swapId</code></td><td><code>string</code></td><td>UUID of this specific swap response.</td></tr><tr><td><code>providers</code></td><td><code>array</code></td><td>List of providers available for this route (<code>CHAINFLIP</code>, <code>THORHCAIN</code>etc.).</td></tr><tr><td><code>sellAsset</code></td><td><code>string</code></td><td>The asset being sold (e.g., <code>“ETH.ETH”</code>).</td></tr><tr><td><code>buyAsset</code></td><td><code>string</code></td><td>The asset being bought (e.g., <code>“BTC.BTC”</code>).</td></tr><tr><td><code>sellAmount</code></td><td><code>string</code></td><td>Amount of the sell asset in smallest units.</td></tr><tr><td><code>expectedBuyAmount</code></td><td><code>string</code></td><td>Estimated amount of the buy asset to be received.</td></tr><tr><td><code>expectedBuyAmountMaxSlippage</code></td><td><code>string</code></td><td>Worst-case buy amount considering max slippage.</td></tr><tr><td><code>tx</code></td><td>varies</td><td>Explained below</td></tr><tr><td><code>approvalTx</code></td><td><code>object</code><br>(optional)</td><td>For EVM sell chain. When a token approval transaction is required to be submitted before the <code>tx</code> can be broadcasted. See <a href="#the-approvaltx-object">below</a> for more details.</td></tr><tr><td><code>targetAddress</code></td><td><code>string</code><br>(optional)</td><td>The address the swap transaction targets — a DEX aggregator/router contract for EVM swaps, or the inbound vault address for non-EVM cross-chain swaps. Optional: it is omitted for deposit-channel routes (e.g. Chainflip), where the send destination comes from the deposit address in <code>meta</code> or is resolved during <code>tx</code> building instead.</td></tr><tr><td><code>memo</code></td><td><code>string</code></td><td>Optional. Memo with instructions for swap.</td></tr><tr><td><code>fees</code></td><td><code>array</code></td><td>List of fees applied to the swap (inbound, network, affiliate, service).</td></tr><tr><td><code>estimatedTime</code></td><td><code>object</code></td><td>Estimated time for different phases of the swap.</td></tr><tr><td><code>totalSlippageBps</code></td><td><code>number</code></td><td>Expected total slippage.</td></tr><tr><td><code>legs</code></td><td><code>array</code></td><td>The different involved steps in the swap.</td></tr><tr><td><code>warnings</code></td><td><code>array</code></td><td>Potential warnings about this swap provider.</td></tr><tr><td><code>meta</code></td><td><code>object</code></td><td>Other information about the transaction. </td></tr><tr><td><code>routeId</code></td><td><code>string</code></td><td>UUID of the specific route this swap was built from — the same <code>routeId</code> returned by <code>/v3/quote</code> and passed back in the <code>/v3/swap</code> request.</td></tr><tr><td><code>sourceAddress</code></td><td><code>string</code></td><td>Blockchain address to send the asset from.</td></tr><tr><td><code>destinationAddress</code></td><td><code>string</code></td><td>Recipient blockchain address to send the asset to.</td></tr><tr><td><code>txHint</code></td><td><code>string</code><br>(enum)</td><td>Hint for how to broadcast the returned <code>tx</code>. One of <code>simpleTransfer</code> (plain value transfer), <code>transferWithMemo</code> (transfer that must include the <code>memo</code>), or <code>contractCall</code> (submit as a smart-contract / EVM transaction).</td></tr><tr><td><code>inboundAddress</code></td><td><code>string</code><br>(optional)</td><td>For deposit/memo-based providers, the protocol's inbound vault address that funds are sent to. Present only when the route settles via an inbound deposit rather than a direct contract call.</td></tr><tr><td><code>expiration</code></td><td><code>string</code><br>(optional)</td><td>Timestamp after which this quote/swap is no longer valid. Returned only by providers that supply a quote deadline. Omitted for providers that don't.</td></tr></tbody></table>

#### The `approvalTx` object

<table><thead><tr><th width="227.8984375">Field</th><th width="128.6484375">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>approvalTx.to</code></td><td><code>string</code></td><td>Token contract address to send the approval</td></tr><tr><td><code>approvalTx.from</code></td><td><code>string</code></td><td>User wallet address.</td></tr><tr><td><code>approvalTx.value</code></td><td><code>string</code></td><td>ETH value — always <code>"0"</code> for approvals.</td></tr><tr><td><code>approvalTx.data</code></td><td><code>string</code></td><td>Encoded <code>approve()</code> call data.</td></tr><tr><td><code>approvalTx.gasLimit</code></td><td><code>string</code></td><td>Estimated max gas units for the approval transaction, as a hex quantity string</td></tr><tr><td><code>approvalTx.gasPrice</code></td><td><code>string</code></td><td>Gas price in wei per gas unit, as a hex quantity string. Legacy (type-0) gas pricing.</td></tr></tbody></table>

#### The `tx` field

We provide the ready to be signed transaction in the `tx` field. It can be an object or a string, depending on the source chain of the swap.&#x20;

* VM sell chain - Ethers V6 Transaction <https://docs.ethers.org/v6/api/transaction/#Transaction>
* UTXO sell chain (BTC, BCH, LTC, DOGE) - base64 encoded PSBT ZCash sell chain - By default a base64 encoded PSBT using <https://github.com/BitGo/BitGoJS/blob/master/modules/utxo-lib/src/bitgo/UtxoPsbt.ts#L161> library is returned.We also support returning of an unsigned PCZT using <https://github.com/zcash/librustzcash> - Please reach out for more information.
* TRON sell chain - A TransactionBuilder object from the TronWeb lib <https://tronweb.network/docu/docs/API%20List/transactionBuilder/sendAsset#example>
* Cosmos sell chains (including THOR & MAYA) - A native Cosmos transaction object <https://tutorials.cosmos.network/academy/2-cosmos-concepts/3-transactions.html#generating-transactions>

As an example, for an EVM sell chain it might look like this. In this case, it's a simple transfer without any contract involved:

```json
"tx": {
        "to": "0x4e6960159d85254cb8e88483793f6fa8e9a49a4c",
        "from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
        "gas": "0x5208",
        "gasPrice": "0x9129260",
        "value": "3000000000000000000",
        "data": "0x"
    },
```

The transaction can also use [SLIP-0024 payload for verification](/spotlights/slip-0024-transaction-payload-signing.md). Reach out to use if you are interested.

***

### **Swap Errors**

<table><thead><tr><th width="179">Field</th><th width="154">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>provider</code></td><td><code>string</code></td><td>Specific provider name</td></tr><tr><td><code>errorCode</code></td><td><code>string</code></td><td>One of the possible error codes listed below.</td></tr><tr><td><code>message</code></td><td><code>string</code></td><td>Message related to the error.</td></tr></tbody></table>

#### **Error codes and messages**

<table><thead><tr><th>Error</th><th>Message</th><th width="111">Status Code</th><th>Scenario</th></tr></thead><tbody><tr><td><code>swapRouteNotFound</code></td><td>Route not found for routeId: {routeId}</td><td>404</td><td>The routeId doesn't exist in cache (expired after 5 minutes or never existed). Client must request a new quote first.</td></tr><tr><td><code>isSanctionedAddress</code></td><td>Address {address} is sanctioned or risky</td><td>400</td><td>Source or destination address flagged by screening service (Chainalysis/Elliptic). Addresses are screened against sanctions lists and risk databases</td></tr><tr><td><code>apiKeyInvalid</code> / <code>unauthorized</code></td><td>"Invalid API key" / "Unauthorized”</td><td>401</td><td>Missing, expired, or invalid API key in x-api-key header.</td></tr><tr><td><code>insufficientBalance</code></td><td>Insufficient balance for {chain} amount {amount} at address {address}</td><td>400</td><td>When <code>disableBalanceCheck</code> is <code>false</code>, source address doesn't have enough tokens to complete the swap. Balance fetched from blockchain and compared to sellAmount.</td></tr><tr><td><code>invalidSourceAddress</code></td><td>Invalid source address: {address}</td><td>400</td><td>Source address validation fails (invalid format, smart contract when not allowed, or fails security checks).</td></tr><tr><td><code>invalidDestinationAddress</code></td><td>Invalid destination address: {address}</td><td>400</td><td>Destination address validation fails (invalid format, smart contract when not allowed, or fails security checks).</td></tr><tr><td><code>outputAmountDeviationTooHigh</code></td><td>Output amount deviation too high. Original: {originalAmount}, Refreshed: {refreshedAmount}, Deviation: {percentageChange}%</td><td>400</td><td>Quote was refreshed and the new output amount deviates more than 5% from the cached quote. Protects users from price slippage. Can be bypassed with <code>overrideSlippage: true</code></td></tr><tr><td><code>noRoutesFound</code></td><td>No routes found for swap from {sellAsset} to {buyAsset}</td><td>404</td><td>When quote is refreshed, no valid routes are returned from providers. Rare - indicates liquidity dried up or all providers failed.</td></tr></tbody></table>

***

### Additional Notes

* **Quote price refresh:** The quote response is cached for 5 minutes. Each `/swap` call fetches a fresh quote from the blockchain to refresh price and slippage; after 5 minutes the `routeId` expires and `/swap` returns a `swapRouteNotFound` error. To get the swap payload, always call `/swap` with the `nextActions` from the quote response.
* **Balance check:** By default we check if the `sourceAddress` has a sufficient balance. Since OKW is already the wallet, you can use `disableBalanceCheck: true` in the body of the `/swap` request.
* **Latency:** The `/swap` endpoint is more costly and slower. It builds the transaction payload, including fetching UTXOs and building PSBT when required, performs a balance check, and automatically runs **address screening on every `/swap` call**. It also opens a deposit channel when NEAR or Chainflip providers are used, which can take up to 2.5s.&#x20;

  Calling this endpoint should only be done after the user has selected a quote as their swap route.
* The `/swap` response also carries over some of the same fields returned by `/quote`, such as `estimatedTime`, `totalSlippageBps`, and the `fees` breakdown.

Some of these can be skipped by using the optional parameters listed in the [request schema](#request-schema).

**Optional `/swap` params:**

1. `disableBalanceCheck` : skip checking the `sourceAddress` balance of the `fromAsset` . Recommended for wallets that do this check internally.
2. `disableEstimate` : skip gas estimation for EVM chains.
3. `overrideSlippage` : receive a `/swap` transaction payload even if the output amount doesn’t fit within the slippage parameter provided in the referenced `/quote` through the `routeId` (relevant if a new quote has to be fetched).
4. `overrideSlippage` : receive a `/swap` transaction payload even if the output amount doesn’t fit within the slippage parameter provided in `/quote` .
