# API concepts > How the Doxa public market data API works. Authentication, rate limits, errors, pagination, ids and price units. Doxa has a small public API for reading market data: events, markets, order books and search. It is **read-only** and in **beta**. This page covers what applies to every endpoint. The [API reference](/api-reference/) lists each endpoint with its parameters, example requests and example responses. ## Base URL ```text https://doxa.pro ``` Every endpoint is a `GET` request under `/api/`, for example `https://doxa.pro/api/events`. ## Authentication None. The public endpoints need no account, key or token. Send a plain HTTPS request. ```bash curl "https://doxa.pro/api/events?limit=5" ``` ## Rate limits Requests without a signed-in session are limited per IP address. The limit is currently **300 requests per 60 seconds**. It may change. Responses carry `RateLimit` and `RateLimit-Policy` headers that show your remaining budget. When you go over the limit, the API answers `429 Too Many Requests`: ```json { "message": "Too many requests, please try again later" } ``` Wait for the number of seconds in the `Retry-After` header before you try again. Do not retry in a tight loop. ## Errors Errors use the usual HTTP status codes. The body is JSON with a human-readable `message`. | Status | Meaning | | --- | --- | | `400` | A query parameter is invalid. Event and market lists add an `errors` object keyed by parameter name. Search adds a `details` object. | | `404` | The event, market or order book was not found. | | `429` | Rate limit reached. See above. | | `451` | The service is not available in your region. See the [Terms](https://doxa.pro/terms). | | `500` | Something went wrong on our side. | | `503` | Temporarily unavailable. When a `Retry-After` header is present, wait that many seconds and retry. | Example `400`: ```json { "message": "Invalid query parameters", "errors": { "limit": ["Too big: expected number to be <=100"] } } ``` Treat `message` as text for people. Do not parse it, because the wording can change. ## Pagination List endpoints page with `limit` and `offset`. - **`GET /api/events`** returns `events` plus `total`, `offset`, `limit` and `hasMore`. Ask for the next page with `offset` increased by `limit` while `hasMore` is `true`. `total` may be an estimate. - **`GET /api/markets`** returns `markets` plus a `pagination` object with `total`, `limit`, `offset`, `hasMore` and `nextCursor`. For long walks, pass `paginate=keyset` on the first request, then pass each page's `nextCursor` back as `after_id`. A cursor stays stable while new markets are added. `nextCursor` is `null` on the last page and in plain offset mode. The allowed range for `limit` differs per endpoint. The reference lists it for each one. ## Ids Ids are opaque strings prefixed with the venue, in the form `:`. For example: - `polymarket:512345` - `kalshi:KXBTC-26DEC31-T100000` Use an id exactly as the API returned it. Do not build ids yourself or parse the part after the colon. A market's `id` is what `GET /api/orderbook/{marketId}` expects. A market's `eventKey` identifies the event it belongs to. ## Prices and amounts - **Market prices** (`yesPrice`, `noPrice`) are decimal strings from `0` to `1`. `"0.410000"` means 41ยข, about a 41% chance. - **Order book levels** use **cents from 0 to 100**. Each level is an array `[price, size, cumulative]`. `size` is the number of shares at that price and `cumulative` is the running total from the best price. - **Dollar amounts** such as liquidity and volume are decimal strings in US dollars. - **Times** are ISO 8601 strings in UTC. Read prices and amounts as decimals. Do not convert them to floating point if you need exact values. ## Versioning and stability The API is in beta. The current version is `0.1.0-beta`. - Endpoints, parameters and fields can change while the API is in beta. - Only the fields in the reference are documented. A response can contain other fields. Those are unstable and can change or disappear without notice, so do not depend on them. - Ignore fields you do not recognise. That way your code keeps working when fields are added. ## Caching Market data changes quickly. Event and market lists can be cached for up to 30 seconds (`Cache-Control: public, max-age=30`). Order books are never cached (`Cache-Control: no-store`). Poll no faster than you need, and stay within the rate limit.