---
title: "Find optimal route between tokens (direct routes, zaps)"
method: POST
path: "/api/v1/shortcuts/route"
tags: ["shortcuts"]
---

# Find optimal route between tokens (direct routes, zaps)

`POST /api/v1/shortcuts/route`

## Request

- Base URL: `https://api.enso.finance`
- URL: `https://api.enso.finance/api/v1/shortcuts/route`
- Auth: HTTP bearer

## Request body

- RouteShortcutVariableInputs
  - `chainId` number, required: Chain ID of the network to execute the transaction on
  - `fromAddress` string, required: Ethereum address of the wallet to send the transaction from
  - `routingStrategy` 'ensowallet-v2' | 'router' | 'delegate' | 'router-legacy' | 'delegate-legacy', nullable: Routing strategy to use
  - `executionMode` 'user' | 'backend': Controls how quote is built based on execution mode
  - `toEoa` boolean, nullable: Flag that indicates if gained tokenOut should be sent to EOA
  - `includeTransactionCost` boolean: Include point-in-time source-chain transaction cost estimates in native units and USD, plus USD values for reported bridge fees
  - `useIntentAddress` boolean: Route a cross-chain request through an intent address on the destination chain. The bridge delivers to that address, then a keeper runs the destination route and sends tokenOut to the receiver. When omitted, intents are used if both chains support them. Set to false to use a bridge callback instead. Ignored for same-chain routes.
  - `spender` string: Ethereum address of the spender of the tokenIn
  - `refundReceiver` string: Ethereum address of the receiver of any dust tokens produced during execution. Required for routes to Solana.
  - `amountIn` string[], required: Amount of tokenIn to swap in wei
  - `minAmountOut` string[]: Minimum amount out in wei. If specified, slippage should not be specified
  - `slippage` string: Slippage in basis points (1/10000). e.g. 50 = 0.50%. If specified, minAmountOut should not be specified
  - `ignoreAggregators` string[], nullable: A list of swap aggregators to be ignored from consideration
  - `ignoreStandards` string[], nullable: A list of standards to be ignored from consideration
  - `ignoreBridges` string[]: A list of bridges to be ignored from consideration
  - `crosschainRouteMode` 'direct' | 'source' | 'destination' | 'sourceOrDestination' | 'full': Controls cross-chain route complexity. direct uses only a bridge, source allows routing before the bridge, destination allows routing after the bridge, sourceOrDestination allows routing on either chain but not both, and full allows routing on both chains
  - `effort` 'light' | 'medium' | 'high' | 'max': Latency/quality trade-off for pathfinding and aggregator querying. light returns fastest over a reduced search space (short aggregator wait with early return once two usable quotes arrive, fewer candidate paths, no destination-side bridge routing), medium waits the full short window over the full search space, high is the default balanced behavior, and max queries all aggregators in parallel with an extended wait for best execution (higher CU cost)
  - `referralCode` string: Referral code that will be included in an on-chain event.
  - `tokenIn` string[], required: Ethereum address of the token to swap from. For ETH, use 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
  - `tokenOut` string[], required: Destination token addresses. Solana mints are case-sensitive; native SOL uses 11111111111111111111111111111111.
  - `receiver` string: Destination recipient. Required for cross-chain routes; Solana uses a case-sensitive Base58 address.
  - `destinationChainId` number: Chain ID of the network to bridge to and receive tokenOut
  - `allowAsync` boolean: Allow async redeems, where tokenOut is paid after the transaction. An async route returns amountOut, minAmountOut and priceImpact as null and describes the payout in `async`. Cannot be combined with minAmountOut or useIntentAddress, intents do not support async redeems.

## Response `200`

- RouteShortcutTransaction
  - `gas` string, required
  - `amountOut` union, required: Null for async routes, see `async.estimatedAmountOut`
    - string
    - string[]
  - `blockNumber` number: Block number the quote was simulated against
  - `priceImpact` number, nullable: Price impact in basis points, null if USD price not found
  - `feeAmount` string[]: An array of the fee amount collected for each tokenIn
  - `ensoFeeAmount` string[]: An array of the enso fee amount collected for each tokenIn, when applicable
  - `metadata` ShortcutResponseMetadata, required
    - `bridgeRefundAssets` BridgeRefundAsset[], required: Protocol-specific refund destinations for bridge principal in the returned transaction. An entry does not guarantee that every bridge failure is refundable.
      - `protocol` 'cctp' | 'stargate' | 'ccip' | 'relay' | 'layerzero-teller' | 'arbitrum-native' | 'mayan', required
      - `chainId` number, required
      - `token` string, required: Address of the bridge principal token that may be refunded
      - `recipient` string, required: Address that would receive the bridge principal refund
      - `symbol` string: Token symbol when metadata is available
    - `bridgeFees` BridgeFee[]: Bridge protocol and intent execution fees
      - `protocol` string, required: Bridge protocol associated with the fee
      - `component` 'bridge' | 'intentExecution', required
      - `chainId` number, required: Chain on which the fee is paid
      - `destinationChainId` number, required: Destination chain of the bridge action
      - `token` string, required: Token used to pay the bridge fee
      - `type` 'maximum' | 'quoted', required: Whether amount is a maximum reserved for execution or a quote-time fee breakdown
      - `deductedFromAmountOut` boolean, required: Whether the fee has already reduced the candidate amountOut and must not be subtracted again when scoring.
      - `amount` string, required: Bridge fee in the token base unit.
      - `amountUsd` string, nullable: Bridge fee in USD when includeTransactionCost=true and pricing is available
    - `bridgeFeeUsd` string, nullable: USD sum of the reported bridge protocol and intent execution fee amounts when includeTransactionCost=true. May include maximum fee reserves. Null when any non-zero fee cannot be priced.
  - `async` AsyncRedeem
    - `chainId` number, required: Chain the redeem request is filed on, where `claim`, `status` and `cancel` live. Cross-chain, this is the destination chain
    - `tokenIn` string, required: Token the redeem request was filed for
    - `amountIn` string, required: Amount of tokenIn in the request, after fees. When other steps come before the redeem, this is their estimated output
    - `tokenOut` string, required: Token paid out when the redeem settles
    - `estimatedAmountOut` string, required: Expected tokenOut payout at current rates. See `pricing` for how binding it is
    - `estimatedMinAmountOut` string, required: Expected tokenOut payout at current rates for the smallest amountIn the transaction allows after slippage. Equal to estimatedAmountOut when nothing before the request can slip. Not enforced on-chain, see `pricing`
    - `priceImpact` number, nullable: Price impact in basis points between the input and estimatedAmountOut, null if USD price not found
    - `pricing` 'fixed' | 'capped' | 'atSettlement', required: `fixed`: the payout is locked at request. `capped`: the lower of the request and settlement rates. `atSettlement`: determined when the redeem settles
    - `beneficiary` string, required: Account entitled to the payout
    - `claim` AsyncRedeemClaim, required
      - `type` 'erc721' | 'erc1155' | 'request' | 'erc7540' | 'account', required: What the beneficiary holds after the transaction: an ERC-721 or ERC-1155 receipt, a request id recorded for the beneficiary, an ERC-7540 request under the beneficiary as controller, or per-account state
      - `contract` string, required: Contract holding the claim
      - `transferable` boolean, required: Whether the claim can be transferred
      - `idFrom` AsyncRedeemClaimId
        - `event` string, required: Human-readable ABI fragment of the event that carries the claim id. `claim.contract` emits it in the transaction that files the request on `chainId`. Cross-chain, that is the destination transaction, not the one the user signs
        - `arg` string, required: Event argument holding the claim id
    - `settlement` AsyncRedeemSettlement, required
      - `type` 'push' | 'claim', required: `push`: the protocol sends tokenOut to the beneficiary (or current receipt holder) without further action. `claim`: a transaction must be sent to `call` once the redeem is claimable
      - `by` 'holder' | 'controller' | 'anyone': Who may send the claim transaction. Present for `claim`
      - `call` AsyncRedeemCall
        - `contract` string, required: Contract to call
        - `signature` string, required: Human-readable ABI fragment, e.g. `function claimWithdrawal(uint256 requestId)`
    - `timing` AsyncRedeemTiming
      - `kind` 'delay' | 'queue' | 'epoch' | 'operator', required: What the wait depends on: a fixed delay, a queue, an epoch, or an operator
      - `minSeconds` number
      - `estimatedSeconds` number
      - `claimWindowSeconds` number: Seconds the claim stays claimable before it expires
    - `cancel` AsyncRedeemCancel
      - `contract` string, required: Contract to call
      - `signature` string, required: Human-readable ABI fragment, e.g. `function claimWithdrawal(uint256 requestId)`
      - `by` 'holder' | 'controller' | 'beneficiary', required: Who may cancel
    - `refund` AsyncRedeemRefund
      - `by` string[], required: Who can unwind the request: the user through `cancel`, a protocol `operator`, or the protocol itself (`automatic`), for example when the payout fails
      - `settlement` AsyncRedeemRefundSettlement, required
        - `type` 'push' | 'claim' | 'manual', required: `push`: tokenIn is sent back to `beneficiary`, the account set at request, even if the claim was transferred. `claim`: a transaction must be sent to `call` to get tokenIn back. `manual`: nothing returns tokenIn on-chain, the protocol settles it off-chain
        - `by` 'holder' | 'controller' | 'anyone': Who may send the refund claim. Present for `claim`
        - `call` AsyncRedeemCall
          - `contract` string, required: Contract to call
          - `signature` string, required: Human-readable ABI fragment, e.g. `function claimWithdrawal(uint256 requestId)`
    - `status` AsyncRedeemCall
      - `contract` string, required: Contract to call
      - `signature` string, required: Human-readable ABI fragment, e.g. `function claimWithdrawal(uint256 requestId)`
  - `minAmountOut` union: The minimum allowable amount out after slippage. Null for async routes, see `async.estimatedMinAmountOut`
    - string
    - string[]
  - `intent` IntentResponse
    - `address` string, required
    - `data` object, required
  - `createdAt` number, required: Block number the transaction was created on
  - `tx` Transaction, required
    - `data` string, required
    - `to` string, required
    - `from` string, required
    - `value` string, required
  - `route` Hop[], required: Simple description of meta actions the route takes
    - `tokenIn` string[], required
    - `tokenOut` string[], required
    - `protocol` string, required
    - `action` 'approve' | 'borrow' | 'borrowwithpositionid' | 'deposit' | 'singledeposit' | 'singledepositwithpositionid' | 'multideposit' | 'multidepositwithpositionid' | 'tokenizedsingledeposit' | 'tokenizedmultideposit' | 'multioutsingledeposit' | 'depositclmm' | 'depositwithestimate' | 'encodedswap' | 'flashloan' | 'singletokenflashloan' | 'multitokenflashloan' | 'harvest' | 'nftborrow' | 'nftdeposit' | 'nftmultideposit' | 'nftmultiredeem' | 'nftredeem' | 'nftrepay' | 'permittransferfrom' | 'redeem' | 'singleredeem' | 'singleredeemwithpositionid' | 'multiredeem' | 'tokenizedsingleredeem' | 'tokenizedmultiredeem' | 'redeemclmm' | 'redeemwithestimate' | 'repay' | 'repaywithpositionid' | 'requestredeem' | 'swap' | 'transfer' | 'transferfrom' | 'withdraw' | 'singlewithdraw' | 'singlewithdrawwithpositionid' | 'multiwithdraw' | 'bridge' | 'route' | 'call' | 'split' | 'merge' | 'ondosplit' | 'ondomerge' | 'balance' | 'minamountout' | 'slippage' | 'fee' | 'ensofee' | 'paymasterfee' | 'depositposition' | 'add' | 'sub' | 'mul' | 'div' | 'min' | 'max' | 'isequal' | 'islessthan' | 'isequalorlessthan' | 'isgreaterthan' | 'isequalorgreaterthan' | 'not' | 'check' | 'toggle', required
    - `primaryAddress` string
    - `internalRoutes` string[]
    - `args` object
    - `sources` string[]
    - `poolAddresses` string[]
    - `estimatedAmountOut` string[]: Only available for split actions returned by the pathfinder routing engine. Display estimates use the planned split input, are ordered to match tokenOut, and are not execution guarantees
    - `chainId` number
    - `sourceChainId` number
    - `destinationChainId` number
    - `positionOut` string[]: Non-tokenized position ID for deposit actions
    - `via` 'cctp-forwarder': Off-chain settler for this hop. Set when the hop is descriptive metadata rather than a weiroll call in `tx.data` — execution happens asynchronously via the named external system (e.g. Circle's CctpForwarder credits HyperCore on CCTP message receipt). Absent on hops that are actual on-chain weiroll calls.
  - `detailedRoute` string[]: Detailed description of the route
  - `userOp` UserOperation
    - `callData` string, required
    - `callGasLimit` string, required
    - `factory` string
    - `factoryData` string
    - `maxFeePerGas` string, required
    - `maxPriorityFeePerGas` string, required
    - `nonce` string, required
    - `paymaster` string
    - `paymasterData` string
    - `paymasterPostOpGasLimit` string
    - `paymasterVerificationGasLimit` string
    - `preVerificationGas` string, required
    - `sender` string, required
    - `signature` string, required
    - `verificationGasLimit` string, required
  - `preTransactions` PreTransaction[]: Transactions that may need to be executed before the main shortcut transaction. Token approvals should be skipped when the current allowance is already sufficient.
    - `type` 'tokenApproval' | 'requiredApproval', required
    - `tx` Transaction, required
      - `data` string, required
      - `to` string, required
      - `from` string, required
      - `value` string, required
    - `token` string: Token whose allowance is being set
    - `spender` string: Account receiving the token allowance
    - `amount` string: Total allowance required by the shortcut
    - `description` string: Human-readable explanation for a required approval
  - `bridgingEstimates` BridgeLatencyEstimate[]: Estimated bridging durations when applicable
    - `fromChainId` number, required
    - `toChainId` number, required
    - `token` string, required: Token bridged to the destination chain
    - `estimatedSeconds` number, required: Estimated bridge latency in seconds
    - `sendConfirmations` number: Send confirmations used for the estimation
    - `receiveConfirmations` number: Receive confirmations
    - `sendBlockTimeSeconds` number: Average block time assumed for the source chain (seconds)
    - `receiveBlockTimeSeconds` number: Average block time assumed for the destination chain (seconds)
    - `bridge` string: Bridge implementation or provider that produced the estimate
    - `source` 'protocol' | 'measured' | 'model' | 'defaults' | 'override' | 'fallback': Source of the data (protocol, measured, model, defaults, override, fallback)
    - `note` string: Optional note describing overrides or fallbacks applied
  - `validUntil` number: Unix timestamp (seconds) after which this quote expires. Transactions submitted after this time may revert. On an intent route a late transaction still bridges, but the bridged token is refunded on the destination chain instead of being swapped.
  - `transactionCost` string, nullable: Point-in-time lower-bound estimate of mandatory source-chain transaction fees in the native token smallest unit. Excludes priority fees, transaction value, bridge fees, and destination execution.
  - `transactionCostUsd` string, nullable: Decimal string USD value of transactionCost. Null when the native-token price or source-chain fee estimate is unavailable.

## Other responses

- `400`

## Changes

- **2026-11-02** `d43e21a824af`: 1 warning, 1 info
  - added the new `mayan` enum value to the `metadata/bridgeRefundAssets/items/protocol` response property for the response status `200`
  - added the new `mayan` enum value to the request property `ignoreBridges/items/`
- **2026-10-27** `a1e1127d32ef`: 1 info
  - added the new optional request property `effort`
- **2026-10-27** `c773c4a1ffeb`: 1 info
  - added the new optional request property `useIntentAddress`
- **2026-10-20** `5e19cbf17e08`: 1 info
  - added the new `akka` enum value to the request property `ignoreAggregators/items/`
- **2026-10-14** `bffb96f7340b`: 2 breaking, 2 info
  - the response property `amountOut` became nullable for the status `200`
  - the response property `minAmountOut` became nullable for the status `200`
  - added the new optional request property `allowAsync`
  - added the optional property `async` to the response with the `200` status

[Operation history](https://skmtc.dev/enso/apis/enso-api-2/changes/api/v1/shortcuts/route/post.md)

---

[API](https://skmtc.dev/enso/apis/enso-api-2.md) - [All operations](https://skmtc.dev/enso/apis/enso-api-2/llms.txt) - [OpenAPI document](https://skmtc.dev/enso/apis/enso-api-2/revisions/d43e21a824af?raw)
