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

# Sell exact or buy exact

> Fix the amount you sell, or the amount you buy. Venues quote the other side.

Every quote request fixes one side of the trade with exactly one amount: `sellAmount` or `buyAmount`. Each venue quotes the other side.

| You send | It is | Each quote states | Quotes are sorted by default |
| - | - | - | - |
| `sellAmount` | What you sell, in units of `sell.asset` | `buy.amount`, what you would buy | Most bought first, by `netReceived` |
| `buyAmount` | What you buy, in units of `buy.asset` | `sell.amount`, what you would sell | Least sold first |

The amount is a positive decimal string in Asset units: `"10"` is ten USDC and `"0.001"` is a thousandth of an ETH, never base units. Send it as a string so no digits are lost. Send one of the two: a body with both, or with neither, is refused with `400 INVALID_REQUEST`.

## How amounts are read

* A venue may price a slightly smaller amount than you sent, rounded down to the precision it trades in. The quote states the amount it actually used: a request to sell `"100"` can come back with `sell.amount` of `"99.99994"`.
* `buy.amount` is what lands at `deliverTo` after every fee the quote includes. `netReceived` also subtracts fees you pay separately, such as a network fee, so you can compare quotes fairly. It reads `{"kind": "unavailable", "reason": ...}` when a fee could not be read, never 0.
* With `sort: "eta"`, quotes are ordered by expected time to delivery instead.

## Sell exact

```bash cURL theme={null}
# Sell exactly `amount` of the sell asset. Each quote states what you would buy.
request=$(jq -nc --arg sell "$sell" --arg buy "$buy" --arg amount "$amount" '{
  sell: {asset: $sell},
  buy: {asset: $buy},
  sellAmount: $amount
}')
sell_exact=$(quote_request "$request")
jq -c '.quotes[] | {venue: .legs[0].venue.id, location: .location.kind,
  firm, sell: .sell.amount, buy: .buy.amount, expiresAt}' <<<"$sell_exact" >&2
```

```typescript TypeScript SDK theme={null}
// Sell exactly 10 USDC. Each quote says how much ETH you would receive for it.
const sellExact = await client.quote({
  sell: { asset: usdc.assetId },
  buy: { asset: eth.assetId },
  sellAmount: '10',
  filters: { locations: ['offChain'] },
});
// An order book trades in whole lot sizes, so it may spend a little less than you asked. It never spends
// more, and `unspent` says how much stays in your account.
const overspent = sellExact.quotes.filter((quote) => quote.sell.amount !== null && Number(quote.sell.amount) > 10);
```

## Buy exact

```bash cURL theme={null}
# Buy exactly `buy_amount` of the buy asset. Each quote states what you would sell.
# A venue that only prices the amount you sell is listed in sources as unsupported.
request=$(jq -nc --arg sell "$sell" --arg buy "$buy" --arg amount "$buy_amount" '{
  sell: {asset: $sell},
  buy: {asset: $buy},
  buyAmount: $amount
}')
buy_exact=$(quote_request "$request")
jq -c '.quotes[] | {venue: .legs[0].venue.id, sell: .sell.amount, buy: .buy.amount}' <<<"$buy_exact" >&2
jq -c '[.sources[] | select(.status == "unsupported") | {venue: .venue.id, reason}]' <<<"$buy_exact" >&2
```

```typescript TypeScript SDK theme={null}
// Buy exactly 0.001 ETH. Each quote says how much USDC it would cost.
const buyExact = await client.quote({
  sell: { asset: usdc.assetId },
  buy: { asset: eth.assetId },
  buyAmount: '0.001',
  filters: { locations: ['offChain'] },
});
// A venue that cannot fix the output names it in sources, for example `buyAmountUnsupported`.
// When none can, the set is empty: that is an answer, and `sources` says why for each venue.
const buyPriced = buyExact.quotes.length > 0;
const buyMismatch = buyExact.quotes
  .filter((quote) => quote.buy.amount !== null && Number(quote.buy.amount) !== 0.001);
```

Not every venue can quote a fixed buy amount. A venue that only prices the amount you sell is listed in `sources` with the token `buyAmountUnsupported`, and is not asked. An on-chain protocol or bridge shows it as an `unsupported` row with the token in `reason`:

```json theme={null}
{ "status": "unsupported", "venue": { "id": "...", "modality": "bridge" }, "asked": false, "reason": "buyAmountUnsupported", "detail": null }
```

A venue you trade through your own exchange or OTC account can show the same limit as a `filteredOut` row, with the token in `detail`. An on-chain venue that cannot deliver an exact amount uses `exactOutputDeliveryUnsupported`. Check both `reason` and `detail` for these tokens.

In practice, on-chain protocols, bridges and some exchanges quote only the amount you sell, so a buy-exact search usually returns fewer quotes. When no venue can quote it, you get an empty `quotes` list and every venue's reason in `sources`. Send `sellAmount` instead, sized from a [price](https://tetrafi.mintlify.site/search/prices.md).

On [`GET /api/v1/prices`](https://tetrafi.mintlify.site/search/prices), the same limit uses the same `buyAmountUnsupported` reason on an `unsupported` row.

## What filters do to venues

Which amount you fix excludes no venue by itself: a venue that cannot serve it reads `unsupported`, as above. Venues your [filters](https://tetrafi.mintlify.site/search/how-it-works.md#the-request) exclude read `filteredOut` and are not asked.

## Refusals

| Code | Why | What to do |
| - | - | - |
| `INVALID_AMOUNT` | `sellAmount` or `buyAmount` is not a positive decimal: zero, negative or not a number. | Send a positive decimal string such as `"10"`. |
| `INVALID_REQUEST` | The body has both `sellAmount` and `buyAmount`, or neither, or the amount is not a string. `message` names the field. | Send exactly one amount, as a string. |

## In the app

On the Trade page, choose in the trade ticket whether the amount you type is the amount you sell or the amount you buy.


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