# API Reference — POST /api/quote

Prices a swap, locks the exact TO amounts, and returns a backend-signed quote. This is the core of
a programmatic swap: you send recipients and the amounts they should receive; the API returns the
FROM cost and a `quoteId` you carry on-chain.

**Endpoint**
```txt
POST https://drip.tools/api/quote
Content-Type: application/json
```

## Request body

**Request body**
```json
{
  "chainId": 8453,
  "fromToken": "0x0000000000000000000000000000000000000000",
  "sender": "0x9246ef7F2b7fEcE8AfD8a72271A76Cc2A8d8A3E5",
  "toChainId": 421614,
  "toToken": "0x0000000000000000000000000000000000000000",
  "recipients": ["0x2F4edA5e7EEa6eb634C7FBb0acAFA04b8938F63A"],
  "toAmounts": ["5000000000000000000"]
}
```

| Field | Type | Description |
| --- | --- | --- |
| `chainId` | integer | FROM (mainnet) chain id. Must be an enabled FROM chain — an EVM id, or `1399811149` (Solana) / `1667471768` (TON). |
| `fromToken` | string | FROM token as listed in `/api/chains`: an `0x…` ERC-20 address, a base58 SPL mint on Solana, or `0x0…0` for the native coin on any chain. |
| `sender` | string | The wallet that will send the payment. Bound into the signature — the payer **must** match. EVM `0x…` (any case), Solana base58, TON any form. |
| `toChainId` | integer | TO (testnet) chain id. Must be an enabled TO chain. |
| `toToken` | address | TO token as listed in `/api/chains`. `0x0…0` = native (also for Solana / TON / Bitcoin testnets). |
| `recipients` | string[] | Recipient addresses on the TO chain. 1 = single swap; >1 = multisend. Up to 10 000. |
| `toAmounts` | string[] | Base-unit **integer strings** of the TO token, one per recipient (same length as `recipients`). No decimals/hex/exponents. |

**Rules**

- `recipients` and `toAmounts` must be non-empty and the same length.
- Recipients are validated per the TO chain: EVM addresses in any case; TON, Solana and Bitcoin
  addresses are checked and delivered **exactly as sent**.
- The payment must come from `sender` — a different paying wallet is not honoured.
- Each `toAmounts[i]` must sit on the TO token's precision grid and be at or above its per-recipient
  minimum (see error codes below).

## Response `200`

**Response**
```json
{
  "quoteId":     "0x1f5215a4577ef4548b550313d772594473e237c67514943751634818fdff9615",
  "signer":      "0x5C0917e114e49F3Cf266D6467ac129FEe42d77c5",
  "vault":       "0x52361c9412dcec6a83980fb065d0276ec001face",
  "issuedAt":    1784120925,
  "expiry":      1784121105,
  "deadline":    1784121105,
  "fromToken":   "0x0000000000000000000000000000000000000000",
  "fromTotal":   "517554316856097",
  "fromAmounts": ["517554316856097"],
  "toAmounts":   ["5000000000000000000"],
  "usdTotal":    "1.25",
  "signature":   "0x23fbc0…1b"
}
```

| Field | Meaning |
| --- | --- |
| `quoteId` | 32 random bytes — the only quote reference carried on-chain. Pass to the `pay` call, or put in the Solana memo / TON comment. |
| `signer` | Address that produced the EIP-712 signature (verify against it). |
| `vault` | Pay target = the FROM chain's `contracts.depository`, in canonical form: the depository contract (EVM) or the treasury account (Solana base58, TON `UQ…`). |
| `issuedAt` / `expiry` | Quote validity window (epoch s). |
| `deadline` | Passed to the `pay` call; the tx reverts `Expired` after it. On Solana / TON a payment landing after it is not honoured. Equals `expiry`. |
| `fromToken` | The FROM token in canonical form. |
| `fromTotal` | **Total FROM to pay**, base units. `msg.value` (native) or `amount` (ERC-20) on EVM; lamports / SPL units / nanotons on Solana / TON. Pay **exactly** this. |
| `fromAmounts` | Per-recipient FROM breakdown, base units (the backend expands the batch by these). |
| `toAmounts` | Echoes the requested TO amounts. Delivered exactly, regardless of later price moves. |
| `usdTotal` | Human USD total, 2 decimals. |
| `signature` | 65-byte EIP-712 signature. Optional to check — see [Verifying the quote signature](https://docs.drip.tools/swap/contract.md#verifying-the-quote-signature-optional). |

## Pricing model

You specify the **TO** amounts; the API computes the **FROM** cost using the live FROM-token price
(Chainlink, see [Prices](https://docs.drip.tools/api/prices.md)) and the TO token's USD rate
([`GET /api/quotes`](https://docs.drip.tools/api/discovery.md#get-api-quotes-rates-liquidity)):

**Formula**
```txt
fromAmount_i = floor( toAmount_i × toRateUsd × 10^fromDecimals / (10^toDecimals × fromPriceUsd) )
fromTotal    = Σ fromAmount_i
```

The quote **locks** `toAmounts` — the backend delivers exactly those, even if prices move between
quoting and payment.

**What you pay** is the listed rate of the testnet tokens converted at the live price of the token
you pay with — nothing more. There is no additional fee or spread. Gas on the FROM chain is yours;
gas for the testnet payouts is ours. Requesting a quote is free and commits you to nothing.

## Minimums

| Order | Minimum USD value |
| --- | --- |
| Single recipient | **$1** |
| Multisend (>1 recipient) | **$5** |

Compared at cent precision (round half up), so a feed wobble like $4.9998 → $5.00 is not rejected.

## Validity window

A quote expires **180 seconds** after issue, on every chain.
Submit the on-chain payment before `deadline`, or request a fresh quote.

## Errors

All errors are `{ "error": "<message>", "code": "<CODE>" }`, except the rate-limit and
warming-up shapes, which carry `retryAfterSec` and a `Retry-After` header instead of `code`.

| | Codes |
| --- | --- |
| Your request | `BAD_FROM_CHAIN` · `BAD_TO_CHAIN` · `BAD_ADDRESS` · `BAD_FROM_TOKEN` · `BAD_TO_TOKEN` · `BAD_ARRAYS` · `EMPTY` · `LENGTH_MISMATCH` · `TOO_MANY` · `BAD_RECIPIENT` · `BAD_TO_AMOUNT` (all `400`) |
| Your amounts | `TO_TOO_SMALL` · `TO_TOO_PRECISE` · `FROM_ROUNDS_TO_ZERO` · `BELOW_SOL_RENT_MIN` · `BELOW_MIN_TOTAL` · `NO_LIQUIDITY` (all `400`) |
| Availability | `NO_FROM_PRICE` · `NO_TO_PRICE` · `SIGNING_DISABLED` · `WARMING_UP` (`503`) · `NO_VAULT` (`500`) |
| Rate limit | `RATE_LIMITED` (`429`, with `Retry-After`) |

Every code with its meaning and fix: [Errors → POST /api/quote](https://docs.drip.tools/reference/errors.md#post-api-quote).

Once you have a quote, [pay on-chain](https://docs.drip.tools/swap/flow.md#step-3-pay-on-chain) and then
[track the order](https://docs.drip.tools/api/orders.md).
