> ## Documentation Index
> Fetch the complete documentation index at: https://turnkey-0e7c1f5b-docs-frames-cross-origin-breaking-change.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Get a Swap Quote

> Request executable quotes for a token pair from a Turnkey wallet, priced net of all fees, with the minimum output enforced at execution.

**Prerequisites:**

* Your parent organization has enabled Swaps via [`ACTIVITY_TYPE_UPSERT_SWAP_CONFIG`](/features/transaction-management/swap/enable-swap) with a valid `feeReceiverWalletAddress` and `feeBps`. Quote requests against organizations without the Swaps feature flag will fail. Without a swap configuration, quotes default to a client fee of 0. See [`Enable Swaps`](/features/transaction-management/swap/enable-swap).
* The signing address (`signWith`) is a wallet account in the organization submitting the activity. Parent organization wallets and sub-organization wallets can both swap: the activity belongs to the organization that owns the wallet. In a delegated access setup, a delegate can submit the activity to the wallet owner's organization or act as the second signer on an activity submitted by the wallet owner.

<Note>
  Swaps is currently an Early Access Product. [Contact us](https://www.turnkey.com/contact-us) to enable it for your organization.
</Note>

## Call create\_swap\_quote

Quoting is an activity: submit an [`ACTIVITY_TYPE_CREATE_SWAP_QUOTE`](/api-reference/activities/get-swap-quote) activity with the standard envelope (`type`, `timestampMs`, `organizationId`) and a `parameters` object.

<ParamField body="organizationId" type="string" required>
  The organization that owns the swapping wallet. Parent organizations and sub-organizations can both swap; the parent's swap configuration applies in either case.
</ParamField>

<ParamField body="parameters.signWith" type="string" required>
  The wallet account address that will sign and fund the swap. Quotes are computed against this address, so balances and allowances are reflected accurately.
</ParamField>

<ParamField body="parameters.inputToken" type="string" required>
  CAIP-19 identifier for the asset being sold, e.g. `eip155:8453/erc20:0x833589fCD6EDB6E08f4c7C32D4f71b54bdA02913` (USDC on Base). The origin chain is derived from this identifier.
</ParamField>

<ParamField body="parameters.outputToken" type="string" required>
  CAIP-19 identifier for the asset being bought. If its CAIP-2 prefix matches `inputToken`, the swap is same-chain; otherwise it's a cross-chain route. Native assets use `slip44:`, e.g. `eip155:137/slip44:966` (POL).
</ParamField>

<ParamField body="parameters.inputAmount" type="string" required>
  In raw onchain units of the input asset, e.g. `"1000000"` for 1 USDC at 6 decimals.
</ParamField>

<ParamField body="parameters.slippageBps" type="string">
  Slippage tolerance in basis points as a stringified integer, e.g. `"50"` for 0.5%. Used to compute each quote's `minOutputAmount`.
</ParamField>

cURL:

```bash title="cURL" theme={"system"}
curl --request POST \
  --url https://api.turnkey.com/public/v1/submit/create_swap_quote \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header "X-Stamp: <string> (see Stamps)" \
  --data '{
    "type": "ACTIVITY_TYPE_CREATE_SWAP_QUOTE",
    "timestampMs": "<string> (e.g. 1745474677453)",
    "organizationId": "<ORGANIZATION_ID>",
    "parameters": {
      "signWith": "<WALLET_ACCOUNT_ADDRESS>",
      "inputToken": "eip155:8453/erc20:0x833589fCD6EDB6E08f4c7C32D4f71b54bdA02913",
      "outputToken": "eip155:8453/erc20:0x4200000000000000000000000000000000000006",
      "inputAmount": "1000000",
      "slippageBps": "50"
    }
  }'
```

JavaScript:

```javascript title="JavaScript" theme={"system"}
import { TurnkeyClient } from "@turnkey/http";
import { ApiKeyStamper } from "@turnkey/api-key-stamper";

const client = new TurnkeyClient(
  { baseUrl: "https://api.turnkey.com" },
  new ApiKeyStamper({
    apiPublicKey: process.env.TURNKEY_API_PUBLIC_KEY,
    apiPrivateKey: process.env.TURNKEY_API_PRIVATE_KEY,
  }),
);

const { activity } = await client.request("/public/v1/submit/create_swap_quote", {
  type: "ACTIVITY_TYPE_CREATE_SWAP_QUOTE",
  timestampMs: String(Date.now()),
  organizationId: "<ORGANIZATION_ID>",
  parameters: {
    signWith: "<WALLET_ACCOUNT_ADDRESS>",
    inputToken: "eip155:8453/erc20:0x833589fCD6EDB6E08f4c7C32D4f71b54bdA02913",
    outputToken: "eip155:8453/erc20:0x4200000000000000000000000000000000000006",
    inputAmount: "1000000",
    slippageBps: "50",
  },
});

const { quotes } = activity.result.createSwapQuoteResult;
const bestQuote = quotes[0];
```

Response:

```json theme={"system"}
{
  "activity": {
    "id": "<ACTIVITY_ID>",
    "status": "ACTIVITY_STATUS_COMPLETED",
    "type": "ACTIVITY_TYPE_CREATE_SWAP_QUOTE",
    "result": {
      "createSwapQuoteResult": {
        "quotes": [
          {
            "quoteId": "<QUOTE_ID>",
            "provider": "relay",
            "outputAmount": "<EXPECTED_OUTPUT>",
            "minOutputAmount": "<MINIMUM_OUTPUT>",
            "clientFeeBps": "<YOUR_FEE_IN_BPS>",
            "slippageBps": "<SLIPPAGE_TOLERANCE>",
            "estimatedTimeSeconds": "<ESTIMATED_TIME>",
            "expiresAt": "<EXPIRY_MS>"
          }
        ]
      }
    }
  }
}
```

## Read the response

The result contains a quotes array. Each quote is executable as-is:

```json theme={"system"}
{
  "activity": {
    "result": {
      "createSwapQuoteResult": {
        "quotes": [
          {
            "provider": "relay",
            "quoteId": "sq_v1_d47bcb2192150649280454baa8a48f1cf4b1e5270997901436c2d907eecca6ac",
            "outputAmount": "6599005722903595711",
            "minOutputAmount": "6566010694289072050",
            "slippageBps": "50",
            "clientFeeBps": "1",
            "estimatedTimeSeconds": "2",
            "expiresAt": "1786453118047"
          }
        ]
      }
    }
  }
}
```

* `quoteId` — identifies this quote. Pass it to `ACTIVITY_TYPE_EXECUTE_SWAP_V2` to execute against this quote's pricing; execution is pinned to the quote it references.
* `provider` — the provider that produced the quote and will execute the swap.
* `outputAmount` — expected output in raw onchain units, net of all fees. This is what the recipient receives if the swap fills at the quoted price.
* `minOutputAmount` — the floor enforced at execution, derived from `outputAmount` and your slippage tolerance. If the swap cannot deliver at least this amount, it fails rather than filling worse.
* `slippageBps` — the slippage tolerance this quote was priced with, echoed from the request.
* `clientFeeBps` — your organization's configured fee, for display or audit. Turnkey's fee is baked into the quoted amounts and is not itemized. See [Fees](/features/transaction-management/swap#fees).
* `estimatedTimeSeconds` — estimated time to settlement.
* `expiresAt` — millisecond epoch after which the quote can no longer be executed.

## Execution price semantics

Execution is pinned to the quote: [`ACTIVITY_TYPE_EXECUTE_SWAP_V2`](/features/transaction-management/swap/execute-swap) references a `quoteId`, and the signed intent carries that quote's `quotedOutputAmount` and `minOutputAmount`. The economics your user signs are the economics that execute.

Within those bounds, the actual fill can move:

* `minOutputAmount` is the enforced floor. If the swap cannot deliver at least this amount, it will fail — the user never receives less than the floor they signed.
* `outputAmount` is the expected fill, not a guarantee. The settled amount can be higher or lower than quoted, bounded on the low side by `minOutputAmount`. The actual amount is reported as `outputAmount` in swap status on `COMPLETED`.
* Quotes expire. A quote can only be executed before its `expiresAt`; after that, request a new quote. Quotes may still be technically valid while the route the quote describes is no longer available in the market due to price movements. In that situation, if the quote cannot be executed with the economic parameters, it will fail at execution time.

**Important:** Neither Turnkey nor the underlying DEX aggregator guarantees execution at any quoted price. Users bear the risk of adverse price movement between the time of quote and the time of execution.

## Slippage

Slippage is the difference between the price reflected in a quote and the price at which the swap actually executes onchain. It occurs because prices can move between quoting and execution. Low-liquidity pairs, large trade sizes, and periods of high network activity can increase slippage.

You set your tolerance at quote time via `slippageBps`, in basis points (e.g. `"50"` for 0.5%). Each quote derives its `minOutputAmount` from the quoted `outputAmount` and your tolerance, and the signed execute intent carries that floor. If the swap would return less than `minOutputAmount`, it fails rather than filling worse.

Choosing a tolerance is a tradeoff worth surfacing to your users:

* A tighter slippage tolerance reduces the risk of an unfavorable fill but increases the chance the swap fails if the market moves.
* A wider tolerance makes execution more likely but exposes the user to a worse price, down to the floor.
* A swap that fails on the floor still incurs gas for the reverted origin transaction. If the swap is sponsored, that cost falls on your organization, not the user — slippage-driven reverts are a gas cost to budget for in sponsored flows.

Quotes expire at `expiresAt`; if a quote has expired before the user confirms, request a new one rather than executing stale economics. Quotes are more likely to succeed the closer they are generated to execution time.

## How fees are applied

Every quote's `outputAmount` and `minOutputAmount` already reflect all fees — Turnkey's and yours. There is no fee math to do on your side: the amount you display to the user is the quote's `outputAmount`, and the amount they receive is the settled `outputAmount` from swap status.

Your fee configuration is applied when the quote is created. The fee baked into a quote travels with it: executing a quote settles at that quote's economics, even if you change your fee configuration in between. Fee changes take effect for new quotes.

## Same-chain vs. cross-chain quotes

Quote shape is identical for same-chain and cross-chain routes. Whether a swap is same-chain or cross-chain is determined by the CAIP-2 prefixes of `inputToken` and `outputToken`; the provider selects the route within that. Same-chain routes cover EVM and Solana. Cross-chain routes are EVM ↔ EVM, with EVM ↔ SVM coming soon.

Cross-chain quotes are subject to the same freshness and slippage semantics as same-chain quotes, but cross-chain execution has a longer post-broadcast lifecycle — the swap stays `PENDING` until the destination leg settles or funds are refunded. See [Track swap status](/features/transaction-management/swap/track-swap-status) for the two lifecycle models.

## Next steps

* [Execute a swap](/features/transaction-management/swap/execute-swap): the signing activity that runs the swap end-to-end.
* [Track swap status](/features/transaction-management/swap/track-swap-status): same-chain vs. cross-chain polling.
