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

# Getting prices

> Where a bot gets a signed quote, what the request looks like, how the program verifies it, and how public use is limited.

Quotes come from **`https://prices.rekt.trading`**. There is no other address. Use TLS everywhere.
The stream is `wss://prices.rekt.trading/v1/stream`.

Only the instructions that read a price need a quote: `settle`, `stamp_book`, `set_take_profit` and
`prove_price`. An open, an add and a close request carry none.

The price service quotes the markets of feed kind 2. A market of feed kind 3 (`isKind3Market(market)`)
is priced by a signed tick that the venue's fillers and keepers attach, and a quote from this service
does not price it: a client of that market opens, adds and requests closes, and needs no price at all. Read
`market.feedKind[0]` on every request: a market's kind can change.

A quote from the service is 80 bytes, signed by several keys. The service signs payload version 1 (the default) or
version 2: ask for version 2 with `payload_version: 2`. **The Knockout program verifies the signatures
on chain**, and refuses a quote that fails any check on [Quotes and freshness](https://docs.rekt.money/sdk/quotes.md). Nothing
the service returns outside the signed bytes is authoritative.

| Endpoint | Purpose |
| - | - |
| `GET /v1/feeds` | The feeds the price service signs, its signer keys, and each feed's `feed_id`. A feed is not a market: the list can carry a feed whose market is not open to trade or is not of feed kind 2. The open markets are on [markets](https://docs.rekt.money/markets.md) |
| `POST /v1/quote` | A signed quote for one feed |
| `GET /v1/stream` | WebSocket: signed quotes as they are produced |
| `GET /v1/readiness` | Whether each feed can be quoted right now, and its market session |
| `GET /v1/health` | Whether the service process is alive |

## The loop

1. **Once, at start-up.** `GET /v1/feeds`. Take the feeds of the markets you trade. A market's feed
   is `market.feeds[0]`; it equals the `feed_id` listed for that symbol. Pin it.
2. **When you are about to act.** `POST /v1/quote`, or hold a stream open and keep the latest frame.
3. **Judge it.** `benchmarkQuoteView` turns a quote into the view the [gates](https://docs.rekt.money/sdk/gates.md) judge:
   `priceGates` applies the program's own admission rule before you spend a fee.
4. **Send it.** `submitBenchmarkQuoted` places the quote's ed25519 instruction immediately before
   yours in the same transaction and sends it. See [Settling a position](https://docs.rekt.money/sdk/settling.md#send-it-with-its-quote).
5. **On a refusal, read the status.** `409` and `429` are retryable after `retry_after_ms`. Every
   other `4xx`, such as `400`, is not: fix the request.

```sh theme={"dark"}
curl -s https://prices.rekt.trading/v1/feeds

curl -s https://prices.rekt.trading/v1/quote \
  -H 'content-type: application/json' \
  -d '{"feed":"SOL/USD","payload_version":2,"idempotency_key":"'"$(openssl rand -hex 16)"'"}'
```

The response carries `payload` (the signed bytes, hex), `signatures`, `ed25519_instruction_data`
(the complete instruction, ready to place before yours) and `decoded`, a mirror for reading. Decide on
the bytes, not on `decoded`.

## Rules that matter

* **A quote ages out.** The program judges its age at execution, against `market.maxOracleAgeSlots`.
  Fetch a new quote for every attempt, with a new `idempotency_key`. Reuse a key only for an immediate
  retry after a transport failure.
* **A window quote is the first quote at or after a slot.** Ask for it with `min_slot` and
  `payload_version: 2`. Every caller who asks for the same slot gets the same bytes.
* **A failure is never a price.** A refusal has a status, a reason and a retry hint.
* **A market with trading hours says so inside the signature.** A closed session signs no price. See
  [Markets](https://docs.rekt.money/markets.md).
* **Call the service from a server, not from a browser.** It sends no CORS headers, so a browser
  cannot call it. Keep a token out of URLs. If you have one, send it as
  `Authorization: Bearer <token>`.

## Limits

Public use needs no sign-up and is rate limited per client address, so clients behind one address
share a limit. A limited request gets `429` with `retry_after_ms` and a `Retry-After` header. A
limit says nothing about whether a feed is healthy.

* Use the stream rather than polling for the latest price.
* Fetch `GET /v1/feeds` at start-up, not per request.
* Back off with jitter on `429` and `503`, and honour `retry_after_ms`.
* Keep one stream connection per process.

**For higher limits, write to [support@asymmetra.xyz](mailto:support@asymmetra.xyz).**

These pages describe the interface. They do not describe how prices are produced.


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