# API Reference — Prices

Live USD prices of the FROM (mainnet) tokens, as the backend reads them from Chainlink, plus
the price history. `POST /api/quote` prices with the same feed, so these endpoints let you
**estimate** a swap before quoting and **audit** what the rate was when you paid.

Prices are raw feed answers: an integer string `price` with `priceDecimals` (8 for every feed
today). USD value = `price / 10^priceDecimals`.

## GET /api/prices

The latest price of every enabled FROM token, or a filtered subset.

**Query parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `chainId` | number | no | Only tokens of this FROM chain. |
| `address` | string | no | Only this token (`0x…`, base58 for an SPL mint, `0x0…0` for native). |

**cURL**
```bash
curl 'https://drip.tools/api/prices?chainId=8453'
```

**Response** — an array:

**Response**
```json
[
  {
    "chainId": 8453,
    "chainName": "Base",
    "symbol": "ETH",
    "address": "0x0000000000000000000000000000000000000000",
    "tokenDecimals": 18,
    "price": "241316450380",
    "priceDecimals": 8,
    "updatedAt": 1792324273,
    "observedAt": 1792324279,
    "available": true
  }
]
```

| Field | Meaning |
| --- | --- |
| `chainId` | FROM chain id, **as a number**. |
| `address` | Token address in canonical form (lowercased `0x…`, or a base58 mint). |
| `tokenDecimals` | The token's own decimals (for converting `fromTotal`). |
| `price` / `priceDecimals` | The feed's latest answer and its scale. USD = `price / 10^priceDecimals`. |
| `updatedAt` / `observedAt` | When the feed last updated, and when the backend read it (epoch s; refreshed about every minute). |
| `available` | `false` only for a token that has never been priced. A **stale** feed keeps `available: true` and its last price, with an old `updatedAt`; `POST /api/quote` refuses it with `NO_FROM_PRICE` once `updatedAt` is older than 26 hours — treat an old `updatedAt` the same way. A never-priced token has `price`, `priceDecimals`, `updatedAt` and `observedAt` as `null`. |

An unknown `chainId` or a token that isn't listed returns `[]`. A malformed `address` →
`400 Invalid address`. `503 WARMING_UP` while the first oracle pass after a restart is running.
Responses are cacheable for 5 s.

## GET /api/prices/at

The price the feed showed at a given moment — the latest feed round at or before `ts`. Use it to
reconcile an order's `from.amount` against the rate at payment time.

**Query parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `chainId` | number | yes | FROM chain id. |
| `address` | string | yes | Token address (`0x0…0` for native). |
| `ts` | number | yes | Epoch seconds. |

**cURL**
```bash
curl 'https://drip.tools/api/prices/at?chainId=1&address=0x0000000000000000000000000000000000000000&ts=1792318200'
```

**Response**

```json
{
  "chainId": 1,
  "address": "0x0000000000000000000000000000000000000000",
  "price": "242105416592",
  "priceDecimals": 8,
  "updatedAt": 1792318127,
  "observedAt": 1792318148
}
```

**Errors:** `400 chainId, address and ts are required`; `400 Invalid address`; `400 Invalid ts`;
`404 No price recorded at or before ts` (history starts when a token was listed). Responses are
cacheable for 60 s.

## How a quote uses these

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

`toRateUsd` is `price` from [`GET /api/quotes`](https://docs.drip.tools/api/discovery.md#get-api-quotes-rates-liquidity);
`fromPriceUsd` is `price / 10^priceDecimals` from this page. The quote locks `toAmounts`, so the
FROM side you pay is fixed at quote time — see [POST /api/quote](https://docs.drip.tools/api/quote.md#pricing-model).
