> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useroutr.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quotes and routes

> Price what your user sends in the asset they hold, and lock the route that delivers it.

A funding intent says what you need. A quote says, for the asset your user holds, how much they
send and which route turns it into your asset. The destination is always the intent's; a quote
only chooses the source.

If your user already holds the asset you asked for, skip quotes entirely: the intent is payable
as it is.

## Quote, then lock

```ts theme={null}
const quote = await useroutr.quotes.create(intent.id, {
  source: { network: "stellar", asset: "asset_xlm_stellar" },
});

console.log(quote.source.amount); // the most your user sends
console.log(quote.fees.total); // every fee, itemised in quote.fees.items

await useroutr.quotes.select(quote.id);
```

Selecting locks the route. From then on the intent's `funding_instructions` ask for the quote's
asset and amount, and the hosted checkout shows the same. There is no execute call: the route
runs automatically once the payment is confirmed, exactly as quoted. A moving market never
re-prices a locked quote.

## Two kinds of quote

<Tabs>
  <Tab title="Exact output (default)">
    Your amount is fixed. The quote says the most your user sends, including slippage.
    `source.expected_amount` is what the route should use, and anything unused is refunded to your
    user after the swap.

    ```ts theme={null}
    await useroutr.quotes.create(intent.id, {
      source: { network: "stellar", asset: "asset_xlm_stellar" },
    });
    ```
  </Tab>

  <Tab title="Exact input">
    Your user fixes what they send and the route decides what arrives. The guaranteed delivery must
    still cover your amount, or the quote is refused with `INSUFFICIENT_INPUT`. You are credited
    exactly your amount; anything above it goes back to your user.

    ```ts theme={null}
    await useroutr.quotes.create(intent.id, {
      type: "EXACT_INPUT",
      source: { network: "stellar", asset: "asset_xlm_stellar", amount: "48" },
    });
    ```
  </Tab>
</Tabs>

## Routes

| Route | When |
| - | - |
| `DIRECT_STELLAR` | Your user pays in the asset you asked for. Costs nothing. |
| `STELLAR_SWAP` | A different Stellar asset, swapped inside the intent's deposit account |
| `CROSS_CHAIN` | An asset bridged between Stellar and another network |
| `DIRECT_EVM` | Your user pays in the asset you asked for, on the same network you receive on, such as USDC on Base to USDC on Base. It is forwarded to you on that network. Costs nothing. |
| `COMPOSED` | Two or three legs through Stellar, when no single route reaches your asset: a bridge and a swap, or a bridge in and a bridge out with a swap between them if needed |

Your user always sees one route, one amount and one deposit address, whatever happens behind it.

## Fees and slippage

`fees` lists every fee by category (`NETWORK`, `PROVIDER`, `SWAP`, `BRIDGE`, `USEROUTR`) with a
`total` in the source asset. Useroutr adds nothing to the rate: a pool's own fee is part of its
price and shows in `expected_amount`. `slippage_bps` applies to swaps only and defaults to 100
(1%); pass 1 to 5000 to change it.

## Expiry and locks

A quote can be selected until `expires_at`. Once locked, the lock lasts until
`lock_expires_at` if nothing arrives; after a payment arrives the lock holds until the route
finishes. If a lock lapses unpaid, the intent goes back to its own asset and you can quote
again.

| Error | Meaning |
| - | - |
| `NO_ROUTE_AVAILABLE` | No route can deliver this pair |
| `INSUFFICIENT_INPUT` | An exact input buys less than your amount |
| `QUOTE_EXPIRED` | The quote passed `expires_at` |
| `QUOTE_NOT_SELECTABLE` | The intent cannot take a quote now, for example it is already paid |
| `CONFLICT` | Another quote is already locked for this intent |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.