` | Requests that act for a wallet, such as creating, reading and removing its orders |
Each endpoint's page lists the credentials it needs under **Authorization**. [Log in](/api/how-tos/log-in) shows how to get a JWT for a wallet. For a Predict account, see [Authentication](/trading/authentication#with-a-predict-account).
On testnet, leave `x-api-key` out. Testnet doesn't need a key, but it rejects an invalid one.
## Requests [#requests]
Send request bodies as JSON, with `Content-Type: application/json`. Query and path parameters are listed on each endpoint's page.
Amounts and prices in orders are integer strings in wei, where `10^18` is 1 USDT or 1 share. For example, a price of 0.40 is `"400000000000000000"`. A decimal string such as `"0.4"` is rejected.
## Responses [#responses]
A successful response has `success: true`. Most endpoints put their result in `data`:
```json
{
"success": true,
"data": { "message": "Please sign this message to log in. …" }
}
```
A list adds a `cursor` for the next page (see [Pagination](#pagination)). A few endpoints, such as [Remove orders](/api/orders/remove-orders), return their fields next to `success` instead of in `data`. Each endpoint's page shows its response.
An error has `success: false`, the HTTP status in `code`, and a stable code in `error` to match on:
```json
{
"success": false,
"code": 401,
"error": "unauthorized",
"message": "invalid signature",
"timestamp": "2026-11-04T20:37:19.030930831Z"
}
```
[Errors](/resources/errors) lists every code with its fix.
### Units and timestamps [#units-and-timestamps]
- Share amounts in responses, such as a position's `amount` or an order's `amountFilled`, are wei strings, like the amounts you send.
- Order book prices and sizes are plain numbers, such as `[0.62, 1500]`: a price between 0 and 1 and a number of shares. See [Prices and order book](/concepts/order-book).
- Fee rates such as `feeRateBps` are in basis points, where 100 is 1%.
- Times in fields named `…At`, such as `createdAt`, are date-time strings. Fields named `…TimestampMs` are milliseconds since the Unix epoch.
## Pagination [#pagination]
List endpoints return one page at a time:
1. Set the page size with `first`. The table below gives each endpoint's default and maximum.
2. Read `cursor` from the response.
3. Send it back as `after` to get the next page.
When there are no more pages, `cursor` is `null`.
| Endpoints | Default `first` | Maximum `first` |
| :--- | :--- | :--- |
| `GET /v1/categories`, `GET /v1/markets`, `GET /v1/positions`, `GET /v1/positions/{address}`, `GET /v1/series/{slug}/rounds` | 20 | 100 |
| `GET /v1/orders`, `GET /v1/orders/matches`, `GET /v1/account/activity`, `GET /v1/account/{address}/activity`, `GET /v1/maker-rebates`, `GET /v1/referral-fees` | 50 | 150 |
A `first` outside that range isn't rejected. A larger value is read as the maximum, and a value below 1 is read as 1.
## Limits [#limits]
Each API key has a request budget per minute. A key can also have a per-second cap on order placement and removal. Responses carry `RateLimit-*` headers with your remaining budget, except when the API key is rejected. A request over the limit gets a `429`. See [Rate limits](/resources/rate-limits).
## Try it in the browser [#try-it-in-the-browser]
Every endpoint's page has a **Try in Playground** button that sends the request from your browser. It uses mainnet unless you pick the testnet server. Enter your API key, and a JWT for wallet endpoints, in its **Authorization** fields.
The OpenAPI document behind these pages is at [`/openapi/rest.json`](/openapi/rest.json). You can use it to generate a client.
## How-tos [#how-tos]
Get a JWT for a wallet, and send it with the wallet's requests.
Send a signed order, and read its status.
List a wallet's open orders, and remove them from the book.
For the SDK side of trading, such as order options, approvals and positions, see the [Trading guides](/trading/place-orders).
# Client example (/websocket/client-example)
A zero-dependency reference client for the Predict WebSocket API, with heartbeat handling, reconnect notices, reconnection with backoff, subscription tracking, and typed payloads.
```typescript
/**
* A zero-dependency client for the Predict WebSocket API.
* Designed to be used in the browser.
*/
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
function neOf(item: T): NonEmptyArray {
return [item] as NonEmptyArray;
}
function isNonEmpty(items: T[]): items is NonEmptyArray {
return items.length > 0;
}
/*
* Realtime Client
*/
export class RealtimeClient {
constructor(
private ws: WebSocket,
private readonly options: {
maxConnAttempts: number;
maxRetryInterval: number;
},
) {
this.bindAll();
}
/** Topic of each in-flight subscribe or unsubscribe request, cleared on its response. */
private topicSubReqIdMap: Map = new Map();
/** Active topics this connection is subscribed to. */
private subscriptions: Map> = new Map();
private connectionAttempts = 0;
private requestId = 0;
/** Set by close(), so the client doesn't reconnect after a close it asked for. */
private closedByUser = false;
/** Set by a reconnect notice, so the next connection opens at once. */
private reconnectNow = false;
private bindAll(): void {
this.ws.onerror = this.onError;
this.ws.onmessage = this.onMessage;
this.ws.onclose = this.onClose;
this.ws.onopen = this.onOpen;
}
private async reconnect() {
// a reconnect notice moves to a new connection at once, and isn't a failed attempt.
if (this.reconnectNow) {
this.reconnectNow = false;
return this.open();
}
const attempt = this.connectionAttempts++;
if (attempt < this.options.maxConnAttempts) {
// reconnect at once the first time. while reconnecting keeps failing, wait
// 1, 2, 4 and 8 seconds and so on, up to maxRetryInterval. up to half a
// second of jitter keeps clients from all reconnecting at the same moment.
const wait =
attempt === 0 ? 0 : Math.min(1000 * 2 ** (attempt - 1), this.options.maxRetryInterval);
await sleep(wait + Math.random() * 500);
this.open();
} else {
const allHandlers = Array.from(this.subscriptions.values()).flat();
for (const handler of allHandlers) {
handler({
err: { code: 'ws_disconnected', message: 'Max connection attempts reached' },
});
}
}
}
/** Opens a new connection to the same URL, unless close() was called. */
private open() {
if (this.closedByUser) return;
this.ws = new WebSocket(
this.ws.url,
this.ws.protocol !== '' ? this.ws.protocol : undefined,
);
this.bindAll();
}
private onOpen = () => {
this.connectionAttempts = 0;
// re-subscribe every active topic after a reconnect.
for (const topic of this.subscriptions.keys()) {
this.subUnsub('subscribe', topic);
}
};
private onClose = () => {
// reconnect after every close the client didn't ask for, clean or not. the
// server's own closes, such as 1001 when it shuts down, are clean ones.
if (!this.closedByUser) {
return this.reconnect();
}
};
private onMessage = (event: MessageEvent) => {
const parsed = JSON.parse(event.data as unknown as string) as Response;
if (parsed.type === 'M') {
const topic = parsed.topic;
if (topic === 'heartbeat') {
// echo the server timestamp back exactly.
this.send({ method: 'heartbeat', data: parsed.data });
} else if (parsed.topic === 'system') {
if (parsed.data.event === 'reconnect') {
// the server is shutting down, so move to a new connection right away.
this.reconnectNow = true;
this.ws.close();
}
} else {
const handlers = this.subscriptions.get(parsed.topic);
for (const handler of handlers || []) {
handler({ data: parsed.data });
}
}
} else if (parsed.type === 'R') {
const requestIdTopic = this.topicSubReqIdMap.get(parsed.requestId);
if (requestIdTopic) {
if (!parsed.success) {
const handlers = this.subscriptions.get(requestIdTopic);
if (handlers) {
for (const handler of handlers) {
handler({ err: parsed.error });
}
}
this.subscriptions.delete(requestIdTopic);
}
this.topicSubReqIdMap.delete(parsed.requestId);
} else {
console.warn(`Unknown response received`, JSON.stringify(parsed, null, 2));
}
}
};
private onError = (event: Event) => {
const allHandlers = Array.from(this.subscriptions.values()).flat();
for (const handler of allHandlers) {
handler({ err: { code: 'ws_error_terminated', message: 'Websocket error' } });
}
console.error('RealtimeClientSocketError', event);
};
private send(data: Requests) {
if (this.ws.readyState === this.ws.OPEN) {
if (data.method !== 'heartbeat') {
this.topicSubReqIdMap.set(data.requestId, data.params[0]);
}
return this.ws.send(JSON.stringify(data));
} else {
console.warn(`Not connected to WS. Ignoring.`);
}
}
private subUnsub(method: 'subscribe' | 'unsubscribe', topic: string) {
this.send({ requestId: this.requestId++, method, params: neOf(topic) });
}
private getTopicStringFor(channel: Channel): string {
switch (channel.name) {
case 'predictOrderbook':
return `predictOrderbook/${channel.marketId}`;
case 'predictTradingStatus':
return `predictTradingStatus/${channel.marketId}`;
case 'predictMarketStatus':
return `predictMarketStatus/${channel.marketId}`;
case 'predictMarketChanged':
return `predictMarketChanged/${channel.marketId}`;
case 'predictCategoryChanged':
return `predictCategoryChanged/${channel.categoryId}`;
case 'predictWalletEvents':
return `predictWalletEvents/${channel.jwt}`;
}
}
subscribe(channel: Channel, callback: EventCallback): { unsubscribe: () => void } {
const topicName = this.getTopicStringFor(channel);
const existing = this.subscriptions.get(topicName);
if (existing) {
existing.push(callback);
} else {
this.subscriptions.set(topicName, [callback]);
this.subUnsub('subscribe', topicName);
}
return {
unsubscribe: (): void => {
const item = this.subscriptions.get(topicName);
if (!item) {
throw new Error('InconsistentState: No subscriptions for this topic');
}
const cbRemoved = item.filter((x) => x !== callback);
if (isNonEmpty(cbRemoved)) {
this.subscriptions.set(topicName, cbRemoved);
} else {
this.subscriptions.delete(topicName);
this.subUnsub('unsubscribe', topicName);
}
},
};
}
close(): void {
this.closedByUser = true;
this.ws.close();
}
}
/*
* Types
*/
export type NonEmptyArray = [T, ...T[]];
export type Pretty = { [K in keyof T]: T[K] } extends infer U ? U : never;
/* Payloads */
export type MarketTradingStatusUpdate = {
kind: 'tradingStatusUpdate';
tsMs: number;
marketId: number;
tradingStatus: 'OPEN' | 'MATCHING_NOT_ENABLED' | 'CANCEL_ONLY' | 'CLOSED';
};
export type MarketStatusOutcomeEntry = {
label: string;
price: string;
indexSet: number;
onChainId?: string;
};
export type MarketStatusUpdatePayload = {
kind: 'marketStatusUpdate';
tsMs: number;
marketId: number;
status: string;
marketOutcomes?: MarketStatusOutcomeEntry[];
};
export type DepthLevel = [number, number];
export type OrderbookLastSettled = {
id: string;
price: string;
kind: string;
marketId: number;
side: 'Ask' | 'Bid';
outcome: 'Yes' | 'No';
};
export type PredictOrderbookUpdate = {
version: 1;
marketId: number;
updateTimestampMs: number;
orderCount: number;
asks: DepthLevel[];
bids: DepthLevel[];
lastOrderSettled: OrderbookLastSettled | null;
settlementsPending: { asks: DepthLevel[]; bids: DepthLevel[] };
};
export type MarketChangedUpdate = {
kind: 'marketChanged';
patchKind: string | null;
tsMs: number;
marketId: number;
patch?: Record;
};
export type CategoryChangedUpdate = {
kind: 'categoryChanged';
patchKind: string | null;
tsMs: number;
categoryId: number;
slug: string;
patch?: Record;
};
/** A change with no detail. Refetch the category. */
export type CategoryChangedNotice = {
categoryId: number;
tsMs: number;
};
export type SystemEvent = {
event: string;
reason: string;
graceMs: number;
};
/* Wallet events */
type BaseEvent = {
orderId: string;
orderHash: string;
timestamp: number;
walletAddress?: string;
details: {
marketId: number;
outcomeIndex: number;
marketQuestion: string;
outcome: 'YES' | 'NO';
outcomeName: string;
quoteType: 'ASK' | 'BID';
quantity: string;
quantityFilled: string;
price: string;
value: string;
valueFilled: string;
strategyType: 'MARKET' | 'LIMIT';
categorySlug: string;
};
};
type Fill = {
executedPriceWei: string;
executedSizeWei: string;
executedValueWei: string;
};
type OrderAccepted = BaseEvent & { type: 'orderAccepted' };
type OrderNotAccepted = BaseEvent & {
type: 'orderNotAccepted';
reason: 'noMarketMatch' | 'rejectedDuplicate' | 'rejectedPostOnly';
settlementId?: string | null;
};
type OrderMarketMatchPlan = BaseEvent & {
type: 'orderMarketMatchPlan';
amount: string;
amountFilled: string;
plannedFill: string;
remainderCancelled: string;
settlementIds: string[];
};
type OrderExpired = BaseEvent & { type: 'orderExpired' };
type OrderCancelled = BaseEvent & {
type: 'orderCancelled';
reason?: 'selfTradePrevention';
};
type OrderTransactionSubmitted = BaseEvent & {
type: 'orderTransactionSubmitted';
kind: 'SALE' | 'PURCHASE';
isMaker: boolean;
settlementId: string;
fill: Fill;
};
type OrderTransactionSuccess = BaseEvent & {
type: 'orderTransactionSuccess';
settlementId: string;
fill: Fill;
isMaker?: boolean;
fee?: { amountWei: string; type: 'COLLATERAL' | 'SHARES' };
};
type OrderTransactionFailed = BaseEvent & {
type: 'orderTransactionFailed';
settlementId: string;
fill: Fill;
};
export type PredictWalletEvents =
| OrderAccepted
| OrderNotAccepted
| OrderMarketMatchPlan
| OrderExpired
| OrderCancelled
| OrderTransactionSubmitted
| OrderTransactionSuccess
| OrderTransactionFailed;
/* Channels */
export interface PredictOrderbookChannel { name: 'predictOrderbook'; marketId: number }
export interface PredictTradingStatusChannel { name: 'predictTradingStatus'; marketId: number }
export interface PredictMarketStatusChannel { name: 'predictMarketStatus'; marketId: number }
export interface PredictMarketChangedChannel { name: 'predictMarketChanged'; marketId: number }
export interface PredictCategoryChangedChannel { name: 'predictCategoryChanged'; categoryId: number }
export interface PredictWalletEventsChannel { name: 'predictWalletEvents'; jwt: string }
export type Channel = Pretty<
| PredictOrderbookChannel
| PredictTradingStatusChannel
| PredictMarketStatusChannel
| PredictMarketChangedChannel
| PredictCategoryChangedChannel
| PredictWalletEventsChannel
>;
/* Requests */
type WithRequestId = T & { requestId: number };
export type SubscribeRequest = WithRequestId<{ method: 'subscribe'; params: NonEmptyArray }>;
export type UnsubscribeRequest = WithRequestId<{ method: 'unsubscribe'; params: NonEmptyArray }>;
export type HeartbeatRequest = { method: 'heartbeat'; data: unknown };
export type Requests = Pretty;
/* Errors */
type InvalidJson = { code: 'invalid_json'; message?: string };
export type InvalidTopic = { code: 'invalid_topic'; message?: string };
export type InvalidParams = { code: 'invalid_params'; message?: string };
export type InvalidCredentials = { code: 'invalid_credentials'; message?: string };
export type InternalServerError = { code: 'internal_server_error'; message?: string };
export type ResponseError = Pretty<
InvalidJson | InvalidTopic | InvalidParams | InvalidCredentials | InternalServerError
>;
/* Responses */
export type RequestResponse = {
type: 'R';
requestId: number;
} & ({ success: true } | { success: false; error: ResponseError });
export type MessageResponse = {
type: 'M';
topic: Topic;
data: Data;
};
export type MessageResponses =
| MessageResponse<'heartbeat', number>
| MessageResponse<`predictOrderbook${string}`, PredictOrderbookUpdate>
| MessageResponse<`predictTradingStatus${string}`, MarketTradingStatusUpdate>
| MessageResponse<`predictMarketStatus${string}`, MarketStatusUpdatePayload>
| MessageResponse<`predictMarketChanged${string}`, MarketChangedUpdate>
| MessageResponse<`predictCategoryChanged${string}`, CategoryChangedUpdate | CategoryChangedNotice>
| MessageResponse<`predictWalletEvents${string}`, PredictWalletEvents>;
export type Response = Pretty<
MessageResponses | MessageResponse<'system', SystemEvent> | RequestResponse
>;
/* Internal */
export type WSError =
| ResponseError
| { code: 'ws_disconnected'; message?: string }
| { code: 'ws_error_terminated'; message?: string };
export type TopicName = string;
export type EventCallback = (
arg: { err?: null; data: MessageResponses['data'] } | { err: WSError; data?: null },
) => void;
```
# Follow your orders (/websocket/how-tos/follow-your-orders)
The `predictWalletEvents/{jwt}` topic sends an event each time something happens to one of your wallet's orders. Use it to learn whether an order was accepted, when it matched, and when its trades settled on-chain.
## Subscribe with a JWT [#subscribe-with-a-jwt]
The topic holds a JWT for the wallet, from the REST API's [Log in](/api/how-tos/log-in) how-to:
```json
{ "method": "subscribe", "requestId": 1, "params": ["predictWalletEvents/eyJ0eXAiOiJKV1Qi…"] }
```
The server checks the JWT when you subscribe. An invalid or expired JWT gets an `invalid_credentials` error. A JWT is valid for 24 hours, so log in again before you subscribe on a new connection. Nothing is sent on subscribe: events start with the next thing that happens to an order.
## Events [#events]
Each event's `type` says what happened to the order, such as `orderAccepted`, `orderTransactionSuccess` or `orderCancelled`. [Order lifecycle](/trading/order-lifecycle#follow-your-orders-live) describes when you get each type, and the [wallet events topic](/websocket/topics/wallet-events) lists every field.
Every event has the order's `orderId` and `orderHash`, a `timestamp` in epoch milliseconds, and `details` with the `marketId`, the side (`quoteType`), the `outcome`, the `price`, the `quantity` and the `quantityFilled`.
## The whole example [#the-whole-example]
This subscribes with a JWT and prints a line for each event:
```typescript
// Print each event of a wallet's orders as it happens.
// Runs in browsers and in Node.js 22 or later, which have WebSocket built in.
const jwt = "YOUR_JWT"; // from the REST API's Log in how-to
const topic = `predictWalletEvents/${jwt}`;
// Browsers can't set headers on a WebSocket, so the key goes in the URL.
const ws = new WebSocket("wss://ws.predict.fun/ws?apiKey=YOUR_API_KEY");
ws.addEventListener("open", () => {
ws.send(
JSON.stringify({ method: "subscribe", requestId: 1, params: [topic] }),
);
});
ws.addEventListener("message", (event) => {
const message = JSON.parse(event.data);
if (message.type === "R" && !message.success) {
console.error(`Subscribe failed: ${message.error.message}`);
} else if (message.topic === "heartbeat") {
// Echo each heartbeat, or the server closes the connection.
ws.send(JSON.stringify({ method: "heartbeat", data: message.data }));
} else if (message.topic === topic) {
const { type, orderId, reason, details } = message.data;
const { quoteType, outcome, quantityFilled, quantity, price } = details;
console.log(
`${type} ${orderId}: ${quoteType} ${outcome} ` +
`${quantityFilled}/${quantity} at ${price}${reason ? ` (${reason})` : ""}`,
);
}
});
```
```python
# Print each event of a wallet's orders as it happens.
# Install: pip install websockets
import asyncio
import json
import websockets
API_KEY = "YOUR_API_KEY"
JWT = "YOUR_JWT" # from the REST API's Log in how-to
async def main():
topic = f"predictWalletEvents/{JWT}"
async with websockets.connect(
"wss://ws.predict.fun/ws", additional_headers={"x-api-key": API_KEY}
) as ws:
await ws.send(
json.dumps({"method": "subscribe", "requestId": 1, "params": [topic]})
)
async for raw in ws:
message = json.loads(raw)
if message.get("type") == "R" and not message["success"]:
print(f"Subscribe failed: {message['error']['message']}")
elif message.get("topic") == "heartbeat":
# Echo each heartbeat, or the server closes the connection.
reply = {"method": "heartbeat", "data": message["data"]}
await ws.send(json.dumps(reply))
elif message.get("topic") == topic:
event, details = message["data"], message["data"]["details"]
reason = f" ({event['reason']})" if event.get("reason") else ""
print(
f"{event['type']} {event['orderId']}: {details['quoteType']} "
f"{details['outcome']} {details['quantityFilled']}/"
f"{details['quantity']} at {details['price']}{reason}"
)
asyncio.run(main())
```
## After a reconnect [#after-a-reconnect]
Events sent while you were disconnected aren't replayed. After you reconnect:
1. Subscribe again, with a JWT that hasn't expired.
2. Fetch your open orders from [`GET /v1/orders?status=OPEN`](/api/orders/get-orders), following its `cursor` for more pages.
3. Treat that list as the current state, and apply new events on top of it.
[Stay connected](/websocket/how-tos/stay-connected) shows the reconnection itself.
# Stay connected (/websocket/how-tos/stay-connected)
A WebSocket connection can close for many reasons: a missed heartbeat, a server shutting down, a network change. A client that stays connected does three things: it answers heartbeats, it moves to a new connection when the server asks, and it reconnects with backoff after any other disconnect.
## Answer heartbeats [#answer-heartbeats]
Every 15 seconds the server sends a heartbeat with the current time. The first one arrives about 15 seconds after you connect:
```json
{ "type": "M", "topic": "heartbeat", "data": 1736696400000 }
```
Echo its `data` back before the next one:
```json
{ "method": "heartbeat", "data": 1736696400000 }
```
The echo has no `requestId` and gets no response. A missing, late or different value closes the connection with code `1000` at the next heartbeat.
## Handle reconnect notices [#handle-reconnect-notices]
Before a server shuts down, for example during a release, it sends a notice on the `system` topic:
```json
{
"type": "M",
"topic": "system",
"data": { "event": "reconnect", "reason": "server_shutdown", "graceMs": 7431 }
}
```
The connection keeps delivering for about `graceMs`, then closes with code `1001` and the reason `server draining`. Use that time to move to a new connection. The examples below reconnect right away. If you can't miss a single update, open the new connection and subscribe on it before you close the old one.
## Reconnect with backoff [#reconnect-with-backoff]
After any other disconnect, reconnect right away. If that fails, wait longer after each failed attempt, for example 1, 2, 4 and 8 seconds, then 10 seconds between tries, so you don't flood a server that is down. Add up to half a second of random jitter, so that many clients don't reconnect at the same moment. Reset the wait once a connection opens, so the next disconnect reconnects right away again.
A new connection starts with no subscriptions, and messages sent while you were away aren't replayed. So on every connection:
1. Subscribe to every topic you need.
2. Refetch from the REST API anything you track, such as your open orders or the market's status.
## The whole example [#the-whole-example]
This keeps a subscription running through heartbeats, reconnect notices and disconnects:
```typescript
// Keep subscriptions running: echo heartbeats, and reconnect after any
// disconnect, subscribing again each time.
// Runs in browsers and in Node.js 22 or later, which have WebSocket built in.
const url = "wss://ws.predict.fun/ws?apiKey=YOUR_API_KEY";
// MARKET_ID: a market ID, like the ones the Market data example prints.
const topics = ["predictOrderbook/MARKET_ID"];
let attempt = 0;
function connect() {
const ws = new WebSocket(url);
let reconnectNow = false;
ws.addEventListener("open", () => {
attempt = 0;
// A new connection has no subscriptions, so subscribe to every topic.
topics.forEach((topic, i) => {
ws.send(
JSON.stringify({
method: "subscribe",
requestId: i + 1,
params: [topic],
}),
);
});
// Updates sent while you were disconnected are not replayed. Refetch
// anything you track from the REST API here.
});
ws.addEventListener("message", (event) => {
const message = JSON.parse(event.data);
if (message.topic === "heartbeat") {
// Echo each heartbeat, or the server closes the connection.
ws.send(JSON.stringify({ method: "heartbeat", data: message.data }));
} else if (
message.topic === "system" &&
message.data.event === "reconnect"
) {
// The server is shutting down, so move to a new connection right away.
reconnectNow = true;
ws.close();
} else if (message.type === "R" && !message.success) {
console.error(
`Request ${message.requestId} failed: ${message.error.message}`,
);
} else if (message.type === "M") {
console.log(`Update on ${message.topic}`);
}
});
ws.addEventListener("close", (event) => {
let delay = 0;
if (!reconnectNow) {
// Reconnect at once the first time. While reconnecting keeps failing,
// wait 1, 2, 4 and 8 seconds, then 10 seconds between tries. Up to half a
// second of jitter keeps clients from all reconnecting at the same moment.
const wait =
attempt === 0 ? 0 : Math.min(1000 * 2 ** (attempt - 1), 10_000);
delay = wait + Math.random() * 500;
attempt++;
}
console.log(
`Closed (${event.code}). Reconnecting in ${Math.round(delay)} ms`,
);
setTimeout(connect, delay);
});
}
connect();
```
```python
# Keep subscriptions running: echo heartbeats, and reconnect after any
# disconnect, subscribing again each time.
# Install: pip install websockets
import asyncio
import json
import random
import websockets
API_KEY = "YOUR_API_KEY"
# MARKET_ID: a market ID, like the ones the Market data example prints.
TOPICS = ["predictOrderbook/MARKET_ID"]
async def main():
attempt = 0
while True:
reconnect_now = False
try:
async with websockets.connect(
"wss://ws.predict.fun/ws", additional_headers={"x-api-key": API_KEY}
) as ws:
attempt = 0
# A new connection has no subscriptions, so subscribe to every topic.
for request_id, topic in enumerate(TOPICS, start=1):
request = {"method": "subscribe", "requestId": request_id}
await ws.send(json.dumps({**request, "params": [topic]}))
# Updates sent while you were disconnected are not replayed.
# Refetch anything you track from the REST API here.
async for raw in ws:
message = json.loads(raw)
if message.get("topic") == "heartbeat":
# Echo each heartbeat, or the server closes the connection.
reply = {"method": "heartbeat", "data": message["data"]}
await ws.send(json.dumps(reply))
elif message.get("topic") == "system":
# The server is shutting down, so move to a new
# connection right away.
if message["data"].get("event") == "reconnect":
reconnect_now = True
break
elif message.get("type") == "R" and not message["success"]:
request_id, error = message["requestId"], message["error"]
print(f"Request {request_id} failed: {error['message']}")
elif message.get("type") == "M":
print(f"Update on {message['topic']}")
except (websockets.WebSocketException, OSError) as error:
print(f"Connection lost: {error}")
if not reconnect_now:
# Reconnect at once the first time. While reconnecting keeps
# failing, wait 1, 2, 4 and 8 seconds, then 10 seconds between
# tries. Up to half a second of jitter keeps clients from all
# reconnecting at the same moment.
wait = 0 if attempt == 0 else min(2 ** (attempt - 1), 10)
await asyncio.sleep(wait + random.random() / 2)
attempt += 1
asyncio.run(main())
```
For a complete client with typed messages and subscription tracking, see the [client example](/websocket/client-example).
# Stream an order book (/websocket/how-tos/stream-an-order-book)
The `predictOrderbook/{marketId}` topic sends a market's whole order book each time it changes. The latest book usually arrives right after you subscribe. When it doesn't, fetch it from [`GET /v1/markets/{id}/orderbook`](/api/markets/get-market-orderbook).
## Subscribe [#subscribe]
Send a subscribe request with the market's ID in the topic:
```json
{ "method": "subscribe", "requestId": 1, "params": ["predictOrderbook/123"] }
```
Each update is the whole book, so replace what you have instead of merging:
```json
{
"type": "M",
"topic": "predictOrderbook/123",
"data": {
"marketId": 123,
"updateTimestampMs": 1736696400000,
"asks": [[0.62, 1500], [0.63, 800]],
"bids": [[0.61, 2000], [0.6, 1200]]
}
}
```
`asks` and `bids` are `[price, shares]` levels, best price first. The [order book topic](/websocket/topics/order-book) lists every field, including the settlements that are still pending.
## The No side [#the-no-side]
The book is priced in Yes. The No side holds the same orders seen from the other side: a Yes bid at 0.61 is a No ask at 0.39. So the No book is the Yes book with its sides swapped, and each price replaced by its complement at the market's `decimalPrecision`. [Prices and order book](/concepts/order-book) explains why.
## The whole example [#the-whole-example]
This reads the market's precision from the REST API, subscribes to its order book, and prints both books on every update. It also echoes the server's heartbeats, which keeps the connection open.
```typescript
// Show a market's order book for both outcomes, Yes and No, as it changes.
// The API sends the Yes book. The No book holds the same orders seen from the
// other side: a Yes bid at 0.40 is a No ask at 0.60. So the sides swap, and each
// price becomes its complement.
// Runs in browsers and in Node.js 22 or later, which have WebSocket built in.
// Get an API key from the developer console: https://developers.predict.fun
const apiKey = "YOUR_API_KEY";
// a market ID, like the ones the Market data example prints.
const marketId = "MARKET_ID";
type Level = [price: number, shares: number];
// Prices have the market's decimal precision, for example 2 for steps of 0.01.
const response = await fetch(`https://api.predict.fun/v1/markets/${marketId}`, {
headers: { "x-api-key": apiKey },
});
if (!response.ok) throw new Error(`Predict API error: ${response.status}`);
const { decimalPrecision } = (await response.json()).data;
// The No price of a Yes price. Rounding at the market's precision makes the two
// add up to exactly 1.
function complement(price: number): number {
const factor = 10 ** decimalPrecision;
return (factor - Math.round(price * factor)) / factor;
}
function cents(price: number): string {
return `${(price * 100).toFixed(Math.max(decimalPrecision - 2, 0))}¢`;
}
// Prints the 5 best levels of each side. The asks print highest first, so the
// best ask and the best bid meet at the spread.
function printBook(outcome: string, asks: Level[], bids: Level[]) {
const row = (side: string, [price, shares]: Level) =>
` ${side} ${cents(price).padStart(6)} ${shares.toFixed(2).padStart(10)}`;
console.log(`${outcome} price shares`);
for (const level of asks.slice(0, 5).reverse()) {
console.log(row("ask", level));
}
if (asks.length > 0 && bids.length > 0) {
console.log(` spread ${cents(asks[0][0] - bids[0][0])}`);
}
for (const level of bids.slice(0, 5)) {
console.log(row("bid", level));
}
}
// Browsers can't set headers on a WebSocket, so the key goes in the URL.
const ws = new WebSocket(`wss://ws.predict.fun/ws?apiKey=${apiKey}`);
const topic = `predictOrderbook/${marketId}`;
ws.addEventListener("open", () => {
ws.send(
JSON.stringify({ method: "subscribe", requestId: 1, params: [topic] }),
);
});
ws.addEventListener("message", (event) => {
const message = JSON.parse(event.data);
if (message.type === "R" && !message.success) {
console.error(`Subscribe failed: ${message.error.message}`);
} else if (message.topic === "heartbeat") {
// Echo each heartbeat, or the server closes the connection.
ws.send(JSON.stringify({ method: "heartbeat", data: message.data }));
} else if (message.topic === topic) {
const { asks, bids }: { asks: Level[]; bids: Level[] } = message.data;
const toNo = ([price, shares]: Level): Level => [complement(price), shares];
console.clear();
printBook("Yes", asks, bids);
// No asks come from the Yes bids, and No bids from the Yes asks.
printBook("No ", bids.map(toNo), asks.map(toNo));
}
});
ws.addEventListener("close", (event) => {
console.log(`Connection closed (${event.code})`);
});
```
```python
# Show a market's order book for both outcomes, Yes and No, as it changes.
# The API sends the Yes book. The No book holds the same orders seen from the
# other side: a Yes bid at 0.40 is a No ask at 0.60. So the sides swap, and each
# price becomes its complement.
# Install: pip install requests websockets
# Get an API key from the developer console: https://developers.predict.fun
import asyncio
import json
import requests
import websockets
API_KEY = "YOUR_API_KEY"
# a market ID, like the ones the Market data example prints.
MARKET_ID = "MARKET_ID"
# Prices have the market's decimal precision, for example 2 for steps of 0.01.
response = requests.get(
f"https://api.predict.fun/v1/markets/{MARKET_ID}",
headers={"x-api-key": API_KEY},
)
response.raise_for_status()
PRECISION = response.json()["data"]["decimalPrecision"]
def complement(price):
"""The No price of a Yes price. Rounding at the market's precision makes the
two add up to exactly 1."""
factor = 10**PRECISION
return (factor - round(price * factor)) / factor
def cents(price):
return f"{price * 100:.{max(PRECISION - 2, 0)}f}¢"
def print_book(outcome, asks, bids):
"""Prints the 5 best levels of each side. The asks print highest first, so
the best ask and the best bid meet at the spread."""
print(f"{outcome} price shares")
for price, shares in reversed(asks[:5]):
print(f" ask {cents(price):>6} {shares:>10.2f}")
if asks and bids:
print(f" spread {cents(asks[0][0] - bids[0][0])}")
for price, shares in bids[:5]:
print(f" bid {cents(price):>6} {shares:>10.2f}")
async def main():
topic = f"predictOrderbook/{MARKET_ID}"
async with websockets.connect(
"wss://ws.predict.fun/ws",
additional_headers={"x-api-key": API_KEY},
) as ws:
await ws.send(
json.dumps({"method": "subscribe", "requestId": 1, "params": [topic]})
)
async for raw in ws:
message = json.loads(raw)
if message.get("type") == "R" and not message["success"]:
print(f"Subscribe failed: {message['error']['message']}")
elif message.get("topic") == "heartbeat":
# Echo each heartbeat, or the server closes the connection.
reply = {"method": "heartbeat", "data": message["data"]}
await ws.send(json.dumps(reply))
elif message.get("topic") == topic:
asks, bids = message["data"]["asks"], message["data"]["bids"]
print("\033[2J\033[H", end="") # clears the terminal
print_book("Yes", asks, bids)
# No asks come from the Yes bids, and No bids from the Yes asks.
no_asks = [(complement(price), shares) for price, shares in bids]
no_bids = [(complement(price), shares) for price, shares in asks]
print_book("No ", no_asks, no_bids)
asyncio.run(main())
```
To keep the stream running through disconnects, add the reconnection from [Stay connected](/websocket/how-tos/stay-connected).
# Overview (/websocket)
The WebSocket API streams live market data and the events of your own orders over one connection. You connect once, subscribe to the topics you need, and the server pushes each topic's messages as they happen.
## Connect [#connect]
| Network | URL |
| :--- | :--- |
| BNB Mainnet | `wss://ws.predict.fun/ws` |
| BNB Testnet | Not available yet |
Connections are served only on the `/ws` path, over TLS.
Send your API key when you connect, in one of two ways:
- The `x-api-key` header, which is preferred.
- The `apiKey` query parameter, for clients that can't set headers, such as browsers: `wss://ws.predict.fun/ws?apiKey=YOUR_API_KEY`.
The key is checked once, at the handshake. A handshake that fails gets an HTTP status instead of a connection, such as `401` for an invalid key or `503` while the service is unavailable.
## Messages [#messages]
Every message is a JSON text frame. Field names and values are case-sensitive, and timestamps are milliseconds since the Unix epoch.
You send **requests**, with a `method`, a `requestId` of your choice and the request's `params`:
```json
{ "method": "subscribe", "requestId": 1, "params": ["predictOrderbook/123"] }
```
The server answers each request with a **response** (`type: "R"`) that carries the same `requestId`:
```json
{ "type": "R", "requestId": 1, "success": true }
```
Everything else the server sends is a **topic message** (`type: "M"`), with the `topic` it belongs to and its `data`:
```json
{ "type": "M", "topic": "predictOrderbook/123", "data": { "marketId": 123, "asks": [[0.62, 1500]], "bids": [[0.61, 2000]] } }
```
The requests are [Subscribe](/websocket/requests/subscribe), [Unsubscribe](/websocket/requests/unsubscribe) and [Set language](/websocket/requests/set-language). Each subscribe or unsubscribe names one topic.
### Errors [#errors]
A request that fails gets a response with `success: false` and an `error`:
```json
{
"type": "R",
"requestId": 1,
"success": false,
"error": { "code": "invalid_topic", "message": "unknown topic: predictOrderbok" }
}
```
| `error.code` | Cause |
| :--- | :--- |
| `invalid_json` | The frame isn't a valid request, for example its `requestId` or `params` is missing. The response's `requestId` is `-1`. |
| `invalid_topic` | The topic is missing or unknown, or one of its parameters is invalid. |
| `invalid_params` | A [Set language](/websocket/requests/set-language) request has no language code. |
| `invalid_credentials` | The JWT in a wallet events topic is invalid, revoked or expired. |
| `internal_server_error` | Something failed on our side. Try again. |
## Topics [#topics]
| Topic | What it sends | Latest value on subscribe |
| :--- | :--- | :--- |
| [`predictOrderbook/{marketId}`](/websocket/topics/order-book) | The market's whole order book, each time it changes. | Yes |
| [`predictTopOfBook/{marketId}`](/websocket/topics/top-of-book) | The market's best bid and best ask, each time either changes. | Yes |
| [`predictTradingStatus/{marketId}`](/websocket/topics/trading-status) | Changes to the market's `tradingStatus`. | Yes |
| [`predictMarketStatus/{marketId}`](/websocket/topics/market-status) | Changes to the market's `status`, such as resolution. | Yes |
| [`predictMarketChanged/{marketId}`](/websocket/topics/market-changed) | A notice that the market's details changed. | No |
| [`predictCategoryChanged/{categoryId}`](/websocket/topics/category-changed) | A notice that the category's details changed. | No |
| [`predictWalletEvents/{jwt}`](/websocket/topics/wallet-events) | The events of your wallet's orders. The topic holds a JWT from the REST API. | No |
For the topics marked Yes, the latest value arrives right after the subscribe response, followed by live updates. It's best effort: when there's nothing to send yet, only updates arrive.
## Keep the connection open [#keep-the-connection-open]
- **Heartbeats.** Every 15 seconds the server sends a `heartbeat` message. Echo its `data` back before the next one, or the server closes the connection.
- **Reconnect notices.** Before a server shuts down, it sends a reconnect notice on the `system` topic, then closes the connection after `graceMs`.
- **Message size.** A frame from the client can be at most 8 KiB. A larger one closes the connection.
- **Keeping up.** Read messages as fast as they arrive. The server disconnects a client that falls too far behind.
| Close code | Why the server closed the connection |
| :--- | :--- |
| `1000` | A heartbeat went unanswered, or a message from the client was over 8 KiB once decompressed. |
| `1001` | The server is shutting down, after a reconnect notice. The reason is `server draining`. |
| `1009` | A frame from the client was over 8 KiB. |
| None | The client fell behind, or the server dropped its connections after a gap in delivery. The server sends no close frame, so browsers report `1006`. |
Reconnect after every close you didn't start. Subscriptions don't carry over to a new connection, and messages sent while you were disconnected aren't replayed. After you reconnect, subscribe again and refetch what you track from the REST API. [Stay connected](/websocket/how-tos/stay-connected) shows how.
## How-tos [#how-tos]
Show a market's Yes and No order book as it changes.
Get the events of your wallet's orders as they happen.
Answer heartbeats, and reconnect after a disconnect.
The [client example](/websocket/client-example) is a complete TypeScript client with heartbeats, reconnection and typed messages.
The AsyncAPI document behind these pages is at [`/asyncapi/websocket.json`](/asyncapi/websocket.json). You can use it to generate a client.
# Get auth message (/api/auth/get-auth-message)
`GET https://api.predict.fun/v1/auth/message`
Get the message to sign to generate a JWT token.
Do not hardcode this message as it is dynamic and can be subject to changes.
```yaml
paths:
/auth/message:
get:
tags:
- Auth
summary: Get auth message
description: >-
Get the message to sign to generate a JWT token.
Do not hardcode this message as it is dynamic and can be subject to
changes.
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/AuthMessageResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
AuthMessageData:
type: object
title: AuthMessageData
description: Authentication message data
required:
- message
properties:
message:
type: string
description: The message to sign with your wallet
AuthMessageResponse:
type: object
title: AuthMessageResponse
description: Response for GET /v1/auth/message
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/AuthMessageData"
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
```
# Get JWT with valid signature (/api/auth/get-jwt-with-valid-signature)
`POST https://api.predict.fun/v1/auth`
Provide a signature and get back a valid JWT that allows order actions.
```yaml
paths:
/auth:
post:
tags:
- Auth
summary: Get JWT with valid signature
description: Provide a signature and get back a valid JWT that allows order actions.
requestBody:
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/PostAuthRequest"
required: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/AuthTokenResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
AuthTokenData:
type: object
title: AuthTokenData
description: Authentication token data
required:
- token
properties:
token:
type: string
description: JWT token for authenticated requests
AuthTokenResponse:
type: object
title: AuthTokenResponse
description: Response for POST /v1/auth
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/AuthTokenData"
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
PostAuthRequest:
type: object
title: PostAuthRequest
description: Request body for POST /v1/auth
required:
- signer
- signature
- message
properties:
signer:
type: string
description: The wallet address (checksummed)
signature:
type: string
description: The signature of the message
maxLength: 200
message:
type: string
description: The signed message (from GET /v1/auth/message)
maxLength: 2048
```
# Get categories (/api/categories/get-categories)
`GET https://api.predict.fun/v1/categories`
Get categories information and their markets.
Markets within RESOLVED categories are not tradable.
```yaml
paths:
/categories:
get:
tags:
- Categories
summary: Get categories
description: |-
Get categories information and their markets.
Markets within RESOLVED categories are not tradable.
parameters:
- name: first
schema:
type: integer
format: int32
in: query
description: Page size, from 1 to 100. Defaults to 20. A value outside that
range is clamped.
required: false
deprecated: false
explode: true
- name: after
schema:
type: string
maxLength: 1024
in: query
description: The `cursor` from the previous page, to get the next one.
required: false
deprecated: false
explode: true
- name: status
schema:
$ref: "#/components/schemas/CategoryStatusFilter"
in: query
description: >-
`RESOLVED` returns only resolved categories, and any other value
only unresolved
ones. Omit it to get both.
required: false
deprecated: false
explode: true
- name: sort
schema:
$ref: "#/components/schemas/CategorySort"
in: query
description: >-
Defaults to `PUBLISHED_AT_DESC`, most recently published first.
`POPULAR` sorts like
`VOLUME_24H_DESC`, and `VOLUME` like `VOLUME_ALL_DESC`.
required: false
deprecated: false
explode: true
- name: tagIds
schema:
type: string
in: query
description: >-
Only categories with at least one of these tag IDs, comma-separated.
Entries that
are not numbers are ignored.
required: false
deprecated: false
explode: true
- name: marketVariant
schema:
$ref: "#/components/schemas/MarketVariant"
in: query
description: Only categories of this variant. Cannot be combined with
`marketVariants`.
required: false
deprecated: false
explode: true
- name: marketVariants
schema:
type: array
items:
$ref: "#/components/schemas/MarketVariant"
in: query
description: |-
Only categories of any of these variants (comma-separated or
repeated). Cannot be combined with `marketVariant`.
required: false
deprecated: false
explode: true
- name: includeStats
schema:
type: boolean
in: query
description: >-
Whether to fill in `stats` with volume and liquidity figures.
Defaults to `false`,
which leaves `stats` null.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/CategoriesResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
CategoriesResponse:
type: object
title: CategoriesResponse
description: Response for GET /v1/categories
required:
- success
- data
properties:
success:
type: boolean
cursor:
type: string
data:
type: array
items:
$ref: "#/components/schemas/CategoryWithStats"
CategorySort:
type: string
description: Category sort options
enum:
- POPULAR
- VOLUME
- VOLUME_24H_DESC
- VOLUME_ALL_DESC
- PUBLISHED_AT_ASC
- PUBLISHED_AT_DESC
CategoryStatsData:
type: object
title: CategoryStatsData
description: Category statistics data
required:
- totalLiquidityUsd
- volumeTotalUsd
- volume24hUsd
- holdersCount
properties:
totalLiquidityUsd:
type: number
format: double
volumeTotalUsd:
type: number
format: double
volume24hUsd:
type: number
format: double
holdersCount:
type: integer
format: int64
CategoryStatus:
type: string
description: Category status
enum:
- OPEN
- RESOLVED
- REMOVED
CategoryStatusFilter:
type: string
description: Category status filter for queries
enum:
- OPEN
- ACTIVE
- RESOLVED
- REMOVED
CategoryVariantDetails:
type: object
title: CategoryVariantDetails
description: |-
What a category is about, one key per kind of category.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for a sports category.
allOf:
- $ref: "#/components/schemas/SportsCategoryDetails"
- description: Set for a sports category.
crypto:
description: >-
Set for a crypto up down category.
Superseded by `up_down`, which says the same thing for every asset
class. Both are populated for crypto so existing readers keep
working.
allOf:
- $ref: "#/components/schemas/UpDownCategoryDetails"
- description: >-
Set for a crypto up down category.
Superseded by `up_down`, which says the same thing for every
asset
class. Both are populated for crypto so existing readers keep
working.
upDown:
description: Set for an up down price category, whatever the asset class.
allOf:
- $ref: "#/components/schemas/UpDownCategoryDetails"
- description: Set for an up down price category, whatever the asset class.
tweet:
description: Set for a tweet count category.
allOf:
- $ref: "#/components/schemas/TweetCategoryDetails"
- description: Set for a tweet count category.
CategoryWithStats:
type: object
title: CategoryWithStats
description: Category data with optional inline statistics.
required:
- id
- slug
- title
- description
- imageUrl
- isNegRisk
- protocol
- isYieldBearing
- marketVariant
- createdAt
- publishedAt
- markets
- startsAt
- status
- isVisible
- resolutionProvider
- tags
properties:
id:
type: integer
format: int64
slug:
type: string
title:
type: string
shortTitle:
type: string
description: Short, human-readable label, e.g. `"BTC Up or Down 15m"`. `null`
when not available.
seriesSlug:
type: string
description: >-
Slug of the recurring series this category is a round of, e.g.
`"btc-updown-5m"`. Absent when it is not a round of one. The series
and
its next rounds are at `GET /v1/series/{slug}`.
description:
type: string
imageUrl:
type: string
isNegRisk:
type: boolean
protocol:
$ref: "#/components/schemas/Protocol"
isYieldBearing:
type: boolean
negRiskOnChainId:
type: string
description: On-chain NegRisk market ID as a 32-byte hex string.
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this category is about, replacing `variantData`.
allOf:
- $ref: "#/components/schemas/CategoryVariantDetails"
- description: What this category is about, replacing `variantData`.
createdAt:
type: string
publishedAt:
type: string
markets:
type: array
items:
$ref: "#/components/schemas/Market"
startsAt:
type: string
endsAt:
type: string
tradingSession:
description: >-
Exchange session containing this Up/Down round's entire `startsAt`
to `endsAt` window.
Session times can differ from the round's times and remain available
after closing.
Returns `null` when no applicable session covers the complete round.
Use each market's `tradingStatus` for its current trading status.
allOf:
- $ref: "#/components/schemas/TradingSession"
- description: >-
Exchange session containing this Up/Down round's entire
`startsAt` to `endsAt` window.
Session times can differ from the round's times and remain
available after closing.
Returns `null` when no applicable session covers the complete
round.
Use each market's `tradingStatus` for its current trading
status.
status:
$ref: "#/components/schemas/CategoryStatus"
isVisible:
type: boolean
resolutionProvider:
$ref: "#/components/schemas/ResolutionProvider"
tags:
type: array
items:
$ref: "#/components/schemas/Tag"
teams:
type: array
description: |-
Deprecated in favour of `variantDetails.sports.teams`. The teams
playing, where the category is a fixture.
items:
$ref: "#/components/schemas/Team"
deprecated: true
parentSlug:
type: string
description: The slug of the parent category, when this is a prop/child market.
stats:
$ref: "#/components/schemas/CategoryStatsData"
CryptoUpDownVariantData:
type: object
title: CryptoUpDownVariantData
description: Variant data for CRYPTO_UP_DOWN markets
required:
- priceFeedProvider
properties:
priceFeedProvider:
$ref: "#/components/schemas/PriceFeedProvider"
startPrice:
type: number
format: double
description: Starting price, null before market start
endPrice:
type: number
format: double
description: Ending price from Pyth oracle, null if not yet resolved
priceFeedId:
type: string
description: Pyth oracle price feed identifier
priceFeedSymbol:
type: string
description: Price feed symbol (e.g. "BTCUSDT" for Binance, "BTC_USD" for Pyth)
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
EsportsVariantData:
type: object
title: EsportsVariantData
description: Variant data for esports match categories sourced from Grid.gg.
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked series yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
Market:
type: object
title: Market
description: Full market data as returned by the API
required:
- id
- imageUrl
- title
- question
- description
- tradingStatus
- status
- isVisible
- isNegRisk
- isYieldBearing
- feeRateBps
- makerFeeBps
- oracleQuestionId
- conditionId
- resolverAddress
- outcomes
- spreadThreshold
- shareThreshold
- isBoosted
- polymarketConditionIds
- categorySlug
- createdAt
- decimalPrecision
- marketVariant
- rewards
properties:
id:
type: integer
format: int64
imageUrl:
type: string
title:
type: string
question:
type: string
description:
type: string
tradingStatus:
$ref: "#/components/schemas/MarketTradingStatus"
status:
$ref: "#/components/schemas/MarketStatus"
isVisible:
type: boolean
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
feeRateBps:
type: integer
format: int32
description: Taker fee in basis points, charged on each matched trade.
makerFeeBps:
type: integer
format: int32
description: |-
Maker fee in basis points. Always `0`: no market charges makers.
Defaults on decode so market entries cached before the field existed
still decode rather than reading as misses, and the default is the
only value it takes.
resolution:
$ref: "#/components/schemas/Outcome"
oracleQuestionId:
type: string
conditionId:
type: string
resolverAddress:
type: string
outcomes:
type: array
items:
$ref: "#/components/schemas/Outcome"
questionIndex:
type: integer
format: int32
spreadThreshold:
type: number
format: double
shareThreshold:
type: integer
format: int32
isBoosted:
type: boolean
boostStartsAt:
type: string
boostEndsAt:
type: string
polymarketConditionIds:
type: array
items:
type: string
kalshiMarketTicker:
type: string
categorySlug:
type: string
seriesSlug:
type: string
description: |-
Slug of the recurring series this market's category is a round of,
e.g. `"btc-updown-5m"`. Absent when it is not a round of one. The
series and its next rounds are at `GET /v1/series/{slug}`.
createdAt:
type: string
decimalPrecision:
type: integer
format: int32
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
allOf:
- $ref: "#/components/schemas/MarketVariantDetails"
- description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
market as a whole is about a single team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
market as a whole is about a single team.
deprecated: true
marketType:
description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
allOf:
- $ref: "#/components/schemas/MarketType"
- description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
rewards:
$ref: "#/components/schemas/MarketRewards"
MarketRewards:
type: object
title: MarketRewards
description: Reward schedule for a market.
required:
- schedule
properties:
current:
description: Active period at request time, or `null` if no rewards are accruing.
allOf:
- $ref: "#/components/schemas/RewardPeriod"
- description: Active period at request time, or `null` if no rewards are
accruing.
schedule:
type: array
description: Full schedule of past and future reward periods for this market.
items:
$ref: "#/components/schemas/RewardPeriod"
MarketStatus:
type: string
description: |-
Market lifecycle state, from registration through resolution.
`Removed` is a synthetic status reported for markets that have been
withdrawn, meaning it is not part of the normal lifecycle progression.
enum:
- REGISTERED
- PRICE_PROPOSED
- PRICE_DISPUTED
- PAUSED
- UNPAUSED
- RESOLVED
- REMOVED
MarketTradingStatus:
type: string
description: Trading status derived from market visibility and deletion state.
enum:
- OPEN
- MATCHING_NOT_ENABLED
- CANCEL_ONLY
- CLOSED
MarketType:
type: string
description: >-
Market type (DB `market.market_type_id` values as repr).
Classifies what kind of prediction an individual market represents,
independent of the category it belongs to. Works alongside
[`MarketVariant`]:
the variant describes how the category container renders; the market
type
describes the prediction mechanic of the individual market.
enum:
- SPORTS_MONEYLINE
- SPORTS_SPREADS
- SPORTS_TOTALS
- SPORTS_BOTH_TEAMS_TO_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_EXACT_SCORE
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_TEAM_TOTAL_CORNERS
- SPORTS_CORNERS_ODD_EVEN
- SPORTS_PLAYER_GOALS
- SPORTS_PLAYER_ASSISTS
- SPORTS_PLAYER_GOALS_PLUS_ASSISTS
- SPORTS_PLAYER_SHOTS
- SPORTS_PLAYER_SHOTS_ON_TARGET
- SPORTS_PLAYER_GOALKEEPER_SAVES
- SPORTS_TEAM_TO_ADVANCE
- SPORTS_EXTRA_TIME
- SPORTS_PENALTY_SHOOTOUT
- SPORTS_TEAM_TOTALS
- SPORTS_CHILD_MONEYLINE
- SPORTS_MAP_HANDICAP
- SPORTS_BOTH_TEAMS_TO_SCORE_FIRST_HALF
- SPORTS_BOTH_TEAMS_TO_SCORE_SECOND_HALF
- SPORTS_FIRST_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- SPORTS_FIRST_CORNER
- SPORTS_FIRST_HALF_TOTALS
- SPORTS_SECOND_HALF_TOTALS
- SPORTS_FIRST_HALF_TEAM_TOTALS
- SPORTS_SECOND_HALF_TEAM_TOTALS
- SPORTS_FIRST_BLOOD_GAME
- SPORTS_KILL_OVER_UNDER_GAME
- SPORTS_ROUND_HANDICAP
- SPORTS_ROUND_TOTALS
- SPORTS_ANYTIME_TOUCHDOWNS
- SPORTS_RACE_TO_POINTS
- SPORTS_ODD_EVEN
MarketVariant:
type: string
description: |-
Classifies the market template type.
Controls the UI layout and trading mechanics of a category. See also
[`MarketType`] which classifies individual markets within a category.
enum:
- DEFAULT
- SPORTS_MATCH
- CRYPTO_UP_DOWN
- TWEET_COUNT
- SPORTS_TEAM_MATCH
- SPORTS_NBA
- SPORTS_FIFA_WORLD_CUP
- SPORTS_EXACT_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_PROPS
- SPORTS_FIFA_FRIENDLIES
- ESPORTS_LOL
- ESPORTS_CS2
- ESPORTS_DOTA2
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- UP_DOWN
MarketVariantDetails:
type: object
title: MarketVariantDetails
description: >-
What a market is about, one key per kind of market.
Grouping by kind rather than discriminating on a type means a kind that
gains a payload is a new key, and one that loses it is a key removed,
with
nothing to keep in step. A market names the kinds that apply to it,
which
today is at most one.
Add a kind by adding a key. Each is filled independently, so a populator
sets its own key on the value already there rather than replacing it.
properties:
sports:
description: Set for a market of a sports category.
allOf:
- $ref: "#/components/schemas/SportsMarketDetails"
- description: Set for a market of a sports category.
Outcome:
type: object
title: Outcome
description: Outcome data (from markets, positions, etc.)/// Outcome data (from
markets, positions, etc.)
required:
- name
- indexSet
- onChainId
properties:
name:
type: string
indexSet:
type: integer
format: int32
onChainId:
type: string
description: bigint string
status:
$ref: "#/components/schemas/OutcomeStatus"
bestBid:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes, or
poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is embedded
in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the next.
That is what caps the shared-cache TTL on those routes at seconds,
and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes,
or poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is
embedded in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the
next.
That is what caps the shared-cache TTL on those routes at
seconds, and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
bestAsk:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead, and
why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead,
and why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
outcome resolves to a specific team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
outcome resolves to a specific team.
deprecated: true
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/OutcomeVariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this outcome is about. Absent when it is about neither team.
allOf:
- $ref: "#/components/schemas/OutcomeVariantDetails"
- description: What this outcome is about. Absent when it is about neither team.
OutcomeStatus:
type: string
description: Resolution status of a market outcome.
enum:
- WON
- LOST
OutcomeVariantData:
type: object
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
oneOf:
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
discriminator:
propertyName: type
mapping:
SPORTS_NBA: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_LOL: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_CS2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_DOTA2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
OutcomeVariantData_SportsTeamOutcomeData:
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/SportsTeamOutcomeData"
OutcomeVariantDetails:
type: object
title: OutcomeVariantDetails
description: |-
What an outcome is about, one key per kind of market.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for an outcome that resolves to a team.
allOf:
- $ref: "#/components/schemas/SportsOutcomeDetails"
- description: Set for an outcome that resolves to a team.
PriceFeedProvider:
type: string
description: Provider of the price feed backing a crypto market.
enum:
- PYTH
- BINANCE
- CHAINLINK
- ATLAS
PriceLevel:
type: object
title: PriceLevel
required:
- price
- size
properties:
price:
type: number
format: double
description: In [0.0, 1.0].
size:
type: number
format: double
Protocol:
type: string
description: |-
The protocol a category's markets trade on. Every market in a category
shares it, and it decides which exchange contracts a client talks to.
enum:
- LEGACY
- PREDICT
ResolutionProvider:
type: string
description: Resolution provider for a category (maps to
`resolution_provider_type` table).
enum:
- PREDICT_DOT_FUN
- THREE_PO
- CHAINLINK
- ATLAS
RewardPeriod:
type: object
title: RewardPeriod
description: A single span during which a market accrues rewards at a fixed
hourly rate.
required:
- hourlyRate
- startsAt
- endsAt
properties:
hourlyRate:
type: integer
format: int32
description: Reward points earned per hour while this period is active.
startsAt:
type: string
endsAt:
type: string
ScoreboardSource:
type: string
description: The source a scoreboard is built on.
enum:
- GRID
- POLYMARKET
- PREDICT_DOT_FUN
SportsCategoryDetails:
type: object
title: SportsCategoryDetails
description: What a sports category is about.
required:
- provider
- teams
properties:
provider:
description: The provider that supplies the fixture.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that supplies the fixture.
providerEventId:
type: string
description: The provider's own id for the fixture, where it has one.
teams:
type: array
description: The two sides of the fixture.
items:
$ref: "#/components/schemas/SportsEventTeam"
scoreboard:
description: Absent until a source has reported on the match.
allOf:
- $ref: "#/components/schemas/SportsScoreboard"
- description: Absent until a source has reported on the match.
SportsDataProvider:
type: string
description: Sports data provider.
enum:
- PREDICT_SPORTS
- GRID
- POLYMARKET
SportsEventTeam:
type: object
title: SportsEventTeam
description: A sportsdata provider team as exposed in category variant data.
required:
- id
properties:
id:
type: integer
format: int64
description: Team identifier.
name:
type: string
abbreviation:
type: string
description: Team key abbreviation (e.g., "MIN", "SA"). Null when not available.
providerTeamId:
type: string
description: The team identifier used by the sportsdata provider. Null when no
game is linked.
isHome:
type: boolean
description: >-
Marks the side the fixture lists as home, which may be a neutral
venue. Null when the
provider does not say.
record:
description: Omitted when the provider sends none, or sends one whose format is
not known.
allOf:
- $ref: "#/components/schemas/SportsTeamRecord"
- description: Omitted when the provider sends none, or sends one whose format is
not known.
color:
type: string
description: >-
Team colour as a hex string from the provider. Omitted when the
provider does not send
one.
SportsFifaFriendliesVariantData:
type: object
title: SportsFifaFriendliesVariantData
description: Variant data for SPORTS_FIFA_FRIENDLIES categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsFifaWorldCupVariantData:
type: object
title: SportsFifaWorldCupVariantData
description: Variant data for SPORTS_FIFA_WORLD_CUP categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsMarketDetails:
type: object
title: SportsMarketDetails
description: What a market of a sports category is about.
properties:
provider:
description: The provider that links the team. Absent when no team is named.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team. Absent when no team is named.
team:
description: The team this market is about, when it is about one. .
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this market is about, when it is about one. .
line:
type: number
format: double
description: >-
The line this market is about: a total, a spread, or a player count.
TODO which side of a spread the line runs is not stated. It belongs
to
the market's `team`, so it needs the importer to record the subject:
polymarket orders a spread's outcomes subject first, and where the
feed
carries `marketMetadata.opticOddsTeamId` that agrees with it. Until
then
only the deprecated `variantData.spreadSide` says anything, and only
for
soccer, where a slug pattern happens to name the side.
gameNumber:
type: integer
format: int32
SportsNbaVariantData:
type: object
title: SportsNbaVariantData
description: Variant data for SPORTS_NBA categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsOutcomeDetails:
type: object
title: SportsOutcomeDetails
description: >-
What an outcome of a sports market is about.
Carries no type of its own, for the same reason as
[`SportsMarketDetails`].
required:
- provider
- team
properties:
provider:
description: The provider that links the team.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team.
team:
description: The team this outcome resolves to.
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this outcome resolves to.
SportsPropsMarketData:
type: object
title: SportsPropsMarketData
description: |-
Per-market data for `SPORTS_PROPS` prop markets.
Fields are market-type-specific: `spreadSide` is set for spread markets,
`line` is set for totals markets. Both-teams-to-score markets emit no
`variantData` of this shape.
properties:
spreadSide:
description: Which side of the parent match this spread market is on. Present
for spread markets only.
allOf:
- $ref: "#/components/schemas/TeamSide"
- description: Which side of the parent match this spread market is on. Present
for spread markets only.
line:
type: number
format: double
description: The line value for this totals market. Present for totals markets
only.
SportsScoreboard:
type: object
title: SportsScoreboard
description: How a match stands.
required:
- source
- score
- games
properties:
source:
description: The source the record is built on.
allOf:
- $ref: "#/components/schemas/ScoreboardSource"
- description: The source the record is built on.
bestOf:
type: integer
format: int32
isLive:
type: boolean
finished:
type: boolean
currentGame:
type: integer
format: int32
description: Counted from one.
period:
type: string
description: "As the feed labels it: `1H`, `Q3`, `2/3`."
clock:
type: string
description: >-
The game clock as the live feed shows it. Its meaning depends on the
sport: time left in
the period for basketball, time played for soccer.
score:
type: array
description: Games won in a series, the match score otherwise.
items:
$ref: "#/components/schemas/SportsTeamScore"
games:
type: array
items:
$ref: "#/components/schemas/SportsScoreboardGame"
SportsScoreboardGame:
type: object
title: SportsScoreboardGame
description: One game of a best-of series.
required:
- gameNumber
- isLive
- finished
- scores
properties:
gameNumber:
type: integer
format: int32
description: Counted from one.
isLive:
type: boolean
finished:
type: boolean
winnerTeamId:
type: integer
format: int64
scores:
type: array
description: Empty when only the winner is known.
items:
$ref: "#/components/schemas/SportsTeamScore"
SportsTeamOutcomeData:
type: object
title: SportsTeamOutcomeData
description: Outcome variant data for sports markets where the outcome maps to a team.
required:
- provider
- team
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
team:
$ref: "#/components/schemas/SportsEventTeam"
SportsTeamRecord:
type: object
title: SportsTeamRecord
description: A team's win-loss record, in one shape whatever the sport or provider.
required:
- wins
- losses
properties:
wins:
type: integer
format: int32
losses:
type: integer
format: int32
draws:
type: integer
format: int32
description: Ties count as draws. Omitted where the sport's record has no draws,
as in basketball.
overtimeLosses:
type: integer
format: int32
description: Ice hockey losses after regulation, counted apart from `losses`.
Omitted elsewhere.
SportsTeamScore:
type: object
title: SportsTeamScore
description: One team's count in a series or a game.
required:
- teamId
- score
properties:
teamId:
type: integer
format: int64
description: The id the category's `teams` entries carry.
score:
type: integer
format: int32
description: Games won, goals, rounds or kills, by what the entry is.
Tag:
type: object
title: Tag
description: Tag data
required:
- id
- name
properties:
id:
type: string
description: bigint string
name:
type: string
level:
type: integer
format: int32
description: >-
Hierarchy level of the tag (1, 2, or 3), or null for flat tags. Tags
form a
tree up to three levels deep, e.g. Sports -> Soccer -> EPL.
parentId:
type: string
description: >-
Id of the parent tag as a bigint string, or null for root and flat
tags.
Together with `level` this allows rendering nested tag menus.
makerRebateBps:
type: integer
format: int32
description: >-
Maker rebate in basis points for fills on categories carrying this
tag,
or null if no rebate applies.
Team:
type: object
title: Team
description: Sports team identity.
required:
- id
- name
- abbreviation
- league
properties:
id:
type: integer
format: int64
name:
type: string
abbreviation:
type: string
alias:
type: string
league:
type: string
TeamSide:
type: string
description: Which side of a sports match a team plays on.
enum:
- HOME
- AWAY
TradingSession:
type: object
title: TradingSession
description: Exchange session during which the settlement price is live, without
trading buffers.
required:
- opensAt
- closesAt
properties:
opensAt:
type: string
description: Session opening time as an ISO 8601 UTC timestamp with millisecond
precision.
closesAt:
type: string
description: Session closing time as an ISO 8601 UTC timestamp with millisecond
precision.
TweetCategoryDetails:
type: object
title: TweetCategoryDetails
description: What a tweet count category is about.
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: The account whose posts are counted.
tweetCount:
type: integer
format: int64
description: Posts counted so far within the category's window.
TweetCountVariantData:
type: object
title: TweetCountVariantData
description: Variant data for TWEET_COUNT markets
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: X (Twitter) account username being tracked
tweetCount:
type: integer
format: int64
description: Current count of tweets within the category date range
UpDownCategoryDetails:
type: object
title: UpDownCategoryDetails
description: What an up down price category is about, whatever the asset class.
required:
- priceFeedProvider
properties:
priceFeedProvider:
description: Who publishes the price this category settles against.
allOf:
- $ref: "#/components/schemas/PriceFeedProvider"
- description: Who publishes the price this category settles against.
priceFeedId:
type: string
description: The feed's own identifier, where it has one.
priceFeedSymbol:
type: string
description: The symbol the feed publishes under, eg. `BTCUSDT` or `SPYUSDT`.
startPrice:
type: number
format: double
description: The price at the start of the window, once the window has opened.
endPrice:
type: number
format: double
description: The price at the end of the window, once it has closed.
VariantData:
type: object
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
oneOf:
- $ref: "#/components/schemas/VariantData_CryptoUpDownVariantData"
- $ref: "#/components/schemas/VariantData_TweetCountVariantData"
- $ref: "#/components/schemas/VariantData_SportsNbaVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
- $ref: "#/components/schemas/VariantData_SportsPropsMarketData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
discriminator:
propertyName: type
mapping:
CRYPTO_UP_DOWN: "#/components/schemas/VariantData_CryptoUpDownVariantData"
TWEET_COUNT: "#/components/schemas/VariantData_TweetCountVariantData"
SPORTS_NBA: "#/components/schemas/VariantData_SportsNbaVariantData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
SPORTS_PROPS: "#/components/schemas/VariantData_SportsPropsMarketData"
ESPORTS_LOL: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_CS2: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_DOTA2: "#/components/schemas/VariantData_EsportsVariantData"
VariantData_CryptoUpDownVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- CRYPTO_UP_DOWN
examples:
- CRYPTO_UP_DOWN
- $ref: "#/components/schemas/CryptoUpDownVariantData"
VariantData_EsportsVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/EsportsVariantData"
VariantData_SportsFifaFriendliesVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_FRIENDLIES
examples:
- SPORTS_FIFA_FRIENDLIES
- $ref: "#/components/schemas/SportsFifaFriendliesVariantData"
VariantData_SportsFifaWorldCupVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_WORLD_CUP
examples:
- SPORTS_FIFA_WORLD_CUP
- $ref: "#/components/schemas/SportsFifaWorldCupVariantData"
VariantData_SportsNbaVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_NBA
examples:
- SPORTS_NBA
- $ref: "#/components/schemas/SportsNbaVariantData"
VariantData_SportsPropsMarketData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_PROPS
examples:
- SPORTS_PROPS
- $ref: "#/components/schemas/SportsPropsMarketData"
VariantData_TweetCountVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- TWEET_COUNT
examples:
- TWEET_COUNT
- $ref: "#/components/schemas/TweetCountVariantData"
```
# Get category by slug (/api/categories/get-category-by-slug)
`GET https://api.predict.fun/v1/categories/{slug}`
Get category information and its markets by slug.
```yaml
paths:
/categories/{slug}:
get:
tags:
- Categories
summary: Get category by slug
description: Get category information and its markets by slug.
parameters:
- name: slug
schema:
type: string
maxLength: 256
in: path
description: The category's slug.
required: true
deprecated: false
explode: true
- name: includeStats
schema:
type: boolean
in: query
description: >-
Whether to fill in `stats` with volume and liquidity figures.
Defaults to `false`,
which leaves `stats` null.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/CategoryResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
CategoryResponse:
type: object
title: CategoryResponse
description: Response for GET /v1/categories/:slug
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/CategoryWithStats"
CategoryStatsData:
type: object
title: CategoryStatsData
description: Category statistics data
required:
- totalLiquidityUsd
- volumeTotalUsd
- volume24hUsd
- holdersCount
properties:
totalLiquidityUsd:
type: number
format: double
volumeTotalUsd:
type: number
format: double
volume24hUsd:
type: number
format: double
holdersCount:
type: integer
format: int64
CategoryStatus:
type: string
description: Category status
enum:
- OPEN
- RESOLVED
- REMOVED
CategoryVariantDetails:
type: object
title: CategoryVariantDetails
description: |-
What a category is about, one key per kind of category.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for a sports category.
allOf:
- $ref: "#/components/schemas/SportsCategoryDetails"
- description: Set for a sports category.
crypto:
description: >-
Set for a crypto up down category.
Superseded by `up_down`, which says the same thing for every asset
class. Both are populated for crypto so existing readers keep
working.
allOf:
- $ref: "#/components/schemas/UpDownCategoryDetails"
- description: >-
Set for a crypto up down category.
Superseded by `up_down`, which says the same thing for every
asset
class. Both are populated for crypto so existing readers keep
working.
upDown:
description: Set for an up down price category, whatever the asset class.
allOf:
- $ref: "#/components/schemas/UpDownCategoryDetails"
- description: Set for an up down price category, whatever the asset class.
tweet:
description: Set for a tweet count category.
allOf:
- $ref: "#/components/schemas/TweetCategoryDetails"
- description: Set for a tweet count category.
CategoryWithStats:
type: object
title: CategoryWithStats
description: Category data with optional inline statistics.
required:
- id
- slug
- title
- description
- imageUrl
- isNegRisk
- protocol
- isYieldBearing
- marketVariant
- createdAt
- publishedAt
- markets
- startsAt
- status
- isVisible
- resolutionProvider
- tags
properties:
id:
type: integer
format: int64
slug:
type: string
title:
type: string
shortTitle:
type: string
description: Short, human-readable label, e.g. `"BTC Up or Down 15m"`. `null`
when not available.
seriesSlug:
type: string
description: >-
Slug of the recurring series this category is a round of, e.g.
`"btc-updown-5m"`. Absent when it is not a round of one. The series
and
its next rounds are at `GET /v1/series/{slug}`.
description:
type: string
imageUrl:
type: string
isNegRisk:
type: boolean
protocol:
$ref: "#/components/schemas/Protocol"
isYieldBearing:
type: boolean
negRiskOnChainId:
type: string
description: On-chain NegRisk market ID as a 32-byte hex string.
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this category is about, replacing `variantData`.
allOf:
- $ref: "#/components/schemas/CategoryVariantDetails"
- description: What this category is about, replacing `variantData`.
createdAt:
type: string
publishedAt:
type: string
markets:
type: array
items:
$ref: "#/components/schemas/Market"
startsAt:
type: string
endsAt:
type: string
tradingSession:
description: >-
Exchange session containing this Up/Down round's entire `startsAt`
to `endsAt` window.
Session times can differ from the round's times and remain available
after closing.
Returns `null` when no applicable session covers the complete round.
Use each market's `tradingStatus` for its current trading status.
allOf:
- $ref: "#/components/schemas/TradingSession"
- description: >-
Exchange session containing this Up/Down round's entire
`startsAt` to `endsAt` window.
Session times can differ from the round's times and remain
available after closing.
Returns `null` when no applicable session covers the complete
round.
Use each market's `tradingStatus` for its current trading
status.
status:
$ref: "#/components/schemas/CategoryStatus"
isVisible:
type: boolean
resolutionProvider:
$ref: "#/components/schemas/ResolutionProvider"
tags:
type: array
items:
$ref: "#/components/schemas/Tag"
teams:
type: array
description: |-
Deprecated in favour of `variantDetails.sports.teams`. The teams
playing, where the category is a fixture.
items:
$ref: "#/components/schemas/Team"
deprecated: true
parentSlug:
type: string
description: The slug of the parent category, when this is a prop/child market.
stats:
$ref: "#/components/schemas/CategoryStatsData"
CryptoUpDownVariantData:
type: object
title: CryptoUpDownVariantData
description: Variant data for CRYPTO_UP_DOWN markets
required:
- priceFeedProvider
properties:
priceFeedProvider:
$ref: "#/components/schemas/PriceFeedProvider"
startPrice:
type: number
format: double
description: Starting price, null before market start
endPrice:
type: number
format: double
description: Ending price from Pyth oracle, null if not yet resolved
priceFeedId:
type: string
description: Pyth oracle price feed identifier
priceFeedSymbol:
type: string
description: Price feed symbol (e.g. "BTCUSDT" for Binance, "BTC_USD" for Pyth)
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
EsportsVariantData:
type: object
title: EsportsVariantData
description: Variant data for esports match categories sourced from Grid.gg.
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked series yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
Market:
type: object
title: Market
description: Full market data as returned by the API
required:
- id
- imageUrl
- title
- question
- description
- tradingStatus
- status
- isVisible
- isNegRisk
- isYieldBearing
- feeRateBps
- makerFeeBps
- oracleQuestionId
- conditionId
- resolverAddress
- outcomes
- spreadThreshold
- shareThreshold
- isBoosted
- polymarketConditionIds
- categorySlug
- createdAt
- decimalPrecision
- marketVariant
- rewards
properties:
id:
type: integer
format: int64
imageUrl:
type: string
title:
type: string
question:
type: string
description:
type: string
tradingStatus:
$ref: "#/components/schemas/MarketTradingStatus"
status:
$ref: "#/components/schemas/MarketStatus"
isVisible:
type: boolean
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
feeRateBps:
type: integer
format: int32
description: Taker fee in basis points, charged on each matched trade.
makerFeeBps:
type: integer
format: int32
description: |-
Maker fee in basis points. Always `0`: no market charges makers.
Defaults on decode so market entries cached before the field existed
still decode rather than reading as misses, and the default is the
only value it takes.
resolution:
$ref: "#/components/schemas/Outcome"
oracleQuestionId:
type: string
conditionId:
type: string
resolverAddress:
type: string
outcomes:
type: array
items:
$ref: "#/components/schemas/Outcome"
questionIndex:
type: integer
format: int32
spreadThreshold:
type: number
format: double
shareThreshold:
type: integer
format: int32
isBoosted:
type: boolean
boostStartsAt:
type: string
boostEndsAt:
type: string
polymarketConditionIds:
type: array
items:
type: string
kalshiMarketTicker:
type: string
categorySlug:
type: string
seriesSlug:
type: string
description: |-
Slug of the recurring series this market's category is a round of,
e.g. `"btc-updown-5m"`. Absent when it is not a round of one. The
series and its next rounds are at `GET /v1/series/{slug}`.
createdAt:
type: string
decimalPrecision:
type: integer
format: int32
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
allOf:
- $ref: "#/components/schemas/MarketVariantDetails"
- description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
market as a whole is about a single team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
market as a whole is about a single team.
deprecated: true
marketType:
description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
allOf:
- $ref: "#/components/schemas/MarketType"
- description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
rewards:
$ref: "#/components/schemas/MarketRewards"
MarketRewards:
type: object
title: MarketRewards
description: Reward schedule for a market.
required:
- schedule
properties:
current:
description: Active period at request time, or `null` if no rewards are accruing.
allOf:
- $ref: "#/components/schemas/RewardPeriod"
- description: Active period at request time, or `null` if no rewards are
accruing.
schedule:
type: array
description: Full schedule of past and future reward periods for this market.
items:
$ref: "#/components/schemas/RewardPeriod"
MarketStatus:
type: string
description: |-
Market lifecycle state, from registration through resolution.
`Removed` is a synthetic status reported for markets that have been
withdrawn, meaning it is not part of the normal lifecycle progression.
enum:
- REGISTERED
- PRICE_PROPOSED
- PRICE_DISPUTED
- PAUSED
- UNPAUSED
- RESOLVED
- REMOVED
MarketTradingStatus:
type: string
description: Trading status derived from market visibility and deletion state.
enum:
- OPEN
- MATCHING_NOT_ENABLED
- CANCEL_ONLY
- CLOSED
MarketType:
type: string
description: >-
Market type (DB `market.market_type_id` values as repr).
Classifies what kind of prediction an individual market represents,
independent of the category it belongs to. Works alongside
[`MarketVariant`]:
the variant describes how the category container renders; the market
type
describes the prediction mechanic of the individual market.
enum:
- SPORTS_MONEYLINE
- SPORTS_SPREADS
- SPORTS_TOTALS
- SPORTS_BOTH_TEAMS_TO_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_EXACT_SCORE
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_TEAM_TOTAL_CORNERS
- SPORTS_CORNERS_ODD_EVEN
- SPORTS_PLAYER_GOALS
- SPORTS_PLAYER_ASSISTS
- SPORTS_PLAYER_GOALS_PLUS_ASSISTS
- SPORTS_PLAYER_SHOTS
- SPORTS_PLAYER_SHOTS_ON_TARGET
- SPORTS_PLAYER_GOALKEEPER_SAVES
- SPORTS_TEAM_TO_ADVANCE
- SPORTS_EXTRA_TIME
- SPORTS_PENALTY_SHOOTOUT
- SPORTS_TEAM_TOTALS
- SPORTS_CHILD_MONEYLINE
- SPORTS_MAP_HANDICAP
- SPORTS_BOTH_TEAMS_TO_SCORE_FIRST_HALF
- SPORTS_BOTH_TEAMS_TO_SCORE_SECOND_HALF
- SPORTS_FIRST_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- SPORTS_FIRST_CORNER
- SPORTS_FIRST_HALF_TOTALS
- SPORTS_SECOND_HALF_TOTALS
- SPORTS_FIRST_HALF_TEAM_TOTALS
- SPORTS_SECOND_HALF_TEAM_TOTALS
- SPORTS_FIRST_BLOOD_GAME
- SPORTS_KILL_OVER_UNDER_GAME
- SPORTS_ROUND_HANDICAP
- SPORTS_ROUND_TOTALS
- SPORTS_ANYTIME_TOUCHDOWNS
- SPORTS_RACE_TO_POINTS
- SPORTS_ODD_EVEN
MarketVariant:
type: string
description: |-
Classifies the market template type.
Controls the UI layout and trading mechanics of a category. See also
[`MarketType`] which classifies individual markets within a category.
enum:
- DEFAULT
- SPORTS_MATCH
- CRYPTO_UP_DOWN
- TWEET_COUNT
- SPORTS_TEAM_MATCH
- SPORTS_NBA
- SPORTS_FIFA_WORLD_CUP
- SPORTS_EXACT_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_PROPS
- SPORTS_FIFA_FRIENDLIES
- ESPORTS_LOL
- ESPORTS_CS2
- ESPORTS_DOTA2
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- UP_DOWN
MarketVariantDetails:
type: object
title: MarketVariantDetails
description: >-
What a market is about, one key per kind of market.
Grouping by kind rather than discriminating on a type means a kind that
gains a payload is a new key, and one that loses it is a key removed,
with
nothing to keep in step. A market names the kinds that apply to it,
which
today is at most one.
Add a kind by adding a key. Each is filled independently, so a populator
sets its own key on the value already there rather than replacing it.
properties:
sports:
description: Set for a market of a sports category.
allOf:
- $ref: "#/components/schemas/SportsMarketDetails"
- description: Set for a market of a sports category.
Outcome:
type: object
title: Outcome
description: Outcome data (from markets, positions, etc.)/// Outcome data (from
markets, positions, etc.)
required:
- name
- indexSet
- onChainId
properties:
name:
type: string
indexSet:
type: integer
format: int32
onChainId:
type: string
description: bigint string
status:
$ref: "#/components/schemas/OutcomeStatus"
bestBid:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes, or
poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is embedded
in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the next.
That is what caps the shared-cache TTL on those routes at seconds,
and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes,
or poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is
embedded in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the
next.
That is what caps the shared-cache TTL on those routes at
seconds, and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
bestAsk:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead, and
why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead,
and why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
outcome resolves to a specific team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
outcome resolves to a specific team.
deprecated: true
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/OutcomeVariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this outcome is about. Absent when it is about neither team.
allOf:
- $ref: "#/components/schemas/OutcomeVariantDetails"
- description: What this outcome is about. Absent when it is about neither team.
OutcomeStatus:
type: string
description: Resolution status of a market outcome.
enum:
- WON
- LOST
OutcomeVariantData:
type: object
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
oneOf:
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
discriminator:
propertyName: type
mapping:
SPORTS_NBA: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_LOL: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_CS2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_DOTA2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
OutcomeVariantData_SportsTeamOutcomeData:
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/SportsTeamOutcomeData"
OutcomeVariantDetails:
type: object
title: OutcomeVariantDetails
description: |-
What an outcome is about, one key per kind of market.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for an outcome that resolves to a team.
allOf:
- $ref: "#/components/schemas/SportsOutcomeDetails"
- description: Set for an outcome that resolves to a team.
PriceFeedProvider:
type: string
description: Provider of the price feed backing a crypto market.
enum:
- PYTH
- BINANCE
- CHAINLINK
- ATLAS
PriceLevel:
type: object
title: PriceLevel
required:
- price
- size
properties:
price:
type: number
format: double
description: In [0.0, 1.0].
size:
type: number
format: double
Protocol:
type: string
description: |-
The protocol a category's markets trade on. Every market in a category
shares it, and it decides which exchange contracts a client talks to.
enum:
- LEGACY
- PREDICT
ResolutionProvider:
type: string
description: Resolution provider for a category (maps to
`resolution_provider_type` table).
enum:
- PREDICT_DOT_FUN
- THREE_PO
- CHAINLINK
- ATLAS
RewardPeriod:
type: object
title: RewardPeriod
description: A single span during which a market accrues rewards at a fixed
hourly rate.
required:
- hourlyRate
- startsAt
- endsAt
properties:
hourlyRate:
type: integer
format: int32
description: Reward points earned per hour while this period is active.
startsAt:
type: string
endsAt:
type: string
ScoreboardSource:
type: string
description: The source a scoreboard is built on.
enum:
- GRID
- POLYMARKET
- PREDICT_DOT_FUN
SportsCategoryDetails:
type: object
title: SportsCategoryDetails
description: What a sports category is about.
required:
- provider
- teams
properties:
provider:
description: The provider that supplies the fixture.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that supplies the fixture.
providerEventId:
type: string
description: The provider's own id for the fixture, where it has one.
teams:
type: array
description: The two sides of the fixture.
items:
$ref: "#/components/schemas/SportsEventTeam"
scoreboard:
description: Absent until a source has reported on the match.
allOf:
- $ref: "#/components/schemas/SportsScoreboard"
- description: Absent until a source has reported on the match.
SportsDataProvider:
type: string
description: Sports data provider.
enum:
- PREDICT_SPORTS
- GRID
- POLYMARKET
SportsEventTeam:
type: object
title: SportsEventTeam
description: A sportsdata provider team as exposed in category variant data.
required:
- id
properties:
id:
type: integer
format: int64
description: Team identifier.
name:
type: string
abbreviation:
type: string
description: Team key abbreviation (e.g., "MIN", "SA"). Null when not available.
providerTeamId:
type: string
description: The team identifier used by the sportsdata provider. Null when no
game is linked.
isHome:
type: boolean
description: >-
Marks the side the fixture lists as home, which may be a neutral
venue. Null when the
provider does not say.
record:
description: Omitted when the provider sends none, or sends one whose format is
not known.
allOf:
- $ref: "#/components/schemas/SportsTeamRecord"
- description: Omitted when the provider sends none, or sends one whose format is
not known.
color:
type: string
description: >-
Team colour as a hex string from the provider. Omitted when the
provider does not send
one.
SportsFifaFriendliesVariantData:
type: object
title: SportsFifaFriendliesVariantData
description: Variant data for SPORTS_FIFA_FRIENDLIES categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsFifaWorldCupVariantData:
type: object
title: SportsFifaWorldCupVariantData
description: Variant data for SPORTS_FIFA_WORLD_CUP categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsMarketDetails:
type: object
title: SportsMarketDetails
description: What a market of a sports category is about.
properties:
provider:
description: The provider that links the team. Absent when no team is named.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team. Absent when no team is named.
team:
description: The team this market is about, when it is about one. .
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this market is about, when it is about one. .
line:
type: number
format: double
description: >-
The line this market is about: a total, a spread, or a player count.
TODO which side of a spread the line runs is not stated. It belongs
to
the market's `team`, so it needs the importer to record the subject:
polymarket orders a spread's outcomes subject first, and where the
feed
carries `marketMetadata.opticOddsTeamId` that agrees with it. Until
then
only the deprecated `variantData.spreadSide` says anything, and only
for
soccer, where a slug pattern happens to name the side.
gameNumber:
type: integer
format: int32
SportsNbaVariantData:
type: object
title: SportsNbaVariantData
description: Variant data for SPORTS_NBA categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsOutcomeDetails:
type: object
title: SportsOutcomeDetails
description: >-
What an outcome of a sports market is about.
Carries no type of its own, for the same reason as
[`SportsMarketDetails`].
required:
- provider
- team
properties:
provider:
description: The provider that links the team.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team.
team:
description: The team this outcome resolves to.
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this outcome resolves to.
SportsPropsMarketData:
type: object
title: SportsPropsMarketData
description: |-
Per-market data for `SPORTS_PROPS` prop markets.
Fields are market-type-specific: `spreadSide` is set for spread markets,
`line` is set for totals markets. Both-teams-to-score markets emit no
`variantData` of this shape.
properties:
spreadSide:
description: Which side of the parent match this spread market is on. Present
for spread markets only.
allOf:
- $ref: "#/components/schemas/TeamSide"
- description: Which side of the parent match this spread market is on. Present
for spread markets only.
line:
type: number
format: double
description: The line value for this totals market. Present for totals markets
only.
SportsScoreboard:
type: object
title: SportsScoreboard
description: How a match stands.
required:
- source
- score
- games
properties:
source:
description: The source the record is built on.
allOf:
- $ref: "#/components/schemas/ScoreboardSource"
- description: The source the record is built on.
bestOf:
type: integer
format: int32
isLive:
type: boolean
finished:
type: boolean
currentGame:
type: integer
format: int32
description: Counted from one.
period:
type: string
description: "As the feed labels it: `1H`, `Q3`, `2/3`."
clock:
type: string
description: >-
The game clock as the live feed shows it. Its meaning depends on the
sport: time left in
the period for basketball, time played for soccer.
score:
type: array
description: Games won in a series, the match score otherwise.
items:
$ref: "#/components/schemas/SportsTeamScore"
games:
type: array
items:
$ref: "#/components/schemas/SportsScoreboardGame"
SportsScoreboardGame:
type: object
title: SportsScoreboardGame
description: One game of a best-of series.
required:
- gameNumber
- isLive
- finished
- scores
properties:
gameNumber:
type: integer
format: int32
description: Counted from one.
isLive:
type: boolean
finished:
type: boolean
winnerTeamId:
type: integer
format: int64
scores:
type: array
description: Empty when only the winner is known.
items:
$ref: "#/components/schemas/SportsTeamScore"
SportsTeamOutcomeData:
type: object
title: SportsTeamOutcomeData
description: Outcome variant data for sports markets where the outcome maps to a team.
required:
- provider
- team
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
team:
$ref: "#/components/schemas/SportsEventTeam"
SportsTeamRecord:
type: object
title: SportsTeamRecord
description: A team's win-loss record, in one shape whatever the sport or provider.
required:
- wins
- losses
properties:
wins:
type: integer
format: int32
losses:
type: integer
format: int32
draws:
type: integer
format: int32
description: Ties count as draws. Omitted where the sport's record has no draws,
as in basketball.
overtimeLosses:
type: integer
format: int32
description: Ice hockey losses after regulation, counted apart from `losses`.
Omitted elsewhere.
SportsTeamScore:
type: object
title: SportsTeamScore
description: One team's count in a series or a game.
required:
- teamId
- score
properties:
teamId:
type: integer
format: int64
description: The id the category's `teams` entries carry.
score:
type: integer
format: int32
description: Games won, goals, rounds or kills, by what the entry is.
Tag:
type: object
title: Tag
description: Tag data
required:
- id
- name
properties:
id:
type: string
description: bigint string
name:
type: string
level:
type: integer
format: int32
description: >-
Hierarchy level of the tag (1, 2, or 3), or null for flat tags. Tags
form a
tree up to three levels deep, e.g. Sports -> Soccer -> EPL.
parentId:
type: string
description: >-
Id of the parent tag as a bigint string, or null for root and flat
tags.
Together with `level` this allows rendering nested tag menus.
makerRebateBps:
type: integer
format: int32
description: >-
Maker rebate in basis points for fills on categories carrying this
tag,
or null if no rebate applies.
Team:
type: object
title: Team
description: Sports team identity.
required:
- id
- name
- abbreviation
- league
properties:
id:
type: integer
format: int64
name:
type: string
abbreviation:
type: string
alias:
type: string
league:
type: string
TeamSide:
type: string
description: Which side of a sports match a team plays on.
enum:
- HOME
- AWAY
TradingSession:
type: object
title: TradingSession
description: Exchange session during which the settlement price is live, without
trading buffers.
required:
- opensAt
- closesAt
properties:
opensAt:
type: string
description: Session opening time as an ISO 8601 UTC timestamp with millisecond
precision.
closesAt:
type: string
description: Session closing time as an ISO 8601 UTC timestamp with millisecond
precision.
TweetCategoryDetails:
type: object
title: TweetCategoryDetails
description: What a tweet count category is about.
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: The account whose posts are counted.
tweetCount:
type: integer
format: int64
description: Posts counted so far within the category's window.
TweetCountVariantData:
type: object
title: TweetCountVariantData
description: Variant data for TWEET_COUNT markets
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: X (Twitter) account username being tracked
tweetCount:
type: integer
format: int64
description: Current count of tweets within the category date range
UpDownCategoryDetails:
type: object
title: UpDownCategoryDetails
description: What an up down price category is about, whatever the asset class.
required:
- priceFeedProvider
properties:
priceFeedProvider:
description: Who publishes the price this category settles against.
allOf:
- $ref: "#/components/schemas/PriceFeedProvider"
- description: Who publishes the price this category settles against.
priceFeedId:
type: string
description: The feed's own identifier, where it has one.
priceFeedSymbol:
type: string
description: The symbol the feed publishes under, eg. `BTCUSDT` or `SPYUSDT`.
startPrice:
type: number
format: double
description: The price at the start of the window, once the window has opened.
endPrice:
type: number
format: double
description: The price at the end of the window, once it has closed.
VariantData:
type: object
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
oneOf:
- $ref: "#/components/schemas/VariantData_CryptoUpDownVariantData"
- $ref: "#/components/schemas/VariantData_TweetCountVariantData"
- $ref: "#/components/schemas/VariantData_SportsNbaVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
- $ref: "#/components/schemas/VariantData_SportsPropsMarketData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
discriminator:
propertyName: type
mapping:
CRYPTO_UP_DOWN: "#/components/schemas/VariantData_CryptoUpDownVariantData"
TWEET_COUNT: "#/components/schemas/VariantData_TweetCountVariantData"
SPORTS_NBA: "#/components/schemas/VariantData_SportsNbaVariantData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
SPORTS_PROPS: "#/components/schemas/VariantData_SportsPropsMarketData"
ESPORTS_LOL: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_CS2: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_DOTA2: "#/components/schemas/VariantData_EsportsVariantData"
VariantData_CryptoUpDownVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- CRYPTO_UP_DOWN
examples:
- CRYPTO_UP_DOWN
- $ref: "#/components/schemas/CryptoUpDownVariantData"
VariantData_EsportsVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/EsportsVariantData"
VariantData_SportsFifaFriendliesVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_FRIENDLIES
examples:
- SPORTS_FIFA_FRIENDLIES
- $ref: "#/components/schemas/SportsFifaFriendliesVariantData"
VariantData_SportsFifaWorldCupVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_WORLD_CUP
examples:
- SPORTS_FIFA_WORLD_CUP
- $ref: "#/components/schemas/SportsFifaWorldCupVariantData"
VariantData_SportsNbaVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_NBA
examples:
- SPORTS_NBA
- $ref: "#/components/schemas/SportsNbaVariantData"
VariantData_SportsPropsMarketData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_PROPS
examples:
- SPORTS_PROPS
- $ref: "#/components/schemas/SportsPropsMarketData"
VariantData_TweetCountVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- TWEET_COUNT
examples:
- TWEET_COUNT
- $ref: "#/components/schemas/TweetCountVariantData"
```
# Get category statistics (/api/categories/get-category-statistics)
`GET https://api.predict.fun/v1/categories/{id}/stats`
Get statistics about a specific category including volume and liquidity.
```yaml
paths:
/categories/{id}/stats:
get:
tags:
- Categories
summary: Get category statistics
description: Get statistics about a specific category including volume and liquidity.
parameters:
- name: id
schema:
type: integer
format: int64
in: path
description: The category's ID.
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/CategoryStatsResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
CategoryStatsData:
type: object
title: CategoryStatsData
description: Category statistics data
required:
- totalLiquidityUsd
- volumeTotalUsd
- volume24hUsd
- holdersCount
properties:
totalLiquidityUsd:
type: number
format: double
volumeTotalUsd:
type: number
format: double
volume24hUsd:
type: number
format: double
holdersCount:
type: integer
format: int64
CategoryStatsResponse:
type: object
title: CategoryStatsResponse
description: Response for GET /v1/categories/:id/stats
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/CategoryStatsData"
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
```
# Get category translations (/api/categories/get-category-translations)
`GET https://api.predict.fun/v1/categories/{slug}/translations`
Fetch all available translations for a category, its markets, and their
outcomes for the requested languages in a single call.
`languages` is a comma-separated list of BCP 47 language codes
(e.g. `zh-CN,ja-JP,ko-KR`). If a language code has no completed
translations it is omitted from the response rather than returning an error.
```yaml
paths:
/categories/{slug}/translations:
get:
tags:
- Categories
summary: Get category translations
description: >-
Fetch all available translations for a category, its markets, and their
outcomes for the requested languages in a single call.
`languages` is a comma-separated list of BCP 47 language codes
(e.g. `zh-CN,ja-JP,ko-KR`). If a language code has no completed
translations it is omitted from the response rather than returning an
error.
parameters:
- name: slug
schema:
type: string
maxLength: 256
in: path
description: The category's slug.
required: true
deprecated: false
explode: true
- name: languages
schema:
type: string
maxLength: 256
in: query
description: >-
Language codes to return, comma-separated, as `GET /v1/languages`
lists them.
Without any, `translations` comes back empty.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/CategoryTranslationsResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
CategoryTranslationData:
type: object
title: CategoryTranslationData
description: All translated content for one language.
required:
- category
- markets
properties:
category:
$ref: "#/components/schemas/CategoryTranslationFields"
markets:
type: array
items:
$ref: "#/components/schemas/MarketTranslationData"
CategoryTranslationFields:
type: object
title: CategoryTranslationFields
description: Translated fields for the category itself.
properties:
title:
type: string
shortTitle:
type: string
CategoryTranslationsResponse:
type: object
title: CategoryTranslationsResponse
description: Response for GET /v1/categories/:slug/translations
required:
- translations
properties:
translations:
type: object
description: Map from language code (e.g. `"zh-CN"`) to its translations.
additionalProperties:
$ref: "#/components/schemas/CategoryTranslationData"
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
MarketTranslationData:
type: object
title: MarketTranslationData
description: Translated fields for a single market.
required:
- id
- outcomes
properties:
id:
type: integer
format: int64
title:
type: string
question:
type: string
description:
type: string
outcomes:
type: array
items:
$ref: "#/components/schemas/OutcomeTranslation"
OutcomeTranslation:
type: object
title: OutcomeTranslation
description: Translated fields for a single outcome.
required:
- index
- name
properties:
index:
type: integer
format: int32
description: Outcome index (matches `Outcome.index_set`).
name:
type: string
```
# Get all tags (/api/categories/get-all-tags)
`GET https://api.predict.fun/v1/tags`
Get all supported tags for filtering categories and markets.
```yaml
paths:
/tags:
get:
tags:
- Categories
summary: Get all tags
description: Get all supported tags for filtering categories and markets.
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/TagsResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
Tag:
type: object
title: Tag
description: Tag data
required:
- id
- name
properties:
id:
type: string
description: bigint string
name:
type: string
level:
type: integer
format: int32
description: >-
Hierarchy level of the tag (1, 2, or 3), or null for flat tags. Tags
form a
tree up to three levels deep, e.g. Sports -> Soccer -> EPL.
parentId:
type: string
description: >-
Id of the parent tag as a bigint string, or null for root and flat
tags.
Together with `level` this allows rendering nested tag menus.
makerRebateBps:
type: integer
format: int32
description: >-
Maker rebate in basis points for fills on categories carrying this
tag,
or null if no rebate applies.
TagsResponse:
type: object
title: TagsResponse
description: Response for GET /v1/tags
required:
- success
- data
properties:
success:
type: boolean
data:
type: array
items:
$ref: "#/components/schemas/Tag"
```
# Get markets (/api/markets/get-markets)
`GET https://api.predict.fun/v1/markets`
Get information about markets with optional filters and sorting.
```yaml
paths:
/markets:
get:
tags:
- Markets
summary: Get markets
description: Get information about markets with optional filters and sorting.
parameters:
- name: first
schema:
type: integer
format: int32
in: query
description: Page size, from 1 to 100. Defaults to 20. A value outside that
range is clamped.
required: false
deprecated: false
explode: true
- name: after
schema:
type: string
maxLength: 1024
in: query
description: The `cursor` from the previous page, to get the next one.
required: false
deprecated: false
explode: true
- name: isBoosted
schema:
type: boolean
in: query
description: Deprecated. Boosts are no longer used.
required: false
deprecated: true
explode: true
- name: hasActiveRewards
schema:
type: boolean
in: query
description: >-
Only markets with a reward period running now (`true`), or only
markets without
one (`false`). Omit it to get both.
required: false
deprecated: false
explode: true
- name: status
schema:
$ref: "#/components/schemas/MarketStatusFilter"
in: query
description: >-
Only open or only resolved markets. Paused markets count as neither,
so they are
only listed when this is omitted.
required: false
deprecated: false
explode: true
- name: tagIds
schema:
type: string
in: query
description: >-
Only markets whose category has at least one of these tag IDs,
comma-separated.
Entries that are not numbers are ignored.
required: false
deprecated: false
explode: true
- name: marketVariant
schema:
$ref: "#/components/schemas/MarketVariant"
in: query
description: Only markets of this variant.
required: false
deprecated: false
explode: true
- name: sort
schema:
$ref: "#/components/schemas/MarketSort"
in: query
description: >-
Without it, markets are grouped by category, with categories in the
platform's
own ranking and markets in their order within the category.
required: false
deprecated: false
explode: true
- name: includeStats
schema:
type: boolean
in: query
description: >-
Whether to fill in `stats` with volume and liquidity figures.
Defaults to `false`,
which leaves `stats` null.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/MarketsResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
CryptoUpDownVariantData:
type: object
title: CryptoUpDownVariantData
description: Variant data for CRYPTO_UP_DOWN markets
required:
- priceFeedProvider
properties:
priceFeedProvider:
$ref: "#/components/schemas/PriceFeedProvider"
startPrice:
type: number
format: double
description: Starting price, null before market start
endPrice:
type: number
format: double
description: Ending price from Pyth oracle, null if not yet resolved
priceFeedId:
type: string
description: Pyth oracle price feed identifier
priceFeedSymbol:
type: string
description: Price feed symbol (e.g. "BTCUSDT" for Binance, "BTC_USD" for Pyth)
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
EsportsVariantData:
type: object
title: EsportsVariantData
description: Variant data for esports match categories sourced from Grid.gg.
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked series yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
MarketRewards:
type: object
title: MarketRewards
description: Reward schedule for a market.
required:
- schedule
properties:
current:
description: Active period at request time, or `null` if no rewards are accruing.
allOf:
- $ref: "#/components/schemas/RewardPeriod"
- description: Active period at request time, or `null` if no rewards are
accruing.
schedule:
type: array
description: Full schedule of past and future reward periods for this market.
items:
$ref: "#/components/schemas/RewardPeriod"
MarketSort:
type: string
description: Market sort options
enum:
- CHANCE_24H_CHANGE_ASC
- CHANCE_24H_CHANGE_DESC
- VOLUME_24H_ASC
- VOLUME_24H_DESC
- VOLUME_24H_CHANGE_ASC
- VOLUME_24H_CHANGE_DESC
- VOLUME_TOTAL_ASC
- VOLUME_TOTAL_DESC
- REWARD_RATE_ASC
- REWARD_RATE_DESC
MarketStatsData:
type: object
title: MarketStatsData
description: Market statistics data
required:
- totalLiquidityUsd
- liquidity3cAskUsd
- volumeTotalUsd
- volume24hUsd
properties:
totalLiquidityUsd:
type: number
format: double
liquidity3cAskUsd:
type: number
format: double
volumeTotalUsd:
type: number
format: double
volume24hUsd:
type: number
format: double
MarketStatus:
type: string
description: |-
Market lifecycle state, from registration through resolution.
`Removed` is a synthetic status reported for markets that have been
withdrawn, meaning it is not part of the normal lifecycle progression.
enum:
- REGISTERED
- PRICE_PROPOSED
- PRICE_DISPUTED
- PAUSED
- UNPAUSED
- RESOLVED
- REMOVED
MarketStatusFilter:
type: string
description: Market status filter for queries
enum:
- OPEN
- RESOLVED
MarketTradingStatus:
type: string
description: Trading status derived from market visibility and deletion state.
enum:
- OPEN
- MATCHING_NOT_ENABLED
- CANCEL_ONLY
- CLOSED
MarketType:
type: string
description: >-
Market type (DB `market.market_type_id` values as repr).
Classifies what kind of prediction an individual market represents,
independent of the category it belongs to. Works alongside
[`MarketVariant`]:
the variant describes how the category container renders; the market
type
describes the prediction mechanic of the individual market.
enum:
- SPORTS_MONEYLINE
- SPORTS_SPREADS
- SPORTS_TOTALS
- SPORTS_BOTH_TEAMS_TO_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_EXACT_SCORE
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_TEAM_TOTAL_CORNERS
- SPORTS_CORNERS_ODD_EVEN
- SPORTS_PLAYER_GOALS
- SPORTS_PLAYER_ASSISTS
- SPORTS_PLAYER_GOALS_PLUS_ASSISTS
- SPORTS_PLAYER_SHOTS
- SPORTS_PLAYER_SHOTS_ON_TARGET
- SPORTS_PLAYER_GOALKEEPER_SAVES
- SPORTS_TEAM_TO_ADVANCE
- SPORTS_EXTRA_TIME
- SPORTS_PENALTY_SHOOTOUT
- SPORTS_TEAM_TOTALS
- SPORTS_CHILD_MONEYLINE
- SPORTS_MAP_HANDICAP
- SPORTS_BOTH_TEAMS_TO_SCORE_FIRST_HALF
- SPORTS_BOTH_TEAMS_TO_SCORE_SECOND_HALF
- SPORTS_FIRST_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- SPORTS_FIRST_CORNER
- SPORTS_FIRST_HALF_TOTALS
- SPORTS_SECOND_HALF_TOTALS
- SPORTS_FIRST_HALF_TEAM_TOTALS
- SPORTS_SECOND_HALF_TEAM_TOTALS
- SPORTS_FIRST_BLOOD_GAME
- SPORTS_KILL_OVER_UNDER_GAME
- SPORTS_ROUND_HANDICAP
- SPORTS_ROUND_TOTALS
- SPORTS_ANYTIME_TOUCHDOWNS
- SPORTS_RACE_TO_POINTS
- SPORTS_ODD_EVEN
MarketVariant:
type: string
description: |-
Classifies the market template type.
Controls the UI layout and trading mechanics of a category. See also
[`MarketType`] which classifies individual markets within a category.
enum:
- DEFAULT
- SPORTS_MATCH
- CRYPTO_UP_DOWN
- TWEET_COUNT
- SPORTS_TEAM_MATCH
- SPORTS_NBA
- SPORTS_FIFA_WORLD_CUP
- SPORTS_EXACT_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_PROPS
- SPORTS_FIFA_FRIENDLIES
- ESPORTS_LOL
- ESPORTS_CS2
- ESPORTS_DOTA2
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- UP_DOWN
MarketVariantDetails:
type: object
title: MarketVariantDetails
description: >-
What a market is about, one key per kind of market.
Grouping by kind rather than discriminating on a type means a kind that
gains a payload is a new key, and one that loses it is a key removed,
with
nothing to keep in step. A market names the kinds that apply to it,
which
today is at most one.
Add a kind by adding a key. Each is filled independently, so a populator
sets its own key on the value already there rather than replacing it.
properties:
sports:
description: Set for a market of a sports category.
allOf:
- $ref: "#/components/schemas/SportsMarketDetails"
- description: Set for a market of a sports category.
MarketWithStats:
type: object
title: MarketWithStats
description: Market data with optional inline statistics.
required:
- id
- imageUrl
- title
- question
- description
- tradingStatus
- status
- isVisible
- isNegRisk
- isYieldBearing
- feeRateBps
- makerFeeBps
- oracleQuestionId
- conditionId
- resolverAddress
- outcomes
- spreadThreshold
- shareThreshold
- isBoosted
- polymarketConditionIds
- categorySlug
- createdAt
- decimalPrecision
- marketVariant
- rewards
properties:
id:
type: integer
format: int64
imageUrl:
type: string
title:
type: string
question:
type: string
description:
type: string
tradingStatus:
$ref: "#/components/schemas/MarketTradingStatus"
status:
$ref: "#/components/schemas/MarketStatus"
isVisible:
type: boolean
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
feeRateBps:
type: integer
format: int32
description: Taker fee in basis points, charged on each matched trade.
makerFeeBps:
type: integer
format: int32
description: |-
Maker fee in basis points. Always `0`: no market charges makers.
Defaults on decode so market entries cached before the field existed
still decode rather than reading as misses, and the default is the
only value it takes.
resolution:
$ref: "#/components/schemas/Outcome"
oracleQuestionId:
type: string
conditionId:
type: string
resolverAddress:
type: string
outcomes:
type: array
items:
$ref: "#/components/schemas/Outcome"
questionIndex:
type: integer
format: int32
spreadThreshold:
type: number
format: double
shareThreshold:
type: integer
format: int32
isBoosted:
type: boolean
boostStartsAt:
type: string
boostEndsAt:
type: string
polymarketConditionIds:
type: array
items:
type: string
kalshiMarketTicker:
type: string
categorySlug:
type: string
seriesSlug:
type: string
description: |-
Slug of the recurring series this market's category is a round of,
e.g. `"btc-updown-5m"`. Absent when it is not a round of one. The
series and its next rounds are at `GET /v1/series/{slug}`.
createdAt:
type: string
decimalPrecision:
type: integer
format: int32
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
allOf:
- $ref: "#/components/schemas/MarketVariantDetails"
- description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
market as a whole is about a single team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
market as a whole is about a single team.
deprecated: true
marketType:
description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
allOf:
- $ref: "#/components/schemas/MarketType"
- description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
rewards:
$ref: "#/components/schemas/MarketRewards"
stats:
$ref: "#/components/schemas/MarketStatsData"
MarketsResponse:
type: object
title: MarketsResponse
description: Response for GET /v1/markets
required:
- success
- data
properties:
success:
type: boolean
cursor:
type: string
data:
type: array
items:
$ref: "#/components/schemas/MarketWithStats"
Outcome:
type: object
title: Outcome
description: Outcome data (from markets, positions, etc.)/// Outcome data (from
markets, positions, etc.)
required:
- name
- indexSet
- onChainId
properties:
name:
type: string
indexSet:
type: integer
format: int32
onChainId:
type: string
description: bigint string
status:
$ref: "#/components/schemas/OutcomeStatus"
bestBid:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes, or
poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is embedded
in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the next.
That is what caps the shared-cache TTL on those routes at seconds,
and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes,
or poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is
embedded in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the
next.
That is what caps the shared-cache TTL on those routes at
seconds, and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
bestAsk:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead, and
why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead,
and why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
outcome resolves to a specific team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
outcome resolves to a specific team.
deprecated: true
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/OutcomeVariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this outcome is about. Absent when it is about neither team.
allOf:
- $ref: "#/components/schemas/OutcomeVariantDetails"
- description: What this outcome is about. Absent when it is about neither team.
OutcomeStatus:
type: string
description: Resolution status of a market outcome.
enum:
- WON
- LOST
OutcomeVariantData:
type: object
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
oneOf:
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
discriminator:
propertyName: type
mapping:
SPORTS_NBA: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_LOL: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_CS2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_DOTA2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
OutcomeVariantData_SportsTeamOutcomeData:
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/SportsTeamOutcomeData"
OutcomeVariantDetails:
type: object
title: OutcomeVariantDetails
description: |-
What an outcome is about, one key per kind of market.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for an outcome that resolves to a team.
allOf:
- $ref: "#/components/schemas/SportsOutcomeDetails"
- description: Set for an outcome that resolves to a team.
PriceFeedProvider:
type: string
description: Provider of the price feed backing a crypto market.
enum:
- PYTH
- BINANCE
- CHAINLINK
- ATLAS
PriceLevel:
type: object
title: PriceLevel
required:
- price
- size
properties:
price:
type: number
format: double
description: In [0.0, 1.0].
size:
type: number
format: double
RewardPeriod:
type: object
title: RewardPeriod
description: A single span during which a market accrues rewards at a fixed
hourly rate.
required:
- hourlyRate
- startsAt
- endsAt
properties:
hourlyRate:
type: integer
format: int32
description: Reward points earned per hour while this period is active.
startsAt:
type: string
endsAt:
type: string
SportsDataProvider:
type: string
description: Sports data provider.
enum:
- PREDICT_SPORTS
- GRID
- POLYMARKET
SportsEventTeam:
type: object
title: SportsEventTeam
description: A sportsdata provider team as exposed in category variant data.
required:
- id
properties:
id:
type: integer
format: int64
description: Team identifier.
name:
type: string
abbreviation:
type: string
description: Team key abbreviation (e.g., "MIN", "SA"). Null when not available.
providerTeamId:
type: string
description: The team identifier used by the sportsdata provider. Null when no
game is linked.
isHome:
type: boolean
description: >-
Marks the side the fixture lists as home, which may be a neutral
venue. Null when the
provider does not say.
record:
description: Omitted when the provider sends none, or sends one whose format is
not known.
allOf:
- $ref: "#/components/schemas/SportsTeamRecord"
- description: Omitted when the provider sends none, or sends one whose format is
not known.
color:
type: string
description: >-
Team colour as a hex string from the provider. Omitted when the
provider does not send
one.
SportsFifaFriendliesVariantData:
type: object
title: SportsFifaFriendliesVariantData
description: Variant data for SPORTS_FIFA_FRIENDLIES categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsFifaWorldCupVariantData:
type: object
title: SportsFifaWorldCupVariantData
description: Variant data for SPORTS_FIFA_WORLD_CUP categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsMarketDetails:
type: object
title: SportsMarketDetails
description: What a market of a sports category is about.
properties:
provider:
description: The provider that links the team. Absent when no team is named.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team. Absent when no team is named.
team:
description: The team this market is about, when it is about one. .
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this market is about, when it is about one. .
line:
type: number
format: double
description: >-
The line this market is about: a total, a spread, or a player count.
TODO which side of a spread the line runs is not stated. It belongs
to
the market's `team`, so it needs the importer to record the subject:
polymarket orders a spread's outcomes subject first, and where the
feed
carries `marketMetadata.opticOddsTeamId` that agrees with it. Until
then
only the deprecated `variantData.spreadSide` says anything, and only
for
soccer, where a slug pattern happens to name the side.
gameNumber:
type: integer
format: int32
SportsNbaVariantData:
type: object
title: SportsNbaVariantData
description: Variant data for SPORTS_NBA categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsOutcomeDetails:
type: object
title: SportsOutcomeDetails
description: >-
What an outcome of a sports market is about.
Carries no type of its own, for the same reason as
[`SportsMarketDetails`].
required:
- provider
- team
properties:
provider:
description: The provider that links the team.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team.
team:
description: The team this outcome resolves to.
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this outcome resolves to.
SportsPropsMarketData:
type: object
title: SportsPropsMarketData
description: |-
Per-market data for `SPORTS_PROPS` prop markets.
Fields are market-type-specific: `spreadSide` is set for spread markets,
`line` is set for totals markets. Both-teams-to-score markets emit no
`variantData` of this shape.
properties:
spreadSide:
description: Which side of the parent match this spread market is on. Present
for spread markets only.
allOf:
- $ref: "#/components/schemas/TeamSide"
- description: Which side of the parent match this spread market is on. Present
for spread markets only.
line:
type: number
format: double
description: The line value for this totals market. Present for totals markets
only.
SportsTeamOutcomeData:
type: object
title: SportsTeamOutcomeData
description: Outcome variant data for sports markets where the outcome maps to a team.
required:
- provider
- team
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
team:
$ref: "#/components/schemas/SportsEventTeam"
SportsTeamRecord:
type: object
title: SportsTeamRecord
description: A team's win-loss record, in one shape whatever the sport or provider.
required:
- wins
- losses
properties:
wins:
type: integer
format: int32
losses:
type: integer
format: int32
draws:
type: integer
format: int32
description: Ties count as draws. Omitted where the sport's record has no draws,
as in basketball.
overtimeLosses:
type: integer
format: int32
description: Ice hockey losses after regulation, counted apart from `losses`.
Omitted elsewhere.
Team:
type: object
title: Team
description: Sports team identity.
required:
- id
- name
- abbreviation
- league
properties:
id:
type: integer
format: int64
name:
type: string
abbreviation:
type: string
alias:
type: string
league:
type: string
TeamSide:
type: string
description: Which side of a sports match a team plays on.
enum:
- HOME
- AWAY
TweetCountVariantData:
type: object
title: TweetCountVariantData
description: Variant data for TWEET_COUNT markets
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: X (Twitter) account username being tracked
tweetCount:
type: integer
format: int64
description: Current count of tweets within the category date range
VariantData:
type: object
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
oneOf:
- $ref: "#/components/schemas/VariantData_CryptoUpDownVariantData"
- $ref: "#/components/schemas/VariantData_TweetCountVariantData"
- $ref: "#/components/schemas/VariantData_SportsNbaVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
- $ref: "#/components/schemas/VariantData_SportsPropsMarketData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
discriminator:
propertyName: type
mapping:
CRYPTO_UP_DOWN: "#/components/schemas/VariantData_CryptoUpDownVariantData"
TWEET_COUNT: "#/components/schemas/VariantData_TweetCountVariantData"
SPORTS_NBA: "#/components/schemas/VariantData_SportsNbaVariantData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
SPORTS_PROPS: "#/components/schemas/VariantData_SportsPropsMarketData"
ESPORTS_LOL: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_CS2: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_DOTA2: "#/components/schemas/VariantData_EsportsVariantData"
VariantData_CryptoUpDownVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- CRYPTO_UP_DOWN
examples:
- CRYPTO_UP_DOWN
- $ref: "#/components/schemas/CryptoUpDownVariantData"
VariantData_EsportsVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/EsportsVariantData"
VariantData_SportsFifaFriendliesVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_FRIENDLIES
examples:
- SPORTS_FIFA_FRIENDLIES
- $ref: "#/components/schemas/SportsFifaFriendliesVariantData"
VariantData_SportsFifaWorldCupVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_WORLD_CUP
examples:
- SPORTS_FIFA_WORLD_CUP
- $ref: "#/components/schemas/SportsFifaWorldCupVariantData"
VariantData_SportsNbaVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_NBA
examples:
- SPORTS_NBA
- $ref: "#/components/schemas/SportsNbaVariantData"
VariantData_SportsPropsMarketData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_PROPS
examples:
- SPORTS_PROPS
- $ref: "#/components/schemas/SportsPropsMarketData"
VariantData_TweetCountVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- TWEET_COUNT
examples:
- TWEET_COUNT
- $ref: "#/components/schemas/TweetCountVariantData"
```
# Get market by ID (/api/markets/get-market-by-id)
`GET https://api.predict.fun/v1/markets/{id}`
Get detailed information about a specific market by its ID.
```yaml
paths:
/markets/{id}:
get:
tags:
- Markets
summary: Get market by ID
description: Get detailed information about a specific market by its ID.
parameters:
- name: id
schema:
type: integer
format: int64
in: path
description: The market's ID.
required: true
deprecated: false
explode: true
- name: includeStats
schema:
type: boolean
in: query
description: >-
Whether to fill in `stats` with volume and liquidity figures.
Defaults to `false`,
which leaves `stats` null.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/MarketResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
CryptoUpDownVariantData:
type: object
title: CryptoUpDownVariantData
description: Variant data for CRYPTO_UP_DOWN markets
required:
- priceFeedProvider
properties:
priceFeedProvider:
$ref: "#/components/schemas/PriceFeedProvider"
startPrice:
type: number
format: double
description: Starting price, null before market start
endPrice:
type: number
format: double
description: Ending price from Pyth oracle, null if not yet resolved
priceFeedId:
type: string
description: Pyth oracle price feed identifier
priceFeedSymbol:
type: string
description: Price feed symbol (e.g. "BTCUSDT" for Binance, "BTC_USD" for Pyth)
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
EsportsVariantData:
type: object
title: EsportsVariantData
description: Variant data for esports match categories sourced from Grid.gg.
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked series yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
MarketResponse:
type: object
title: MarketResponse
description: Response for GET /v1/markets/:id
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/MarketWithStats"
MarketRewards:
type: object
title: MarketRewards
description: Reward schedule for a market.
required:
- schedule
properties:
current:
description: Active period at request time, or `null` if no rewards are accruing.
allOf:
- $ref: "#/components/schemas/RewardPeriod"
- description: Active period at request time, or `null` if no rewards are
accruing.
schedule:
type: array
description: Full schedule of past and future reward periods for this market.
items:
$ref: "#/components/schemas/RewardPeriod"
MarketStatsData:
type: object
title: MarketStatsData
description: Market statistics data
required:
- totalLiquidityUsd
- liquidity3cAskUsd
- volumeTotalUsd
- volume24hUsd
properties:
totalLiquidityUsd:
type: number
format: double
liquidity3cAskUsd:
type: number
format: double
volumeTotalUsd:
type: number
format: double
volume24hUsd:
type: number
format: double
MarketStatus:
type: string
description: |-
Market lifecycle state, from registration through resolution.
`Removed` is a synthetic status reported for markets that have been
withdrawn, meaning it is not part of the normal lifecycle progression.
enum:
- REGISTERED
- PRICE_PROPOSED
- PRICE_DISPUTED
- PAUSED
- UNPAUSED
- RESOLVED
- REMOVED
MarketTradingStatus:
type: string
description: Trading status derived from market visibility and deletion state.
enum:
- OPEN
- MATCHING_NOT_ENABLED
- CANCEL_ONLY
- CLOSED
MarketType:
type: string
description: >-
Market type (DB `market.market_type_id` values as repr).
Classifies what kind of prediction an individual market represents,
independent of the category it belongs to. Works alongside
[`MarketVariant`]:
the variant describes how the category container renders; the market
type
describes the prediction mechanic of the individual market.
enum:
- SPORTS_MONEYLINE
- SPORTS_SPREADS
- SPORTS_TOTALS
- SPORTS_BOTH_TEAMS_TO_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_EXACT_SCORE
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_TEAM_TOTAL_CORNERS
- SPORTS_CORNERS_ODD_EVEN
- SPORTS_PLAYER_GOALS
- SPORTS_PLAYER_ASSISTS
- SPORTS_PLAYER_GOALS_PLUS_ASSISTS
- SPORTS_PLAYER_SHOTS
- SPORTS_PLAYER_SHOTS_ON_TARGET
- SPORTS_PLAYER_GOALKEEPER_SAVES
- SPORTS_TEAM_TO_ADVANCE
- SPORTS_EXTRA_TIME
- SPORTS_PENALTY_SHOOTOUT
- SPORTS_TEAM_TOTALS
- SPORTS_CHILD_MONEYLINE
- SPORTS_MAP_HANDICAP
- SPORTS_BOTH_TEAMS_TO_SCORE_FIRST_HALF
- SPORTS_BOTH_TEAMS_TO_SCORE_SECOND_HALF
- SPORTS_FIRST_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- SPORTS_FIRST_CORNER
- SPORTS_FIRST_HALF_TOTALS
- SPORTS_SECOND_HALF_TOTALS
- SPORTS_FIRST_HALF_TEAM_TOTALS
- SPORTS_SECOND_HALF_TEAM_TOTALS
- SPORTS_FIRST_BLOOD_GAME
- SPORTS_KILL_OVER_UNDER_GAME
- SPORTS_ROUND_HANDICAP
- SPORTS_ROUND_TOTALS
- SPORTS_ANYTIME_TOUCHDOWNS
- SPORTS_RACE_TO_POINTS
- SPORTS_ODD_EVEN
MarketVariant:
type: string
description: |-
Classifies the market template type.
Controls the UI layout and trading mechanics of a category. See also
[`MarketType`] which classifies individual markets within a category.
enum:
- DEFAULT
- SPORTS_MATCH
- CRYPTO_UP_DOWN
- TWEET_COUNT
- SPORTS_TEAM_MATCH
- SPORTS_NBA
- SPORTS_FIFA_WORLD_CUP
- SPORTS_EXACT_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_PROPS
- SPORTS_FIFA_FRIENDLIES
- ESPORTS_LOL
- ESPORTS_CS2
- ESPORTS_DOTA2
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- UP_DOWN
MarketVariantDetails:
type: object
title: MarketVariantDetails
description: >-
What a market is about, one key per kind of market.
Grouping by kind rather than discriminating on a type means a kind that
gains a payload is a new key, and one that loses it is a key removed,
with
nothing to keep in step. A market names the kinds that apply to it,
which
today is at most one.
Add a kind by adding a key. Each is filled independently, so a populator
sets its own key on the value already there rather than replacing it.
properties:
sports:
description: Set for a market of a sports category.
allOf:
- $ref: "#/components/schemas/SportsMarketDetails"
- description: Set for a market of a sports category.
MarketWithStats:
type: object
title: MarketWithStats
description: Market data with optional inline statistics.
required:
- id
- imageUrl
- title
- question
- description
- tradingStatus
- status
- isVisible
- isNegRisk
- isYieldBearing
- feeRateBps
- makerFeeBps
- oracleQuestionId
- conditionId
- resolverAddress
- outcomes
- spreadThreshold
- shareThreshold
- isBoosted
- polymarketConditionIds
- categorySlug
- createdAt
- decimalPrecision
- marketVariant
- rewards
properties:
id:
type: integer
format: int64
imageUrl:
type: string
title:
type: string
question:
type: string
description:
type: string
tradingStatus:
$ref: "#/components/schemas/MarketTradingStatus"
status:
$ref: "#/components/schemas/MarketStatus"
isVisible:
type: boolean
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
feeRateBps:
type: integer
format: int32
description: Taker fee in basis points, charged on each matched trade.
makerFeeBps:
type: integer
format: int32
description: |-
Maker fee in basis points. Always `0`: no market charges makers.
Defaults on decode so market entries cached before the field existed
still decode rather than reading as misses, and the default is the
only value it takes.
resolution:
$ref: "#/components/schemas/Outcome"
oracleQuestionId:
type: string
conditionId:
type: string
resolverAddress:
type: string
outcomes:
type: array
items:
$ref: "#/components/schemas/Outcome"
questionIndex:
type: integer
format: int32
spreadThreshold:
type: number
format: double
shareThreshold:
type: integer
format: int32
isBoosted:
type: boolean
boostStartsAt:
type: string
boostEndsAt:
type: string
polymarketConditionIds:
type: array
items:
type: string
kalshiMarketTicker:
type: string
categorySlug:
type: string
seriesSlug:
type: string
description: |-
Slug of the recurring series this market's category is a round of,
e.g. `"btc-updown-5m"`. Absent when it is not a round of one. The
series and its next rounds are at `GET /v1/series/{slug}`.
createdAt:
type: string
decimalPrecision:
type: integer
format: int32
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
allOf:
- $ref: "#/components/schemas/MarketVariantDetails"
- description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
market as a whole is about a single team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
market as a whole is about a single team.
deprecated: true
marketType:
description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
allOf:
- $ref: "#/components/schemas/MarketType"
- description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
rewards:
$ref: "#/components/schemas/MarketRewards"
stats:
$ref: "#/components/schemas/MarketStatsData"
Outcome:
type: object
title: Outcome
description: Outcome data (from markets, positions, etc.)/// Outcome data (from
markets, positions, etc.)
required:
- name
- indexSet
- onChainId
properties:
name:
type: string
indexSet:
type: integer
format: int32
onChainId:
type: string
description: bigint string
status:
$ref: "#/components/schemas/OutcomeStatus"
bestBid:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes, or
poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is embedded
in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the next.
That is what caps the shared-cache TTL on those routes at seconds,
and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes,
or poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is
embedded in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the
next.
That is what caps the shared-cache TTL on those routes at
seconds, and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
bestAsk:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead, and
why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead,
and why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
outcome resolves to a specific team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
outcome resolves to a specific team.
deprecated: true
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/OutcomeVariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this outcome is about. Absent when it is about neither team.
allOf:
- $ref: "#/components/schemas/OutcomeVariantDetails"
- description: What this outcome is about. Absent when it is about neither team.
OutcomeStatus:
type: string
description: Resolution status of a market outcome.
enum:
- WON
- LOST
OutcomeVariantData:
type: object
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
oneOf:
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
discriminator:
propertyName: type
mapping:
SPORTS_NBA: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_LOL: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_CS2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_DOTA2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
OutcomeVariantData_SportsTeamOutcomeData:
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/SportsTeamOutcomeData"
OutcomeVariantDetails:
type: object
title: OutcomeVariantDetails
description: |-
What an outcome is about, one key per kind of market.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for an outcome that resolves to a team.
allOf:
- $ref: "#/components/schemas/SportsOutcomeDetails"
- description: Set for an outcome that resolves to a team.
PriceFeedProvider:
type: string
description: Provider of the price feed backing a crypto market.
enum:
- PYTH
- BINANCE
- CHAINLINK
- ATLAS
PriceLevel:
type: object
title: PriceLevel
required:
- price
- size
properties:
price:
type: number
format: double
description: In [0.0, 1.0].
size:
type: number
format: double
RewardPeriod:
type: object
title: RewardPeriod
description: A single span during which a market accrues rewards at a fixed
hourly rate.
required:
- hourlyRate
- startsAt
- endsAt
properties:
hourlyRate:
type: integer
format: int32
description: Reward points earned per hour while this period is active.
startsAt:
type: string
endsAt:
type: string
SportsDataProvider:
type: string
description: Sports data provider.
enum:
- PREDICT_SPORTS
- GRID
- POLYMARKET
SportsEventTeam:
type: object
title: SportsEventTeam
description: A sportsdata provider team as exposed in category variant data.
required:
- id
properties:
id:
type: integer
format: int64
description: Team identifier.
name:
type: string
abbreviation:
type: string
description: Team key abbreviation (e.g., "MIN", "SA"). Null when not available.
providerTeamId:
type: string
description: The team identifier used by the sportsdata provider. Null when no
game is linked.
isHome:
type: boolean
description: >-
Marks the side the fixture lists as home, which may be a neutral
venue. Null when the
provider does not say.
record:
description: Omitted when the provider sends none, or sends one whose format is
not known.
allOf:
- $ref: "#/components/schemas/SportsTeamRecord"
- description: Omitted when the provider sends none, or sends one whose format is
not known.
color:
type: string
description: >-
Team colour as a hex string from the provider. Omitted when the
provider does not send
one.
SportsFifaFriendliesVariantData:
type: object
title: SportsFifaFriendliesVariantData
description: Variant data for SPORTS_FIFA_FRIENDLIES categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsFifaWorldCupVariantData:
type: object
title: SportsFifaWorldCupVariantData
description: Variant data for SPORTS_FIFA_WORLD_CUP categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsMarketDetails:
type: object
title: SportsMarketDetails
description: What a market of a sports category is about.
properties:
provider:
description: The provider that links the team. Absent when no team is named.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team. Absent when no team is named.
team:
description: The team this market is about, when it is about one. .
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this market is about, when it is about one. .
line:
type: number
format: double
description: >-
The line this market is about: a total, a spread, or a player count.
TODO which side of a spread the line runs is not stated. It belongs
to
the market's `team`, so it needs the importer to record the subject:
polymarket orders a spread's outcomes subject first, and where the
feed
carries `marketMetadata.opticOddsTeamId` that agrees with it. Until
then
only the deprecated `variantData.spreadSide` says anything, and only
for
soccer, where a slug pattern happens to name the side.
gameNumber:
type: integer
format: int32
SportsNbaVariantData:
type: object
title: SportsNbaVariantData
description: Variant data for SPORTS_NBA categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsOutcomeDetails:
type: object
title: SportsOutcomeDetails
description: >-
What an outcome of a sports market is about.
Carries no type of its own, for the same reason as
[`SportsMarketDetails`].
required:
- provider
- team
properties:
provider:
description: The provider that links the team.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team.
team:
description: The team this outcome resolves to.
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this outcome resolves to.
SportsPropsMarketData:
type: object
title: SportsPropsMarketData
description: |-
Per-market data for `SPORTS_PROPS` prop markets.
Fields are market-type-specific: `spreadSide` is set for spread markets,
`line` is set for totals markets. Both-teams-to-score markets emit no
`variantData` of this shape.
properties:
spreadSide:
description: Which side of the parent match this spread market is on. Present
for spread markets only.
allOf:
- $ref: "#/components/schemas/TeamSide"
- description: Which side of the parent match this spread market is on. Present
for spread markets only.
line:
type: number
format: double
description: The line value for this totals market. Present for totals markets
only.
SportsTeamOutcomeData:
type: object
title: SportsTeamOutcomeData
description: Outcome variant data for sports markets where the outcome maps to a team.
required:
- provider
- team
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
team:
$ref: "#/components/schemas/SportsEventTeam"
SportsTeamRecord:
type: object
title: SportsTeamRecord
description: A team's win-loss record, in one shape whatever the sport or provider.
required:
- wins
- losses
properties:
wins:
type: integer
format: int32
losses:
type: integer
format: int32
draws:
type: integer
format: int32
description: Ties count as draws. Omitted where the sport's record has no draws,
as in basketball.
overtimeLosses:
type: integer
format: int32
description: Ice hockey losses after regulation, counted apart from `losses`.
Omitted elsewhere.
Team:
type: object
title: Team
description: Sports team identity.
required:
- id
- name
- abbreviation
- league
properties:
id:
type: integer
format: int64
name:
type: string
abbreviation:
type: string
alias:
type: string
league:
type: string
TeamSide:
type: string
description: Which side of a sports match a team plays on.
enum:
- HOME
- AWAY
TweetCountVariantData:
type: object
title: TweetCountVariantData
description: Variant data for TWEET_COUNT markets
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: X (Twitter) account username being tracked
tweetCount:
type: integer
format: int64
description: Current count of tweets within the category date range
VariantData:
type: object
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
oneOf:
- $ref: "#/components/schemas/VariantData_CryptoUpDownVariantData"
- $ref: "#/components/schemas/VariantData_TweetCountVariantData"
- $ref: "#/components/schemas/VariantData_SportsNbaVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
- $ref: "#/components/schemas/VariantData_SportsPropsMarketData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
discriminator:
propertyName: type
mapping:
CRYPTO_UP_DOWN: "#/components/schemas/VariantData_CryptoUpDownVariantData"
TWEET_COUNT: "#/components/schemas/VariantData_TweetCountVariantData"
SPORTS_NBA: "#/components/schemas/VariantData_SportsNbaVariantData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
SPORTS_PROPS: "#/components/schemas/VariantData_SportsPropsMarketData"
ESPORTS_LOL: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_CS2: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_DOTA2: "#/components/schemas/VariantData_EsportsVariantData"
VariantData_CryptoUpDownVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- CRYPTO_UP_DOWN
examples:
- CRYPTO_UP_DOWN
- $ref: "#/components/schemas/CryptoUpDownVariantData"
VariantData_EsportsVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/EsportsVariantData"
VariantData_SportsFifaFriendliesVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_FRIENDLIES
examples:
- SPORTS_FIFA_FRIENDLIES
- $ref: "#/components/schemas/SportsFifaFriendliesVariantData"
VariantData_SportsFifaWorldCupVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_WORLD_CUP
examples:
- SPORTS_FIFA_WORLD_CUP
- $ref: "#/components/schemas/SportsFifaWorldCupVariantData"
VariantData_SportsNbaVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_NBA
examples:
- SPORTS_NBA
- $ref: "#/components/schemas/SportsNbaVariantData"
VariantData_SportsPropsMarketData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_PROPS
examples:
- SPORTS_PROPS
- $ref: "#/components/schemas/SportsPropsMarketData"
VariantData_TweetCountVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- TWEET_COUNT
examples:
- TWEET_COUNT
- $ref: "#/components/schemas/TweetCountVariantData"
```
# Get market statistics (/api/markets/get-market-statistics)
`GET https://api.predict.fun/v1/markets/{id}/stats`
Get statistics about a specific market including volume and liquidity.
```yaml
paths:
/markets/{id}/stats:
get:
tags:
- Markets
summary: Get market statistics
description: Get statistics about a specific market including volume and liquidity.
parameters:
- name: id
schema:
type: integer
format: int64
in: path
description: The market's ID.
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/MarketStatsResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
MarketStatsData:
type: object
title: MarketStatsData
description: Market statistics data
required:
- totalLiquidityUsd
- liquidity3cAskUsd
- volumeTotalUsd
- volume24hUsd
properties:
totalLiquidityUsd:
type: number
format: double
liquidity3cAskUsd:
type: number
format: double
volumeTotalUsd:
type: number
format: double
volume24hUsd:
type: number
format: double
MarketStatsResponse:
type: object
title: MarketStatsResponse
description: Response for GET /v1/markets/:id/stats
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/MarketStatsData"
```
# Get market last sale (/api/markets/get-market-last-sale)
`GET https://api.predict.fun/v1/markets/{id}/last-sale`
Get the last sale information for a specific market.
```yaml
paths:
/markets/{id}/last-sale:
get:
tags:
- Markets
summary: Get market last sale
description: Get the last sale information for a specific market.
parameters:
- name: id
schema:
type: integer
format: int64
in: path
description: The market's ID.
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/LastSaleResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
LastSaleData:
type: object
title: LastSaleData
description: Last sale information
required:
- quoteType
- outcome
- priceInCurrency
- strategy
properties:
quoteType:
$ref: "#/components/schemas/QuoteType"
outcome:
$ref: "#/components/schemas/OutcomeSide"
priceInCurrency:
type: string
strategy:
$ref: "#/components/schemas/OrderStrategy"
LastSaleResponse:
type: object
title: LastSaleResponse
description: Response for GET /v1/markets/:id/last-sale
required:
- success
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/LastSaleData"
OrderStrategy:
type: string
description: Order execution strategy.
enum:
- MARKET
- LIMIT
OutcomeSide:
type: string
description: "Outcome side in a binary market: yes or no."
enum:
- Yes
- No
QuoteType:
type: string
description: "Quote type: ask or bid."
enum:
- Ask
- Bid
```
# Get market orderbook (/api/markets/get-market-orderbook)
`GET https://api.predict.fun/v1/markets/{id}/orderbook`
Get the orderbook for a specific market.
The order book stores prices based on the Yes outcome.
```yaml
paths:
/markets/{id}/orderbook:
get:
tags:
- Markets
summary: Get market orderbook
description: |-
Get the orderbook for a specific market.
The order book stores prices based on the Yes outcome.
parameters:
- name: id
schema:
type: integer
format: int64
in: path
description: The market's ID.
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/OrderbookResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
LastOrderSettled:
type: object
title: LastOrderSettled
description: Last order settled in orderbook
required:
- id
- price
- kind
- marketId
- side
- outcome
properties:
id:
type: string
price:
type: string
kind:
type: string
marketId:
type: integer
format: int64
side:
$ref: "#/components/schemas/QuoteType"
outcome:
$ref: "#/components/schemas/OutcomeSide"
OrderbookData:
type: object
title: OrderbookData
description: Orderbook data (single object, not array)
required:
- marketId
- updateTimestampMs
- asks
- bids
properties:
marketId:
type: integer
format: int64
updateTimestampMs:
type: integer
format: int64
lastOrderSettled:
$ref: "#/components/schemas/LastOrderSettled"
asks:
type: array
description: Array of [price, size] tuples
items:
type: array
items:
type: number
format: double
bids:
type: array
description: Array of [price, size] tuples
items:
type: array
items:
type: number
format: double
OrderbookResponse:
type: object
title: OrderbookResponse
description: Response for GET /v1/markets/:id/orderbook
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/OrderbookData"
OutcomeSide:
type: string
description: "Outcome side in a binary market: yes or no."
enum:
- Yes
- No
QuoteType:
type: string
description: "Quote type: ask or bid."
enum:
- Ask
- Bid
```
# Get market quote (/api/markets/get-market-quote)
`GET https://api.predict.fun/v1/markets/{id}/quote`
Get the best bid and best ask resting on a market's order book, quoted
against the outcome whose `indexSet` is 1, as the book itself is.
Prefer this over the full order book when only the current price matters,
and over the quotes embedded in a market payload, which are deprecated.
```yaml
paths:
/markets/{id}/quote:
get:
tags:
- Markets
summary: Get market quote
description: >-
Get the best bid and best ask resting on a market's order book, quoted
against the outcome whose `indexSet` is 1, as the book itself is.
Prefer this over the full order book when only the current price
matters,
and over the quotes embedded in a market payload, which are deprecated.
parameters:
- name: id
schema:
type: integer
format: int64
in: path
description: The market's ID.
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/QuoteResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
MarketQuote:
type: object
title: MarketQuote
description: >-
Top of a market's order book: the best price resting on each side.
This is the lightweight alternative to fetching a whole order book, or
to
reading the quotes that used to be embedded in a market payload. Both
sides
come from a single reading, so the two ends of a spread are always
observed
at the same instant.
Prices are quoted against the outcome whose `indexSet` is 1, the same
convention the order book itself uses. To price the complementary
outcome,
swap the sides and subtract from one: its best bid is `1 -
bestAsk.price` and
its best ask is `1 - bestBid.price`, at the same sizes. Round the result
to
six decimal places, or binary floating point will hand you values like
`0.17000000000000004`.
A quote reports the order book as it stands and says nothing about
whether
the market is still trading. Read the market itself for that, and note
that
an absent quote means only that no book is being maintained.
required:
- marketId
- updateTimestampMs
properties:
marketId:
type: integer
format: int64
updateTimestampMs:
type: integer
format: int64
description: >-
When this book last changed, in unix milliseconds. Use it to discard
a
quote that arrives out of order.
bestBid:
description: Absent when nobody is bidding.
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: Absent when nobody is bidding.
bestAsk:
description: Absent when nobody is offering.
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: Absent when nobody is offering.
PriceLevel:
type: object
title: PriceLevel
required:
- price
- size
properties:
price:
type: number
format: double
description: In [0.0, 1.0].
size:
type: number
format: double
QuoteResponse:
type: object
title: QuoteResponse
description: Response for GET /v1/markets/:id/quote
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/MarketQuote"
```
# Get market timeseries (/api/markets/get-market-timeseries)
`GET https://api.predict.fun/v1/markets/{id}/timeseries`
```yaml
paths:
/markets/{id}/timeseries:
get:
tags:
- Markets
summary: Get market timeseries
parameters:
- name: id
schema:
type: integer
format: int64
in: path
description: The market's ID.
required: true
deprecated: false
explode: true
- name: metric
schema:
$ref: "#/components/schemas/Metric"
in: query
description: The metric to query
required: true
deprecated: false
explode: true
- name: resolution
schema:
$ref: "#/components/schemas/Resolution"
in: query
description: Resolution (bucket size) for aggregation
required: false
deprecated: false
explode: true
- name: from
schema:
type: integer
format: int64
in: query
description: >-
Start of the time range in unix seconds, inclusive. It must be
before `to` and at
most 365 days earlier.
required: true
deprecated: false
explode: true
- name: to
schema:
type: integer
format: int64
in: query
description: End of the time range in unix seconds, inclusive. Defaults to now.
required: false
deprecated: false
explode: true
- name: limit
schema:
type: integer
format: int32
in: query
description: >-
Most data points to return, from 1 to 250. Defaults to 50, and a
value outside that
range is clamped.
required: false
deprecated: false
explode: true
- name: after
schema:
type: string
maxLength: 1024
in: query
description: The `cursor` from the previous page, to get the next one.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/TimeseriesResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
Metric:
type: string
description: The metric to query
enum:
- chance
Resolution:
type: string
description: Resolution (bucket size) for timeseries data
enum:
- 1m
- 5m
- 1h
- 1d
- 1w
- 1M
TimeseriesData:
type: object
title: TimeseriesData
description: Inner data for the timeseries response
required:
- resolution
- series
properties:
resolution:
description: The resolution of the returned data points
allOf:
- $ref: "#/components/schemas/Resolution"
- description: The resolution of the returned data points
series:
type: array
description: Data points ordered by time ascending
items:
$ref: "#/components/schemas/TimeseriesPoint"
TimeseriesPoint:
type: object
title: TimeseriesPoint
description: A single timeseries data point
required:
- x
- y
properties:
x:
type: number
format: double
description: Unix timestamp (seconds)
y:
type: number
format: double
description: The metric value
TimeseriesResponse:
type: object
title: TimeseriesResponse
description: Response for market timeseries
required:
- success
- data
properties:
success:
type: boolean
cursor:
type: string
data:
$ref: "#/components/schemas/TimeseriesData"
```
# Get latest market timeseries value (/api/markets/get-latest-market-timeseries-value)
`GET https://api.predict.fun/v1/markets/{id}/timeseries/latest`
```yaml
paths:
/markets/{id}/timeseries/latest:
get:
tags:
- Markets
summary: Get latest market timeseries value
parameters:
- name: id
schema:
type: integer
format: int64
in: path
description: The market's ID.
required: true
deprecated: false
explode: true
- name: metric
schema:
$ref: "#/components/schemas/Metric"
in: query
description: The metric to query
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/TimeseriesLatestResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
Metric:
type: string
description: The metric to query
enum:
- chance
TimeseriesLatestData:
type: object
title: TimeseriesLatestData
description: Inner data for the latest timeseries response
required:
- x
- y
properties:
x:
type: number
format: double
description: Unix timestamp (seconds)
y:
type: number
format: double
description: The metric value
TimeseriesLatestResponse:
type: object
title: TimeseriesLatestResponse
description: Response for market timeseries latest
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/TimeseriesLatestData"
```
# Get orderbooks for multiple markets (/api/markets/get-orderbooks-for-multiple-markets)
`GET https://api.predict.fun/v1/markets/orderbooks`
Returns orderbooks for up to 100 markets in a single call.
Markets without an orderbook are omitted from the response.
```yaml
paths:
/markets/orderbooks:
get:
tags:
- Markets
summary: Get orderbooks for multiple markets
description: |-
Returns orderbooks for up to 100 markets in a single call.
Markets without an orderbook are omitted from the response.
parameters:
- name: ids
schema:
type: array
items:
type: integer
format: int64
in: query
description: Up to 100 market IDs, comma-separated or repeated. A longer list is
rejected.
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/OrderbooksResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
LastOrderSettled:
type: object
title: LastOrderSettled
description: Last order settled in orderbook
required:
- id
- price
- kind
- marketId
- side
- outcome
properties:
id:
type: string
price:
type: string
kind:
type: string
marketId:
type: integer
format: int64
side:
$ref: "#/components/schemas/QuoteType"
outcome:
$ref: "#/components/schemas/OutcomeSide"
OrderbookData:
type: object
title: OrderbookData
description: Orderbook data (single object, not array)
required:
- marketId
- updateTimestampMs
- asks
- bids
properties:
marketId:
type: integer
format: int64
updateTimestampMs:
type: integer
format: int64
lastOrderSettled:
$ref: "#/components/schemas/LastOrderSettled"
asks:
type: array
description: Array of [price, size] tuples
items:
type: array
items:
type: number
format: double
bids:
type: array
description: Array of [price, size] tuples
items:
type: array
items:
type: number
format: double
OrderbooksResponse:
type: object
title: OrderbooksResponse
description: Response for GET /v1/markets/orderbooks
required:
- success
- data
properties:
success:
type: boolean
data:
type: array
items:
$ref: "#/components/schemas/OrderbookData"
OutcomeSide:
type: string
description: "Outcome side in a binary market: yes or no."
enum:
- Yes
- No
QuoteType:
type: string
description: "Quote type: ask or bid."
enum:
- Ask
- Bid
```
# Get quotes for multiple markets (/api/markets/get-quotes-for-multiple-markets)
`GET https://api.predict.fun/v1/markets/quotes`
Returns a quote for up to 500 markets in a single call. This is the
cheapest way to keep a board of prices current.
Markets without a live book are omitted from the response rather than
returned empty, so the result may be shorter than the request.
```yaml
paths:
/markets/quotes:
get:
tags:
- Markets
summary: Get quotes for multiple markets
description: |-
Returns a quote for up to 500 markets in a single call. This is the
cheapest way to keep a board of prices current.
Markets without a live book are omitted from the response rather than
returned empty, so the result may be shorter than the request.
parameters:
- name: ids
schema:
type: array
items:
type: integer
format: int64
in: query
description: Up to 500 market IDs, comma-separated or repeated. A longer list is
rejected.
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/QuotesResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
MarketQuote:
type: object
title: MarketQuote
description: >-
Top of a market's order book: the best price resting on each side.
This is the lightweight alternative to fetching a whole order book, or
to
reading the quotes that used to be embedded in a market payload. Both
sides
come from a single reading, so the two ends of a spread are always
observed
at the same instant.
Prices are quoted against the outcome whose `indexSet` is 1, the same
convention the order book itself uses. To price the complementary
outcome,
swap the sides and subtract from one: its best bid is `1 -
bestAsk.price` and
its best ask is `1 - bestBid.price`, at the same sizes. Round the result
to
six decimal places, or binary floating point will hand you values like
`0.17000000000000004`.
A quote reports the order book as it stands and says nothing about
whether
the market is still trading. Read the market itself for that, and note
that
an absent quote means only that no book is being maintained.
required:
- marketId
- updateTimestampMs
properties:
marketId:
type: integer
format: int64
updateTimestampMs:
type: integer
format: int64
description: >-
When this book last changed, in unix milliseconds. Use it to discard
a
quote that arrives out of order.
bestBid:
description: Absent when nobody is bidding.
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: Absent when nobody is bidding.
bestAsk:
description: Absent when nobody is offering.
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: Absent when nobody is offering.
PriceLevel:
type: object
title: PriceLevel
required:
- price
- size
properties:
price:
type: number
format: double
description: In [0.0, 1.0].
size:
type: number
format: double
QuotesResponse:
type: object
title: QuotesResponse
description: Response for GET /v1/markets/quotes
required:
- success
- data
properties:
success:
type: boolean
data:
type: array
items:
$ref: "#/components/schemas/MarketQuote"
```
# Get timeseries for multiple markets (/api/markets/get-timeseries-for-multiple-markets)
`GET https://api.predict.fun/v1/markets/timeseries`
Paginated chance points for up to 20 markets in one call. The cursor
is a single shared timestamp that advances across all markets.
```yaml
paths:
/markets/timeseries:
get:
tags:
- Markets
summary: Get timeseries for multiple markets
description: |-
Paginated chance points for up to 20 markets in one call. The cursor
is a single shared timestamp that advances across all markets.
parameters:
- name: ids
schema:
type: array
items:
type: integer
format: int64
in: query
description: Up to 20 market IDs, comma-separated or repeated. A longer list is
rejected.
required: true
deprecated: false
explode: true
- name: metric
schema:
$ref: "#/components/schemas/Metric"
in: query
description: The metric to query.
required: true
deprecated: false
explode: true
- name: resolution
schema:
$ref: "#/components/schemas/Resolution"
in: query
description: >-
Bucket size of the data points, the same for every market. Defaults
to one chosen
from the length of the time range.
required: false
deprecated: false
explode: true
- name: from
schema:
type: integer
format: int64
in: query
description: >-
Start of the time range in unix seconds, inclusive. It must be
before `to` and at
most 365 days earlier.
required: true
deprecated: false
explode: true
- name: to
schema:
type: integer
format: int64
in: query
description: End of the time range in unix seconds, inclusive. Defaults to now.
required: false
deprecated: false
explode: true
- name: limit
schema:
type: integer
format: int32
in: query
description: >-
Most distinct timestamps to return across all markets, from 1 to
250. Defaults to
50, and a value outside that range is clamped.
required: false
deprecated: false
explode: true
- name: after
schema:
type: string
maxLength: 1024
in: query
description: The `cursor` from the previous page, to get the next one.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/TimeseriesBatchResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
MarketTimeseries:
type: object
title: MarketTimeseries
required:
- marketId
- series
properties:
marketId:
type: integer
format: int64
series:
type: array
items:
$ref: "#/components/schemas/TimeseriesPoint"
Metric:
type: string
description: The metric to query
enum:
- chance
Resolution:
type: string
description: Resolution (bucket size) for timeseries data
enum:
- 1m
- 5m
- 1h
- 1d
- 1w
- 1M
TimeseriesBatchData:
type: object
title: TimeseriesBatchData
description: "`resolution` is shared across all markets in the request."
required:
- resolution
- markets
properties:
resolution:
$ref: "#/components/schemas/Resolution"
markets:
type: array
items:
$ref: "#/components/schemas/MarketTimeseries"
TimeseriesBatchResponse:
type: object
title: TimeseriesBatchResponse
required:
- success
- data
properties:
success:
type: boolean
cursor:
type: string
data:
$ref: "#/components/schemas/TimeseriesBatchData"
TimeseriesPoint:
type: object
title: TimeseriesPoint
description: A single timeseries data point
required:
- x
- y
properties:
x:
type: number
format: double
description: Unix timestamp (seconds)
y:
type: number
format: double
description: The metric value
```
# Get latest timeseries value for multiple markets (/api/markets/get-latest-timeseries-value-for-multiple-markets)
`GET https://api.predict.fun/v1/markets/timeseries/latest`
Returns the current chance for up to 20 markets in one call.
Missing markets are omitted.
```yaml
paths:
/markets/timeseries/latest:
get:
tags:
- Markets
summary: Get latest timeseries value for multiple markets
description: |-
Returns the current chance for up to 20 markets in one call.
Missing markets are omitted.
parameters:
- name: ids
schema:
type: array
items:
type: integer
format: int64
in: query
description: Up to 20 market IDs, comma-separated or repeated. A longer list is
rejected.
required: true
deprecated: false
explode: true
- name: metric
schema:
$ref: "#/components/schemas/Metric"
in: query
description: The metric to query.
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/TimeseriesLatestBatchResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
MarketTimeseriesLatest:
type: object
title: MarketTimeseriesLatest
required:
- marketId
- x
- y
properties:
marketId:
type: integer
format: int64
x:
type: number
format: double
description: Unix timestamp (seconds)
y:
type: number
format: double
description: The metric value
Metric:
type: string
description: The metric to query
enum:
- chance
TimeseriesLatestBatchResponse:
type: object
title: TimeseriesLatestBatchResponse
required:
- success
- data
properties:
success:
type: boolean
data:
type: array
items:
$ref: "#/components/schemas/MarketTimeseriesLatest"
```
# Get market status logs (/api/markets/get-market-status-logs)
`GET https://api.predict.fun/v1/markets/status-logs`
Returns the on-chain status transitions (registration, price proposal,
dispute, pause, resolution) of up to 100 markets in a single call,
each market's oldest first. Markets that are not listed, or have no
transitions yet, are omitted from the response.
```yaml
paths:
/markets/status-logs:
get:
tags:
- Markets
summary: Get market status logs
description: |-
Returns the on-chain status transitions (registration, price proposal,
dispute, pause, resolution) of up to 100 markets in a single call,
each market's oldest first. Markets that are not listed, or have no
transitions yet, are omitted from the response.
parameters:
- name: ids
schema:
type: array
items:
type: integer
format: int64
in: query
description: Market ids (comma-separated or repeated)
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/MarketStatusLogsResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
MarketStatus:
type: string
description: |-
Market lifecycle state, from registration through resolution.
`Removed` is a synthetic status reported for markets that have been
withdrawn, meaning it is not part of the normal lifecycle progression.
enum:
- REGISTERED
- PRICE_PROPOSED
- PRICE_DISPUTED
- PAUSED
- UNPAUSED
- RESOLVED
- REMOVED
MarketStatusLog:
type: object
title: MarketStatusLog
description: One on-chain status transition of a market
required:
- status
- timestamp
- transactionHash
- resolutionProvider
properties:
status:
$ref: "#/components/schemas/MarketStatus"
timestamp:
type: string
description: ISO 8601 UTC timestamp of the transaction that made the transition.
transactionHash:
type: string
logIndex:
type: integer
format: int32
description: >-
Position of the event within its block. `null` for transitions with
no
block context.
proposedOutcomeId:
type: integer
format: int32
description: |-
The outcome proposed for resolution: 1 and 2 are the outcomes with
that `indexSet`, 3 is a draw. Only set on `PRICE_PROPOSED` entries.
proposedOutcomeLabel:
type: string
description: |-
Name of the proposed outcome, e.g. `"Yes"` or `"Draw"`. Only set on
`PRICE_PROPOSED` entries.
resolutionProvider:
description: The oracle that made the transition.
allOf:
- $ref: "#/components/schemas/ResolutionProvider"
- description: The oracle that made the transition.
MarketStatusLogs:
type: object
title: MarketStatusLogs
description: A market's status transitions, oldest first
required:
- marketId
- logs
properties:
marketId:
type: integer
format: int64
logs:
type: array
items:
$ref: "#/components/schemas/MarketStatusLog"
MarketStatusLogsResponse:
type: object
title: MarketStatusLogsResponse
description: Response for GET /v1/markets/status-logs
required:
- success
- data
properties:
success:
type: boolean
data:
type: array
items:
$ref: "#/components/schemas/MarketStatusLogs"
ResolutionProvider:
type: string
description: Resolution provider for a category (maps to
`resolution_provider_type` table).
enum:
- PREDICT_DOT_FUN
- THREE_PO
- CHAINLINK
- ATLAS
```
# Get series (/api/series/get-series)
`GET https://api.predict.fun/v1/series`
Get every recurring up/down series, active or retired, sorted by slug.
`marketVariant` keeps the series whose rounds are of that variant, as it
does on `GET /v1/categories`.
```yaml
paths:
/series:
get:
tags:
- Series
summary: Get series
description: |-
Get every recurring up/down series, active or retired, sorted by slug.
`marketVariant` keeps the series whose rounds are of that variant, as it
does on `GET /v1/categories`.
parameters:
- name: marketVariant
schema:
$ref: "#/components/schemas/MarketVariant"
in: query
description: Only series whose rounds are of this variant.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/SeriesListResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
MarketVariant:
type: string
description: |-
Classifies the market template type.
Controls the UI layout and trading mechanics of a category. See also
[`MarketType`] which classifies individual markets within a category.
enum:
- DEFAULT
- SPORTS_MATCH
- CRYPTO_UP_DOWN
- TWEET_COUNT
- SPORTS_TEAM_MATCH
- SPORTS_NBA
- SPORTS_FIFA_WORLD_CUP
- SPORTS_EXACT_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_PROPS
- SPORTS_FIFA_FRIENDLIES
- ESPORTS_LOL
- ESPORTS_CS2
- ESPORTS_DOTA2
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- UP_DOWN
Series:
type: object
title: Series
description: >-
A recurring up/down series: one asset at one cadence, rolling over from
one
round to the next. Each round is a category, listed by
`GET /v1/series/{slug}/rounds`. A retired series stays listed, with its
past
rounds still readable, and simply has no active rounds.
required:
- slug
- symbol
- marketVariant
- intervalSeconds
properties:
slug:
type: string
description: |-
Stable identifier, e.g. `"btc-updown-5m"`. A published slug never
changes, and every round of the series carries it as `seriesSlug`.
symbol:
type: string
description: Asset symbol, e.g. `"BTC"` or `"NVDA"`.
marketVariant:
description: >-
The market variant every round of the series is created with, the
same
value each round reports as its own `marketVariant`.
allOf:
- $ref: "#/components/schemas/MarketVariant"
- description: >-
The market variant every round of the series is created with,
the same
value each round reports as its own `marketVariant`.
intervalSeconds:
type: integer
format: int32
description: >-
Nominal seconds between the starts of consecutive rounds. Series
that
follow a trading calendar skip the hours their market is closed, so
read
each round's own `startsAt` and `endsAt` rather than adding this up.
SeriesListResponse:
type: object
title: SeriesListResponse
description: Response for GET /v1/series
required:
- success
- data
properties:
success:
type: boolean
data:
type: array
items:
$ref: "#/components/schemas/Series"
```
# Get series by slug (/api/series/get-series-by-slug)
`GET https://api.predict.fun/v1/series/{slug}`
Get one recurring up/down series by its slug, e.g. `btc-updown-5m`.
```yaml
paths:
/series/{slug}:
get:
tags:
- Series
summary: Get series by slug
description: Get one recurring up/down series by its slug, e.g. `btc-updown-5m`.
parameters:
- name: slug
schema:
type: string
maxLength: 256
in: path
description: The series' slug, for example `btc-updown-5m`.
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/SeriesResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
MarketVariant:
type: string
description: |-
Classifies the market template type.
Controls the UI layout and trading mechanics of a category. See also
[`MarketType`] which classifies individual markets within a category.
enum:
- DEFAULT
- SPORTS_MATCH
- CRYPTO_UP_DOWN
- TWEET_COUNT
- SPORTS_TEAM_MATCH
- SPORTS_NBA
- SPORTS_FIFA_WORLD_CUP
- SPORTS_EXACT_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_PROPS
- SPORTS_FIFA_FRIENDLIES
- ESPORTS_LOL
- ESPORTS_CS2
- ESPORTS_DOTA2
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- UP_DOWN
Series:
type: object
title: Series
description: >-
A recurring up/down series: one asset at one cadence, rolling over from
one
round to the next. Each round is a category, listed by
`GET /v1/series/{slug}/rounds`. A retired series stays listed, with its
past
rounds still readable, and simply has no active rounds.
required:
- slug
- symbol
- marketVariant
- intervalSeconds
properties:
slug:
type: string
description: |-
Stable identifier, e.g. `"btc-updown-5m"`. A published slug never
changes, and every round of the series carries it as `seriesSlug`.
symbol:
type: string
description: Asset symbol, e.g. `"BTC"` or `"NVDA"`.
marketVariant:
description: >-
The market variant every round of the series is created with, the
same
value each round reports as its own `marketVariant`.
allOf:
- $ref: "#/components/schemas/MarketVariant"
- description: >-
The market variant every round of the series is created with,
the same
value each round reports as its own `marketVariant`.
intervalSeconds:
type: integer
format: int32
description: >-
Nominal seconds between the starts of consecutive rounds. Series
that
follow a trading calendar skip the hours their market is closed, so
read
each round's own `startsAt` and `endsAt` rather than adding this up.
SeriesResponse:
type: object
title: SeriesResponse
description: Response for GET /v1/series/{slug}
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/Series"
```
# Get series rounds (/api/series/get-series-rounds)
`GET https://api.predict.fun/v1/series/{slug}/rounds`
Get the rounds of a series, each one a category with its markets.
`ACTIVE`, the default, lists the rounds that have not ended yet in start
order, so the first is the live round, and the rest are the rounds it
rolls over to. Rounds are created ahead of time, so one page is enough to
follow a series through several rollovers. `ENDED` lists the rounds that
have ended, newest first.
Pages are cached for a few seconds, so a round can still be listed as
active for a moment after its `endsAt`.
```yaml
paths:
/series/{slug}/rounds:
get:
tags:
- Series
summary: Get series rounds
description: >-
Get the rounds of a series, each one a category with its markets.
`ACTIVE`, the default, lists the rounds that have not ended yet in start
order, so the first is the live round, and the rest are the rounds it
rolls over to. Rounds are created ahead of time, so one page is enough
to
follow a series through several rollovers. `ENDED` lists the rounds that
have ended, newest first.
Pages are cached for a few seconds, so a round can still be listed as
active for a moment after its `endsAt`.
parameters:
- name: slug
schema:
type: string
maxLength: 256
in: path
description: The series' slug, for example `btc-updown-5m`.
required: true
deprecated: false
explode: true
- name: status
schema:
$ref: "#/components/schemas/RoundStatusFilter"
in: query
description: >-
Which rounds to list, by whether they have ended. Defaults to
`ACTIVE`, the rounds
that have not ended yet.
required: false
deprecated: false
explode: true
- name: first
schema:
type: integer
format: int32
in: query
description: Page size, from 1 to 100. Defaults to 20. A value outside that
range is clamped.
required: false
deprecated: false
explode: true
- name: after
schema:
type: string
maxLength: 1024
in: query
description: >-
The `cursor` from the previous page, to get the next one. A cursor
from a page of
the other `status` is rejected.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/CategoriesResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
CategoriesResponse:
type: object
title: CategoriesResponse
description: Response for GET /v1/categories
required:
- success
- data
properties:
success:
type: boolean
cursor:
type: string
data:
type: array
items:
$ref: "#/components/schemas/CategoryWithStats"
CategoryStatsData:
type: object
title: CategoryStatsData
description: Category statistics data
required:
- totalLiquidityUsd
- volumeTotalUsd
- volume24hUsd
- holdersCount
properties:
totalLiquidityUsd:
type: number
format: double
volumeTotalUsd:
type: number
format: double
volume24hUsd:
type: number
format: double
holdersCount:
type: integer
format: int64
CategoryStatus:
type: string
description: Category status
enum:
- OPEN
- RESOLVED
- REMOVED
CategoryVariantDetails:
type: object
title: CategoryVariantDetails
description: |-
What a category is about, one key per kind of category.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for a sports category.
allOf:
- $ref: "#/components/schemas/SportsCategoryDetails"
- description: Set for a sports category.
crypto:
description: >-
Set for a crypto up down category.
Superseded by `up_down`, which says the same thing for every asset
class. Both are populated for crypto so existing readers keep
working.
allOf:
- $ref: "#/components/schemas/UpDownCategoryDetails"
- description: >-
Set for a crypto up down category.
Superseded by `up_down`, which says the same thing for every
asset
class. Both are populated for crypto so existing readers keep
working.
upDown:
description: Set for an up down price category, whatever the asset class.
allOf:
- $ref: "#/components/schemas/UpDownCategoryDetails"
- description: Set for an up down price category, whatever the asset class.
tweet:
description: Set for a tweet count category.
allOf:
- $ref: "#/components/schemas/TweetCategoryDetails"
- description: Set for a tweet count category.
CategoryWithStats:
type: object
title: CategoryWithStats
description: Category data with optional inline statistics.
required:
- id
- slug
- title
- description
- imageUrl
- isNegRisk
- protocol
- isYieldBearing
- marketVariant
- createdAt
- publishedAt
- markets
- startsAt
- status
- isVisible
- resolutionProvider
- tags
properties:
id:
type: integer
format: int64
slug:
type: string
title:
type: string
shortTitle:
type: string
description: Short, human-readable label, e.g. `"BTC Up or Down 15m"`. `null`
when not available.
seriesSlug:
type: string
description: >-
Slug of the recurring series this category is a round of, e.g.
`"btc-updown-5m"`. Absent when it is not a round of one. The series
and
its next rounds are at `GET /v1/series/{slug}`.
description:
type: string
imageUrl:
type: string
isNegRisk:
type: boolean
protocol:
$ref: "#/components/schemas/Protocol"
isYieldBearing:
type: boolean
negRiskOnChainId:
type: string
description: On-chain NegRisk market ID as a 32-byte hex string.
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this category is about, replacing `variantData`.
allOf:
- $ref: "#/components/schemas/CategoryVariantDetails"
- description: What this category is about, replacing `variantData`.
createdAt:
type: string
publishedAt:
type: string
markets:
type: array
items:
$ref: "#/components/schemas/Market"
startsAt:
type: string
endsAt:
type: string
tradingSession:
description: >-
Exchange session containing this Up/Down round's entire `startsAt`
to `endsAt` window.
Session times can differ from the round's times and remain available
after closing.
Returns `null` when no applicable session covers the complete round.
Use each market's `tradingStatus` for its current trading status.
allOf:
- $ref: "#/components/schemas/TradingSession"
- description: >-
Exchange session containing this Up/Down round's entire
`startsAt` to `endsAt` window.
Session times can differ from the round's times and remain
available after closing.
Returns `null` when no applicable session covers the complete
round.
Use each market's `tradingStatus` for its current trading
status.
status:
$ref: "#/components/schemas/CategoryStatus"
isVisible:
type: boolean
resolutionProvider:
$ref: "#/components/schemas/ResolutionProvider"
tags:
type: array
items:
$ref: "#/components/schemas/Tag"
teams:
type: array
description: |-
Deprecated in favour of `variantDetails.sports.teams`. The teams
playing, where the category is a fixture.
items:
$ref: "#/components/schemas/Team"
deprecated: true
parentSlug:
type: string
description: The slug of the parent category, when this is a prop/child market.
stats:
$ref: "#/components/schemas/CategoryStatsData"
CryptoUpDownVariantData:
type: object
title: CryptoUpDownVariantData
description: Variant data for CRYPTO_UP_DOWN markets
required:
- priceFeedProvider
properties:
priceFeedProvider:
$ref: "#/components/schemas/PriceFeedProvider"
startPrice:
type: number
format: double
description: Starting price, null before market start
endPrice:
type: number
format: double
description: Ending price from Pyth oracle, null if not yet resolved
priceFeedId:
type: string
description: Pyth oracle price feed identifier
priceFeedSymbol:
type: string
description: Price feed symbol (e.g. "BTCUSDT" for Binance, "BTC_USD" for Pyth)
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
EsportsVariantData:
type: object
title: EsportsVariantData
description: Variant data for esports match categories sourced from Grid.gg.
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked series yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
Market:
type: object
title: Market
description: Full market data as returned by the API
required:
- id
- imageUrl
- title
- question
- description
- tradingStatus
- status
- isVisible
- isNegRisk
- isYieldBearing
- feeRateBps
- makerFeeBps
- oracleQuestionId
- conditionId
- resolverAddress
- outcomes
- spreadThreshold
- shareThreshold
- isBoosted
- polymarketConditionIds
- categorySlug
- createdAt
- decimalPrecision
- marketVariant
- rewards
properties:
id:
type: integer
format: int64
imageUrl:
type: string
title:
type: string
question:
type: string
description:
type: string
tradingStatus:
$ref: "#/components/schemas/MarketTradingStatus"
status:
$ref: "#/components/schemas/MarketStatus"
isVisible:
type: boolean
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
feeRateBps:
type: integer
format: int32
description: Taker fee in basis points, charged on each matched trade.
makerFeeBps:
type: integer
format: int32
description: |-
Maker fee in basis points. Always `0`: no market charges makers.
Defaults on decode so market entries cached before the field existed
still decode rather than reading as misses, and the default is the
only value it takes.
resolution:
$ref: "#/components/schemas/Outcome"
oracleQuestionId:
type: string
conditionId:
type: string
resolverAddress:
type: string
outcomes:
type: array
items:
$ref: "#/components/schemas/Outcome"
questionIndex:
type: integer
format: int32
spreadThreshold:
type: number
format: double
shareThreshold:
type: integer
format: int32
isBoosted:
type: boolean
boostStartsAt:
type: string
boostEndsAt:
type: string
polymarketConditionIds:
type: array
items:
type: string
kalshiMarketTicker:
type: string
categorySlug:
type: string
seriesSlug:
type: string
description: |-
Slug of the recurring series this market's category is a round of,
e.g. `"btc-updown-5m"`. Absent when it is not a round of one. The
series and its next rounds are at `GET /v1/series/{slug}`.
createdAt:
type: string
decimalPrecision:
type: integer
format: int32
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
allOf:
- $ref: "#/components/schemas/MarketVariantDetails"
- description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
market as a whole is about a single team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
market as a whole is about a single team.
deprecated: true
marketType:
description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
allOf:
- $ref: "#/components/schemas/MarketType"
- description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
rewards:
$ref: "#/components/schemas/MarketRewards"
MarketRewards:
type: object
title: MarketRewards
description: Reward schedule for a market.
required:
- schedule
properties:
current:
description: Active period at request time, or `null` if no rewards are accruing.
allOf:
- $ref: "#/components/schemas/RewardPeriod"
- description: Active period at request time, or `null` if no rewards are
accruing.
schedule:
type: array
description: Full schedule of past and future reward periods for this market.
items:
$ref: "#/components/schemas/RewardPeriod"
MarketStatus:
type: string
description: |-
Market lifecycle state, from registration through resolution.
`Removed` is a synthetic status reported for markets that have been
withdrawn, meaning it is not part of the normal lifecycle progression.
enum:
- REGISTERED
- PRICE_PROPOSED
- PRICE_DISPUTED
- PAUSED
- UNPAUSED
- RESOLVED
- REMOVED
MarketTradingStatus:
type: string
description: Trading status derived from market visibility and deletion state.
enum:
- OPEN
- MATCHING_NOT_ENABLED
- CANCEL_ONLY
- CLOSED
MarketType:
type: string
description: >-
Market type (DB `market.market_type_id` values as repr).
Classifies what kind of prediction an individual market represents,
independent of the category it belongs to. Works alongside
[`MarketVariant`]:
the variant describes how the category container renders; the market
type
describes the prediction mechanic of the individual market.
enum:
- SPORTS_MONEYLINE
- SPORTS_SPREADS
- SPORTS_TOTALS
- SPORTS_BOTH_TEAMS_TO_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_EXACT_SCORE
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_TEAM_TOTAL_CORNERS
- SPORTS_CORNERS_ODD_EVEN
- SPORTS_PLAYER_GOALS
- SPORTS_PLAYER_ASSISTS
- SPORTS_PLAYER_GOALS_PLUS_ASSISTS
- SPORTS_PLAYER_SHOTS
- SPORTS_PLAYER_SHOTS_ON_TARGET
- SPORTS_PLAYER_GOALKEEPER_SAVES
- SPORTS_TEAM_TO_ADVANCE
- SPORTS_EXTRA_TIME
- SPORTS_PENALTY_SHOOTOUT
- SPORTS_TEAM_TOTALS
- SPORTS_CHILD_MONEYLINE
- SPORTS_MAP_HANDICAP
- SPORTS_BOTH_TEAMS_TO_SCORE_FIRST_HALF
- SPORTS_BOTH_TEAMS_TO_SCORE_SECOND_HALF
- SPORTS_FIRST_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- SPORTS_FIRST_CORNER
- SPORTS_FIRST_HALF_TOTALS
- SPORTS_SECOND_HALF_TOTALS
- SPORTS_FIRST_HALF_TEAM_TOTALS
- SPORTS_SECOND_HALF_TEAM_TOTALS
- SPORTS_FIRST_BLOOD_GAME
- SPORTS_KILL_OVER_UNDER_GAME
- SPORTS_ROUND_HANDICAP
- SPORTS_ROUND_TOTALS
- SPORTS_ANYTIME_TOUCHDOWNS
- SPORTS_RACE_TO_POINTS
- SPORTS_ODD_EVEN
MarketVariant:
type: string
description: |-
Classifies the market template type.
Controls the UI layout and trading mechanics of a category. See also
[`MarketType`] which classifies individual markets within a category.
enum:
- DEFAULT
- SPORTS_MATCH
- CRYPTO_UP_DOWN
- TWEET_COUNT
- SPORTS_TEAM_MATCH
- SPORTS_NBA
- SPORTS_FIFA_WORLD_CUP
- SPORTS_EXACT_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_PROPS
- SPORTS_FIFA_FRIENDLIES
- ESPORTS_LOL
- ESPORTS_CS2
- ESPORTS_DOTA2
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- UP_DOWN
MarketVariantDetails:
type: object
title: MarketVariantDetails
description: >-
What a market is about, one key per kind of market.
Grouping by kind rather than discriminating on a type means a kind that
gains a payload is a new key, and one that loses it is a key removed,
with
nothing to keep in step. A market names the kinds that apply to it,
which
today is at most one.
Add a kind by adding a key. Each is filled independently, so a populator
sets its own key on the value already there rather than replacing it.
properties:
sports:
description: Set for a market of a sports category.
allOf:
- $ref: "#/components/schemas/SportsMarketDetails"
- description: Set for a market of a sports category.
Outcome:
type: object
title: Outcome
description: Outcome data (from markets, positions, etc.)/// Outcome data (from
markets, positions, etc.)
required:
- name
- indexSet
- onChainId
properties:
name:
type: string
indexSet:
type: integer
format: int32
onChainId:
type: string
description: bigint string
status:
$ref: "#/components/schemas/OutcomeStatus"
bestBid:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes, or
poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is embedded
in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the next.
That is what caps the shared-cache TTL on those routes at seconds,
and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes,
or poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is
embedded in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the
next.
That is what caps the shared-cache TTL on those routes at
seconds, and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
bestAsk:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead, and
why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead,
and why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
outcome resolves to a specific team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
outcome resolves to a specific team.
deprecated: true
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/OutcomeVariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this outcome is about. Absent when it is about neither team.
allOf:
- $ref: "#/components/schemas/OutcomeVariantDetails"
- description: What this outcome is about. Absent when it is about neither team.
OutcomeStatus:
type: string
description: Resolution status of a market outcome.
enum:
- WON
- LOST
OutcomeVariantData:
type: object
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
oneOf:
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
discriminator:
propertyName: type
mapping:
SPORTS_NBA: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_LOL: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_CS2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_DOTA2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
OutcomeVariantData_SportsTeamOutcomeData:
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/SportsTeamOutcomeData"
OutcomeVariantDetails:
type: object
title: OutcomeVariantDetails
description: |-
What an outcome is about, one key per kind of market.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for an outcome that resolves to a team.
allOf:
- $ref: "#/components/schemas/SportsOutcomeDetails"
- description: Set for an outcome that resolves to a team.
PriceFeedProvider:
type: string
description: Provider of the price feed backing a crypto market.
enum:
- PYTH
- BINANCE
- CHAINLINK
- ATLAS
PriceLevel:
type: object
title: PriceLevel
required:
- price
- size
properties:
price:
type: number
format: double
description: In [0.0, 1.0].
size:
type: number
format: double
Protocol:
type: string
description: |-
The protocol a category's markets trade on. Every market in a category
shares it, and it decides which exchange contracts a client talks to.
enum:
- LEGACY
- PREDICT
ResolutionProvider:
type: string
description: Resolution provider for a category (maps to
`resolution_provider_type` table).
enum:
- PREDICT_DOT_FUN
- THREE_PO
- CHAINLINK
- ATLAS
RewardPeriod:
type: object
title: RewardPeriod
description: A single span during which a market accrues rewards at a fixed
hourly rate.
required:
- hourlyRate
- startsAt
- endsAt
properties:
hourlyRate:
type: integer
format: int32
description: Reward points earned per hour while this period is active.
startsAt:
type: string
endsAt:
type: string
RoundStatusFilter:
type: string
description: >-
Which rounds of a series to list, by time rather than by resolution: a
round that has ended can still be awaiting its outcome, which each
round's
own `status` reports.
enum:
- ACTIVE
- ENDED
ScoreboardSource:
type: string
description: The source a scoreboard is built on.
enum:
- GRID
- POLYMARKET
- PREDICT_DOT_FUN
SportsCategoryDetails:
type: object
title: SportsCategoryDetails
description: What a sports category is about.
required:
- provider
- teams
properties:
provider:
description: The provider that supplies the fixture.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that supplies the fixture.
providerEventId:
type: string
description: The provider's own id for the fixture, where it has one.
teams:
type: array
description: The two sides of the fixture.
items:
$ref: "#/components/schemas/SportsEventTeam"
scoreboard:
description: Absent until a source has reported on the match.
allOf:
- $ref: "#/components/schemas/SportsScoreboard"
- description: Absent until a source has reported on the match.
SportsDataProvider:
type: string
description: Sports data provider.
enum:
- PREDICT_SPORTS
- GRID
- POLYMARKET
SportsEventTeam:
type: object
title: SportsEventTeam
description: A sportsdata provider team as exposed in category variant data.
required:
- id
properties:
id:
type: integer
format: int64
description: Team identifier.
name:
type: string
abbreviation:
type: string
description: Team key abbreviation (e.g., "MIN", "SA"). Null when not available.
providerTeamId:
type: string
description: The team identifier used by the sportsdata provider. Null when no
game is linked.
isHome:
type: boolean
description: >-
Marks the side the fixture lists as home, which may be a neutral
venue. Null when the
provider does not say.
record:
description: Omitted when the provider sends none, or sends one whose format is
not known.
allOf:
- $ref: "#/components/schemas/SportsTeamRecord"
- description: Omitted when the provider sends none, or sends one whose format is
not known.
color:
type: string
description: >-
Team colour as a hex string from the provider. Omitted when the
provider does not send
one.
SportsFifaFriendliesVariantData:
type: object
title: SportsFifaFriendliesVariantData
description: Variant data for SPORTS_FIFA_FRIENDLIES categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsFifaWorldCupVariantData:
type: object
title: SportsFifaWorldCupVariantData
description: Variant data for SPORTS_FIFA_WORLD_CUP categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsMarketDetails:
type: object
title: SportsMarketDetails
description: What a market of a sports category is about.
properties:
provider:
description: The provider that links the team. Absent when no team is named.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team. Absent when no team is named.
team:
description: The team this market is about, when it is about one. .
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this market is about, when it is about one. .
line:
type: number
format: double
description: >-
The line this market is about: a total, a spread, or a player count.
TODO which side of a spread the line runs is not stated. It belongs
to
the market's `team`, so it needs the importer to record the subject:
polymarket orders a spread's outcomes subject first, and where the
feed
carries `marketMetadata.opticOddsTeamId` that agrees with it. Until
then
only the deprecated `variantData.spreadSide` says anything, and only
for
soccer, where a slug pattern happens to name the side.
gameNumber:
type: integer
format: int32
SportsNbaVariantData:
type: object
title: SportsNbaVariantData
description: Variant data for SPORTS_NBA categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsOutcomeDetails:
type: object
title: SportsOutcomeDetails
description: >-
What an outcome of a sports market is about.
Carries no type of its own, for the same reason as
[`SportsMarketDetails`].
required:
- provider
- team
properties:
provider:
description: The provider that links the team.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team.
team:
description: The team this outcome resolves to.
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this outcome resolves to.
SportsPropsMarketData:
type: object
title: SportsPropsMarketData
description: |-
Per-market data for `SPORTS_PROPS` prop markets.
Fields are market-type-specific: `spreadSide` is set for spread markets,
`line` is set for totals markets. Both-teams-to-score markets emit no
`variantData` of this shape.
properties:
spreadSide:
description: Which side of the parent match this spread market is on. Present
for spread markets only.
allOf:
- $ref: "#/components/schemas/TeamSide"
- description: Which side of the parent match this spread market is on. Present
for spread markets only.
line:
type: number
format: double
description: The line value for this totals market. Present for totals markets
only.
SportsScoreboard:
type: object
title: SportsScoreboard
description: How a match stands.
required:
- source
- score
- games
properties:
source:
description: The source the record is built on.
allOf:
- $ref: "#/components/schemas/ScoreboardSource"
- description: The source the record is built on.
bestOf:
type: integer
format: int32
isLive:
type: boolean
finished:
type: boolean
currentGame:
type: integer
format: int32
description: Counted from one.
period:
type: string
description: "As the feed labels it: `1H`, `Q3`, `2/3`."
clock:
type: string
description: >-
The game clock as the live feed shows it. Its meaning depends on the
sport: time left in
the period for basketball, time played for soccer.
score:
type: array
description: Games won in a series, the match score otherwise.
items:
$ref: "#/components/schemas/SportsTeamScore"
games:
type: array
items:
$ref: "#/components/schemas/SportsScoreboardGame"
SportsScoreboardGame:
type: object
title: SportsScoreboardGame
description: One game of a best-of series.
required:
- gameNumber
- isLive
- finished
- scores
properties:
gameNumber:
type: integer
format: int32
description: Counted from one.
isLive:
type: boolean
finished:
type: boolean
winnerTeamId:
type: integer
format: int64
scores:
type: array
description: Empty when only the winner is known.
items:
$ref: "#/components/schemas/SportsTeamScore"
SportsTeamOutcomeData:
type: object
title: SportsTeamOutcomeData
description: Outcome variant data for sports markets where the outcome maps to a team.
required:
- provider
- team
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
team:
$ref: "#/components/schemas/SportsEventTeam"
SportsTeamRecord:
type: object
title: SportsTeamRecord
description: A team's win-loss record, in one shape whatever the sport or provider.
required:
- wins
- losses
properties:
wins:
type: integer
format: int32
losses:
type: integer
format: int32
draws:
type: integer
format: int32
description: Ties count as draws. Omitted where the sport's record has no draws,
as in basketball.
overtimeLosses:
type: integer
format: int32
description: Ice hockey losses after regulation, counted apart from `losses`.
Omitted elsewhere.
SportsTeamScore:
type: object
title: SportsTeamScore
description: One team's count in a series or a game.
required:
- teamId
- score
properties:
teamId:
type: integer
format: int64
description: The id the category's `teams` entries carry.
score:
type: integer
format: int32
description: Games won, goals, rounds or kills, by what the entry is.
Tag:
type: object
title: Tag
description: Tag data
required:
- id
- name
properties:
id:
type: string
description: bigint string
name:
type: string
level:
type: integer
format: int32
description: >-
Hierarchy level of the tag (1, 2, or 3), or null for flat tags. Tags
form a
tree up to three levels deep, e.g. Sports -> Soccer -> EPL.
parentId:
type: string
description: >-
Id of the parent tag as a bigint string, or null for root and flat
tags.
Together with `level` this allows rendering nested tag menus.
makerRebateBps:
type: integer
format: int32
description: >-
Maker rebate in basis points for fills on categories carrying this
tag,
or null if no rebate applies.
Team:
type: object
title: Team
description: Sports team identity.
required:
- id
- name
- abbreviation
- league
properties:
id:
type: integer
format: int64
name:
type: string
abbreviation:
type: string
alias:
type: string
league:
type: string
TeamSide:
type: string
description: Which side of a sports match a team plays on.
enum:
- HOME
- AWAY
TradingSession:
type: object
title: TradingSession
description: Exchange session during which the settlement price is live, without
trading buffers.
required:
- opensAt
- closesAt
properties:
opensAt:
type: string
description: Session opening time as an ISO 8601 UTC timestamp with millisecond
precision.
closesAt:
type: string
description: Session closing time as an ISO 8601 UTC timestamp with millisecond
precision.
TweetCategoryDetails:
type: object
title: TweetCategoryDetails
description: What a tweet count category is about.
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: The account whose posts are counted.
tweetCount:
type: integer
format: int64
description: Posts counted so far within the category's window.
TweetCountVariantData:
type: object
title: TweetCountVariantData
description: Variant data for TWEET_COUNT markets
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: X (Twitter) account username being tracked
tweetCount:
type: integer
format: int64
description: Current count of tweets within the category date range
UpDownCategoryDetails:
type: object
title: UpDownCategoryDetails
description: What an up down price category is about, whatever the asset class.
required:
- priceFeedProvider
properties:
priceFeedProvider:
description: Who publishes the price this category settles against.
allOf:
- $ref: "#/components/schemas/PriceFeedProvider"
- description: Who publishes the price this category settles against.
priceFeedId:
type: string
description: The feed's own identifier, where it has one.
priceFeedSymbol:
type: string
description: The symbol the feed publishes under, eg. `BTCUSDT` or `SPYUSDT`.
startPrice:
type: number
format: double
description: The price at the start of the window, once the window has opened.
endPrice:
type: number
format: double
description: The price at the end of the window, once it has closed.
VariantData:
type: object
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
oneOf:
- $ref: "#/components/schemas/VariantData_CryptoUpDownVariantData"
- $ref: "#/components/schemas/VariantData_TweetCountVariantData"
- $ref: "#/components/schemas/VariantData_SportsNbaVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
- $ref: "#/components/schemas/VariantData_SportsPropsMarketData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
discriminator:
propertyName: type
mapping:
CRYPTO_UP_DOWN: "#/components/schemas/VariantData_CryptoUpDownVariantData"
TWEET_COUNT: "#/components/schemas/VariantData_TweetCountVariantData"
SPORTS_NBA: "#/components/schemas/VariantData_SportsNbaVariantData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
SPORTS_PROPS: "#/components/schemas/VariantData_SportsPropsMarketData"
ESPORTS_LOL: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_CS2: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_DOTA2: "#/components/schemas/VariantData_EsportsVariantData"
VariantData_CryptoUpDownVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- CRYPTO_UP_DOWN
examples:
- CRYPTO_UP_DOWN
- $ref: "#/components/schemas/CryptoUpDownVariantData"
VariantData_EsportsVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/EsportsVariantData"
VariantData_SportsFifaFriendliesVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_FRIENDLIES
examples:
- SPORTS_FIFA_FRIENDLIES
- $ref: "#/components/schemas/SportsFifaFriendliesVariantData"
VariantData_SportsFifaWorldCupVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_WORLD_CUP
examples:
- SPORTS_FIFA_WORLD_CUP
- $ref: "#/components/schemas/SportsFifaWorldCupVariantData"
VariantData_SportsNbaVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_NBA
examples:
- SPORTS_NBA
- $ref: "#/components/schemas/SportsNbaVariantData"
VariantData_SportsPropsMarketData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_PROPS
examples:
- SPORTS_PROPS
- $ref: "#/components/schemas/SportsPropsMarketData"
VariantData_TweetCountVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- TWEET_COUNT
examples:
- TWEET_COUNT
- $ref: "#/components/schemas/TweetCountVariantData"
```
# Get order by hash (/api/orders/get-order-by-hash)
`GET https://api.predict.fun/v1/orders/{hash}`
Get the order information for one of your own orders by its hash.
Requires JWT authentication.
```yaml
paths:
/orders/{hash}:
get:
tags:
- Orders
summary: Get order by hash
description: |-
Get the order information for one of your own orders by its hash.
Requires JWT authentication.
parameters:
- name: hash
schema:
type: string
maxLength: 66
in: path
description: The order's hash, in lowercase hex with the `0x` prefix.
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/OrderResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
ContractOrder:
type: object
title: ContractOrder
description: Contract order data (the signed order)
required:
- salt
- maker
- signer
- taker
- tokenId
- makerAmount
- takerAmount
- expiration
- nonce
- feeRateBps
- side
- signatureType
properties:
hash:
type: string
maxLength: 66
salt:
type: string
maker:
type: string
signer:
type: string
taker:
type: string
tokenId:
type: string
makerAmount:
type: string
takerAmount:
type: string
expiration:
type: integer
format: int64
description: Unix timestamp in seconds
nonce:
type: string
feeRateBps:
type: string
side:
type: integer
format: int32
signatureType:
type: integer
format: int32
signature:
type: string
description: |-
Capped at `order_core::order_create::validate::MAX_SIGNATURE_CHARS`.
The attribute takes only a literal, so a test pins the two together.
maxLength: 1026
OrderData:
type: object
title: OrderData
description: Order data as returned by the API
required:
- order
- id
- marketId
- currency
- amount
- amountFilled
- isNegRisk
- isYieldBearing
- strategy
- status
- rewardEarningRate
properties:
order:
$ref: "#/components/schemas/ContractOrder"
id:
type: string
marketId:
type: integer
format: int64
currency:
type: string
amount:
type: string
amountFilled:
type: string
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
strategy:
$ref: "#/components/schemas/OrderStrategy"
status:
$ref: "#/components/schemas/OrderStatus"
rewardEarningRate:
type: integer
format: int32
OrderResponse:
type: object
title: OrderResponse
description: Response for GET /v1/orders/:hash
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/OrderData"
OrderStatus:
type: string
description: Order status
enum:
- OPEN
- FILLED
- EXPIRED
- CANCELLED
- INVALIDATED
OrderStrategy:
type: string
description: Order execution strategy.
enum:
- MARKET
- LIMIT
```
# Get orders (/api/orders/get-orders)
`GET https://api.predict.fun/v1/orders`
Get a list of your own orders with optional filters.
Requires JWT authentication.
```yaml
paths:
/orders:
get:
tags:
- Orders
summary: Get orders
description: |-
Get a list of your own orders with optional filters.
Requires JWT authentication.
parameters:
- name: first
schema:
type: integer
format: int32
in: query
description: Page size, from 1 to 150. Defaults to 50. A value outside that
range is clamped.
required: false
deprecated: false
explode: true
- name: after
schema:
type: string
maxLength: 1024
in: query
description: The `cursor` from the previous page, to get the next one.
required: false
deprecated: false
explode: true
- name: status
schema:
$ref: "#/components/schemas/OrderStatusFilter"
in: query
description: Only orders with this status. Defaults to `OPEN`.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/OrdersResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
ContractOrder:
type: object
title: ContractOrder
description: Contract order data (the signed order)
required:
- salt
- maker
- signer
- taker
- tokenId
- makerAmount
- takerAmount
- expiration
- nonce
- feeRateBps
- side
- signatureType
properties:
hash:
type: string
maxLength: 66
salt:
type: string
maker:
type: string
signer:
type: string
taker:
type: string
tokenId:
type: string
makerAmount:
type: string
takerAmount:
type: string
expiration:
type: integer
format: int64
description: Unix timestamp in seconds
nonce:
type: string
feeRateBps:
type: string
side:
type: integer
format: int32
signatureType:
type: integer
format: int32
signature:
type: string
description: |-
Capped at `order_core::order_create::validate::MAX_SIGNATURE_CHARS`.
The attribute takes only a literal, so a test pins the two together.
maxLength: 1026
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
OrderData:
type: object
title: OrderData
description: Order data as returned by the API
required:
- order
- id
- marketId
- currency
- amount
- amountFilled
- isNegRisk
- isYieldBearing
- strategy
- status
- rewardEarningRate
properties:
order:
$ref: "#/components/schemas/ContractOrder"
id:
type: string
marketId:
type: integer
format: int64
currency:
type: string
amount:
type: string
amountFilled:
type: string
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
strategy:
$ref: "#/components/schemas/OrderStrategy"
status:
$ref: "#/components/schemas/OrderStatus"
rewardEarningRate:
type: integer
format: int32
OrderStatus:
type: string
description: Order status
enum:
- OPEN
- FILLED
- EXPIRED
- CANCELLED
- INVALIDATED
OrderStatusFilter:
type: string
description: Order status filter for queries.
enum:
- OPEN
- FILLED
OrderStrategy:
type: string
description: Order execution strategy.
enum:
- MARKET
- LIMIT
OrdersResponse:
type: object
title: OrdersResponse
description: Response for GET /v1/orders
required:
- success
- data
properties:
success:
type: boolean
cursor:
type: string
data:
type: array
items:
$ref: "#/components/schemas/OrderData"
```
# Create an order (/api/orders/create-an-order)
`POST https://api.predict.fun/v1/orders`
Create a LIMIT or MARKET order for the authenticated user.
Requires JWT authentication.
```yaml
paths:
/orders:
post:
tags:
- Orders
summary: Create an order
description: |-
Create a LIMIT or MARKET order for the authenticated user.
Requires JWT authentication.
requestBody:
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/CreateOrderRequest"
required: true
responses:
"201":
description: Created
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/CreateOrderResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
ContractOrder:
type: object
title: ContractOrder
description: Contract order data (the signed order)
required:
- salt
- maker
- signer
- taker
- tokenId
- makerAmount
- takerAmount
- expiration
- nonce
- feeRateBps
- side
- signatureType
properties:
hash:
type: string
maxLength: 66
salt:
type: string
maker:
type: string
signer:
type: string
taker:
type: string
tokenId:
type: string
makerAmount:
type: string
takerAmount:
type: string
expiration:
type: integer
format: int64
description: Unix timestamp in seconds
nonce:
type: string
feeRateBps:
type: string
side:
type: integer
format: int32
signatureType:
type: integer
format: int32
signature:
type: string
description: |-
Capped at `order_core::order_create::validate::MAX_SIGNATURE_CHARS`.
The attribute takes only a literal, so a test pins the two together.
maxLength: 1026
CreateOrderData:
type: object
title: CreateOrderData
description: Create order request data
required:
- pricePerShare
- strategy
- order
properties:
pricePerShare:
type: string
strategy:
$ref: "#/components/schemas/OrderStrategy"
slippageBps:
type: string
isFillOrKill:
type: boolean
isPostOnly:
type: boolean
reservedBalancePolicy:
$ref: "#/components/schemas/ReservedBalancePolicy"
isMinAmountOut:
type: boolean
description: >-
Signals that `takerAmount` is deflated and represents a signed
minimum,
not the actual fill target. When `true` the backend derives the
actual
share quantity from the expected cost:
`amount = makerAmount * 1e18 / priceInCurrency`.
selfTradePrevention:
$ref: "#/components/schemas/SelfTradePreventionStrategy"
order:
$ref: "#/components/schemas/ContractOrder"
CreateOrderRequest:
type: object
title: CreateOrderRequest
description: Create order request
required:
- data
properties:
data:
$ref: "#/components/schemas/CreateOrderData"
CreateOrderResponse:
type: object
title: CreateOrderResponse
description: Response for POST /v1/orders
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/CreateOrderResponseData"
CreateOrderResponseData:
type: object
title: CreateOrderResponseData
description: Create order response data
required:
- code
- orderId
- orderHash
properties:
code:
type: string
orderId:
type: string
orderHash:
type: string
removalLockedUntil:
type: string
description: RFC 3339 timestamp before which this order cannot be removed.
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
OrderStrategy:
type: string
description: Order execution strategy.
enum:
- MARKET
- LIMIT
ReservedBalancePolicy:
type: string
description: Reserved balance policy
enum:
- REJECT_MARKET_ORDER
- SKIP_RESERVED_BALANCE_CHECKS
SelfTradePreventionStrategy:
type: string
description: Self-trade prevention strategy
enum:
- CANCEL_MAKER
- CANCEL_TAKER
- CANCEL_BOTH
```
# Get order match events (/api/orders/get-order-match-events)
`GET https://api.predict.fun/v1/orders/matches`
Get a paginated list of order match events with optional filtering.
Results are sorted by executedAt DESC. The executedAfter and
executedBefore filters are unix timestamps in milliseconds and both
bounds are exclusive. The orderHashes filter accepts up to 25 order
hashes, comma separated or repeated, and returns the match events in
which any of those orders took part as maker or taker. Hashes that do
not belong to any order are ignored. A match event describes a whole
transaction, so filtering by a maker order also includes the other
fills settled in the same transaction.
```yaml
paths:
/orders/matches:
get:
tags:
- Orders
summary: Get order match events
description: |-
Get a paginated list of order match events with optional filtering.
Results are sorted by executedAt DESC. The executedAfter and
executedBefore filters are unix timestamps in milliseconds and both
bounds are exclusive. The orderHashes filter accepts up to 25 order
hashes, comma separated or repeated, and returns the match events in
which any of those orders took part as maker or taker. Hashes that do
not belong to any order are ignored. A match event describes a whole
transaction, so filtering by a maker order also includes the other
fills settled in the same transaction.
parameters:
- name: first
schema:
type: integer
format: int32
in: query
description: Page size, from 1 to 150. Defaults to 50. A value outside that
range is clamped.
required: false
deprecated: false
explode: true
- name: after
schema:
type: string
in: query
description: The `cursor` from the previous page, to get the next one.
required: false
deprecated: false
explode: true
- name: categoryId
schema:
type: string
in: query
description: Only matches in the category with this slug, which markets return
as `categorySlug`.
required: false
deprecated: false
explode: true
- name: marketId
schema:
type: integer
format: int64
in: query
description: Only matches in this market.
required: false
deprecated: false
explode: true
- name: minValueUsdtWei
schema:
type: string
in: query
description: >-
Only matches with at least one fill worth this much or more, in wei,
where 1 USDT is
10^18 units.
required: false
deprecated: false
explode: true
- name: signerAddress
schema:
type: string
in: query
description: >-
Only matches in which this address was the maker or the taker. For a
Predict account,
use the account's address.
required: false
deprecated: false
explode: true
- name: isSignerMaker
schema:
type: boolean
in: query
description: >-
Set to `true` for only the matches where `signerAddress` was the
maker, or `false` for
those where it was the taker. Requires `signerAddress`.
required: false
deprecated: false
explode: true
- name: orderHashes
schema:
type: array
items:
type: string
in: query
description: >-
Only matches in which one of these orders was the maker or the
taker. Takes up to 25
hashes, comma-separated or repeated.
required: false
deprecated: false
explode: true
- name: executedAfter
schema:
type: integer
format: int64
in: query
description: Only include matches executed strictly after this unix timestamp
(milliseconds).
required: false
deprecated: false
explode: true
- name: executedBefore
schema:
type: integer
format: int64
in: query
description: Only include matches executed strictly before this unix timestamp
(milliseconds).
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/MatchesResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
CryptoUpDownVariantData:
type: object
title: CryptoUpDownVariantData
description: Variant data for CRYPTO_UP_DOWN markets
required:
- priceFeedProvider
properties:
priceFeedProvider:
$ref: "#/components/schemas/PriceFeedProvider"
startPrice:
type: number
format: double
description: Starting price, null before market start
endPrice:
type: number
format: double
description: Ending price from Pyth oracle, null if not yet resolved
priceFeedId:
type: string
description: Pyth oracle price feed identifier
priceFeedSymbol:
type: string
description: Price feed symbol (e.g. "BTCUSDT" for Binance, "BTC_USD" for Pyth)
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
EsportsVariantData:
type: object
title: EsportsVariantData
description: Variant data for esports match categories sourced from Grid.gg.
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked series yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
Fee:
type: object
title: Fee
description: Fee information
required:
- amount
- type
properties:
amount:
type: string
description: The fee amount in wei
type:
description: The fee side, either COLLATERAL (e.g. USDT) or SHARES
allOf:
- $ref: "#/components/schemas/FeeType"
- description: The fee side, either COLLATERAL (e.g. USDT) or SHARES
FeeType:
type: string
description: Fee type
enum:
- COLLATERAL
- SHARES
Market:
type: object
title: Market
description: Full market data as returned by the API
required:
- id
- imageUrl
- title
- question
- description
- tradingStatus
- status
- isVisible
- isNegRisk
- isYieldBearing
- feeRateBps
- makerFeeBps
- oracleQuestionId
- conditionId
- resolverAddress
- outcomes
- spreadThreshold
- shareThreshold
- isBoosted
- polymarketConditionIds
- categorySlug
- createdAt
- decimalPrecision
- marketVariant
- rewards
properties:
id:
type: integer
format: int64
imageUrl:
type: string
title:
type: string
question:
type: string
description:
type: string
tradingStatus:
$ref: "#/components/schemas/MarketTradingStatus"
status:
$ref: "#/components/schemas/MarketStatus"
isVisible:
type: boolean
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
feeRateBps:
type: integer
format: int32
description: Taker fee in basis points, charged on each matched trade.
makerFeeBps:
type: integer
format: int32
description: |-
Maker fee in basis points. Always `0`: no market charges makers.
Defaults on decode so market entries cached before the field existed
still decode rather than reading as misses, and the default is the
only value it takes.
resolution:
$ref: "#/components/schemas/Outcome"
oracleQuestionId:
type: string
conditionId:
type: string
resolverAddress:
type: string
outcomes:
type: array
items:
$ref: "#/components/schemas/Outcome"
questionIndex:
type: integer
format: int32
spreadThreshold:
type: number
format: double
shareThreshold:
type: integer
format: int32
isBoosted:
type: boolean
boostStartsAt:
type: string
boostEndsAt:
type: string
polymarketConditionIds:
type: array
items:
type: string
kalshiMarketTicker:
type: string
categorySlug:
type: string
seriesSlug:
type: string
description: |-
Slug of the recurring series this market's category is a round of,
e.g. `"btc-updown-5m"`. Absent when it is not a round of one. The
series and its next rounds are at `GET /v1/series/{slug}`.
createdAt:
type: string
decimalPrecision:
type: integer
format: int32
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
allOf:
- $ref: "#/components/schemas/MarketVariantDetails"
- description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
market as a whole is about a single team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
market as a whole is about a single team.
deprecated: true
marketType:
description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
allOf:
- $ref: "#/components/schemas/MarketType"
- description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
rewards:
$ref: "#/components/schemas/MarketRewards"
MarketRewards:
type: object
title: MarketRewards
description: Reward schedule for a market.
required:
- schedule
properties:
current:
description: Active period at request time, or `null` if no rewards are accruing.
allOf:
- $ref: "#/components/schemas/RewardPeriod"
- description: Active period at request time, or `null` if no rewards are
accruing.
schedule:
type: array
description: Full schedule of past and future reward periods for this market.
items:
$ref: "#/components/schemas/RewardPeriod"
MarketStatus:
type: string
description: |-
Market lifecycle state, from registration through resolution.
`Removed` is a synthetic status reported for markets that have been
withdrawn, meaning it is not part of the normal lifecycle progression.
enum:
- REGISTERED
- PRICE_PROPOSED
- PRICE_DISPUTED
- PAUSED
- UNPAUSED
- RESOLVED
- REMOVED
MarketTradingStatus:
type: string
description: Trading status derived from market visibility and deletion state.
enum:
- OPEN
- MATCHING_NOT_ENABLED
- CANCEL_ONLY
- CLOSED
MarketType:
type: string
description: >-
Market type (DB `market.market_type_id` values as repr).
Classifies what kind of prediction an individual market represents,
independent of the category it belongs to. Works alongside
[`MarketVariant`]:
the variant describes how the category container renders; the market
type
describes the prediction mechanic of the individual market.
enum:
- SPORTS_MONEYLINE
- SPORTS_SPREADS
- SPORTS_TOTALS
- SPORTS_BOTH_TEAMS_TO_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_EXACT_SCORE
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_TEAM_TOTAL_CORNERS
- SPORTS_CORNERS_ODD_EVEN
- SPORTS_PLAYER_GOALS
- SPORTS_PLAYER_ASSISTS
- SPORTS_PLAYER_GOALS_PLUS_ASSISTS
- SPORTS_PLAYER_SHOTS
- SPORTS_PLAYER_SHOTS_ON_TARGET
- SPORTS_PLAYER_GOALKEEPER_SAVES
- SPORTS_TEAM_TO_ADVANCE
- SPORTS_EXTRA_TIME
- SPORTS_PENALTY_SHOOTOUT
- SPORTS_TEAM_TOTALS
- SPORTS_CHILD_MONEYLINE
- SPORTS_MAP_HANDICAP
- SPORTS_BOTH_TEAMS_TO_SCORE_FIRST_HALF
- SPORTS_BOTH_TEAMS_TO_SCORE_SECOND_HALF
- SPORTS_FIRST_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- SPORTS_FIRST_CORNER
- SPORTS_FIRST_HALF_TOTALS
- SPORTS_SECOND_HALF_TOTALS
- SPORTS_FIRST_HALF_TEAM_TOTALS
- SPORTS_SECOND_HALF_TEAM_TOTALS
- SPORTS_FIRST_BLOOD_GAME
- SPORTS_KILL_OVER_UNDER_GAME
- SPORTS_ROUND_HANDICAP
- SPORTS_ROUND_TOTALS
- SPORTS_ANYTIME_TOUCHDOWNS
- SPORTS_RACE_TO_POINTS
- SPORTS_ODD_EVEN
MarketVariant:
type: string
description: |-
Classifies the market template type.
Controls the UI layout and trading mechanics of a category. See also
[`MarketType`] which classifies individual markets within a category.
enum:
- DEFAULT
- SPORTS_MATCH
- CRYPTO_UP_DOWN
- TWEET_COUNT
- SPORTS_TEAM_MATCH
- SPORTS_NBA
- SPORTS_FIFA_WORLD_CUP
- SPORTS_EXACT_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_PROPS
- SPORTS_FIFA_FRIENDLIES
- ESPORTS_LOL
- ESPORTS_CS2
- ESPORTS_DOTA2
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- UP_DOWN
MarketVariantDetails:
type: object
title: MarketVariantDetails
description: >-
What a market is about, one key per kind of market.
Grouping by kind rather than discriminating on a type means a kind that
gains a payload is a new key, and one that loses it is a key removed,
with
nothing to keep in step. A market names the kinds that apply to it,
which
today is at most one.
Add a kind by adding a key. Each is filled independently, so a populator
sets its own key on the value already there rather than replacing it.
properties:
sports:
description: Set for a market of a sports category.
allOf:
- $ref: "#/components/schemas/SportsMarketDetails"
- description: Set for a market of a sports category.
MatchData:
type: object
title: MatchData
description: Match event data
required:
- market
- taker
- amountFilled
- priceExecuted
- makers
- transactionHash
- executedAt
properties:
market:
$ref: "#/components/schemas/Market"
taker:
$ref: "#/components/schemas/OrderFillData"
amountFilled:
type: string
priceExecuted:
type: string
makers:
type: array
items:
$ref: "#/components/schemas/OrderFillData"
transactionHash:
type: string
settlementId:
type: string
description: Identifier of the off-chain settlement that produced this match.
executedAt:
type: string
MatchesResponse:
type: object
title: MatchesResponse
description: Response for GET /v1/orders/matches
required:
- success
- data
properties:
success:
type: boolean
cursor:
type: string
data:
type: array
items:
$ref: "#/components/schemas/MatchData"
OrderFillData:
type: object
title: OrderFillData
description: Order fill data (for maker/taker in matches)
required:
- quoteType
- amount
- price
- outcome
- signer
- hash
- fee
properties:
quoteType:
$ref: "#/components/schemas/QuoteType"
amount:
type: string
price:
type: string
outcome:
$ref: "#/components/schemas/Outcome"
signer:
type: string
hash:
type: string
fee:
$ref: "#/components/schemas/Fee"
Outcome:
type: object
title: Outcome
description: Outcome data (from markets, positions, etc.)/// Outcome data (from
markets, positions, etc.)
required:
- name
- indexSet
- onChainId
properties:
name:
type: string
indexSet:
type: integer
format: int32
onChainId:
type: string
description: bigint string
status:
$ref: "#/components/schemas/OutcomeStatus"
bestBid:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes, or
poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is embedded
in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the next.
That is what caps the shared-cache TTL on those routes at seconds,
and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes,
or poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is
embedded in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the
next.
That is what caps the shared-cache TTL on those routes at
seconds, and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
bestAsk:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead, and
why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead,
and why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
outcome resolves to a specific team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
outcome resolves to a specific team.
deprecated: true
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/OutcomeVariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this outcome is about. Absent when it is about neither team.
allOf:
- $ref: "#/components/schemas/OutcomeVariantDetails"
- description: What this outcome is about. Absent when it is about neither team.
OutcomeStatus:
type: string
description: Resolution status of a market outcome.
enum:
- WON
- LOST
OutcomeVariantData:
type: object
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
oneOf:
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
discriminator:
propertyName: type
mapping:
SPORTS_NBA: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_LOL: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_CS2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_DOTA2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
OutcomeVariantData_SportsTeamOutcomeData:
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/SportsTeamOutcomeData"
OutcomeVariantDetails:
type: object
title: OutcomeVariantDetails
description: |-
What an outcome is about, one key per kind of market.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for an outcome that resolves to a team.
allOf:
- $ref: "#/components/schemas/SportsOutcomeDetails"
- description: Set for an outcome that resolves to a team.
PriceFeedProvider:
type: string
description: Provider of the price feed backing a crypto market.
enum:
- PYTH
- BINANCE
- CHAINLINK
- ATLAS
PriceLevel:
type: object
title: PriceLevel
required:
- price
- size
properties:
price:
type: number
format: double
description: In [0.0, 1.0].
size:
type: number
format: double
QuoteType:
type: string
description: "Quote type: ask or bid."
enum:
- Ask
- Bid
RewardPeriod:
type: object
title: RewardPeriod
description: A single span during which a market accrues rewards at a fixed
hourly rate.
required:
- hourlyRate
- startsAt
- endsAt
properties:
hourlyRate:
type: integer
format: int32
description: Reward points earned per hour while this period is active.
startsAt:
type: string
endsAt:
type: string
SportsDataProvider:
type: string
description: Sports data provider.
enum:
- PREDICT_SPORTS
- GRID
- POLYMARKET
SportsEventTeam:
type: object
title: SportsEventTeam
description: A sportsdata provider team as exposed in category variant data.
required:
- id
properties:
id:
type: integer
format: int64
description: Team identifier.
name:
type: string
abbreviation:
type: string
description: Team key abbreviation (e.g., "MIN", "SA"). Null when not available.
providerTeamId:
type: string
description: The team identifier used by the sportsdata provider. Null when no
game is linked.
isHome:
type: boolean
description: >-
Marks the side the fixture lists as home, which may be a neutral
venue. Null when the
provider does not say.
record:
description: Omitted when the provider sends none, or sends one whose format is
not known.
allOf:
- $ref: "#/components/schemas/SportsTeamRecord"
- description: Omitted when the provider sends none, or sends one whose format is
not known.
color:
type: string
description: >-
Team colour as a hex string from the provider. Omitted when the
provider does not send
one.
SportsFifaFriendliesVariantData:
type: object
title: SportsFifaFriendliesVariantData
description: Variant data for SPORTS_FIFA_FRIENDLIES categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsFifaWorldCupVariantData:
type: object
title: SportsFifaWorldCupVariantData
description: Variant data for SPORTS_FIFA_WORLD_CUP categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsMarketDetails:
type: object
title: SportsMarketDetails
description: What a market of a sports category is about.
properties:
provider:
description: The provider that links the team. Absent when no team is named.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team. Absent when no team is named.
team:
description: The team this market is about, when it is about one. .
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this market is about, when it is about one. .
line:
type: number
format: double
description: >-
The line this market is about: a total, a spread, or a player count.
TODO which side of a spread the line runs is not stated. It belongs
to
the market's `team`, so it needs the importer to record the subject:
polymarket orders a spread's outcomes subject first, and where the
feed
carries `marketMetadata.opticOddsTeamId` that agrees with it. Until
then
only the deprecated `variantData.spreadSide` says anything, and only
for
soccer, where a slug pattern happens to name the side.
gameNumber:
type: integer
format: int32
SportsNbaVariantData:
type: object
title: SportsNbaVariantData
description: Variant data for SPORTS_NBA categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsOutcomeDetails:
type: object
title: SportsOutcomeDetails
description: >-
What an outcome of a sports market is about.
Carries no type of its own, for the same reason as
[`SportsMarketDetails`].
required:
- provider
- team
properties:
provider:
description: The provider that links the team.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team.
team:
description: The team this outcome resolves to.
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this outcome resolves to.
SportsPropsMarketData:
type: object
title: SportsPropsMarketData
description: |-
Per-market data for `SPORTS_PROPS` prop markets.
Fields are market-type-specific: `spreadSide` is set for spread markets,
`line` is set for totals markets. Both-teams-to-score markets emit no
`variantData` of this shape.
properties:
spreadSide:
description: Which side of the parent match this spread market is on. Present
for spread markets only.
allOf:
- $ref: "#/components/schemas/TeamSide"
- description: Which side of the parent match this spread market is on. Present
for spread markets only.
line:
type: number
format: double
description: The line value for this totals market. Present for totals markets
only.
SportsTeamOutcomeData:
type: object
title: SportsTeamOutcomeData
description: Outcome variant data for sports markets where the outcome maps to a team.
required:
- provider
- team
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
team:
$ref: "#/components/schemas/SportsEventTeam"
SportsTeamRecord:
type: object
title: SportsTeamRecord
description: A team's win-loss record, in one shape whatever the sport or provider.
required:
- wins
- losses
properties:
wins:
type: integer
format: int32
losses:
type: integer
format: int32
draws:
type: integer
format: int32
description: Ties count as draws. Omitted where the sport's record has no draws,
as in basketball.
overtimeLosses:
type: integer
format: int32
description: Ice hockey losses after regulation, counted apart from `losses`.
Omitted elsewhere.
Team:
type: object
title: Team
description: Sports team identity.
required:
- id
- name
- abbreviation
- league
properties:
id:
type: integer
format: int64
name:
type: string
abbreviation:
type: string
alias:
type: string
league:
type: string
TeamSide:
type: string
description: Which side of a sports match a team plays on.
enum:
- HOME
- AWAY
TweetCountVariantData:
type: object
title: TweetCountVariantData
description: Variant data for TWEET_COUNT markets
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: X (Twitter) account username being tracked
tweetCount:
type: integer
format: int64
description: Current count of tweets within the category date range
VariantData:
type: object
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
oneOf:
- $ref: "#/components/schemas/VariantData_CryptoUpDownVariantData"
- $ref: "#/components/schemas/VariantData_TweetCountVariantData"
- $ref: "#/components/schemas/VariantData_SportsNbaVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
- $ref: "#/components/schemas/VariantData_SportsPropsMarketData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
discriminator:
propertyName: type
mapping:
CRYPTO_UP_DOWN: "#/components/schemas/VariantData_CryptoUpDownVariantData"
TWEET_COUNT: "#/components/schemas/VariantData_TweetCountVariantData"
SPORTS_NBA: "#/components/schemas/VariantData_SportsNbaVariantData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
SPORTS_PROPS: "#/components/schemas/VariantData_SportsPropsMarketData"
ESPORTS_LOL: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_CS2: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_DOTA2: "#/components/schemas/VariantData_EsportsVariantData"
VariantData_CryptoUpDownVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- CRYPTO_UP_DOWN
examples:
- CRYPTO_UP_DOWN
- $ref: "#/components/schemas/CryptoUpDownVariantData"
VariantData_EsportsVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/EsportsVariantData"
VariantData_SportsFifaFriendliesVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_FRIENDLIES
examples:
- SPORTS_FIFA_FRIENDLIES
- $ref: "#/components/schemas/SportsFifaFriendliesVariantData"
VariantData_SportsFifaWorldCupVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_WORLD_CUP
examples:
- SPORTS_FIFA_WORLD_CUP
- $ref: "#/components/schemas/SportsFifaWorldCupVariantData"
VariantData_SportsNbaVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_NBA
examples:
- SPORTS_NBA
- $ref: "#/components/schemas/SportsNbaVariantData"
VariantData_SportsPropsMarketData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_PROPS
examples:
- SPORTS_PROPS
- $ref: "#/components/schemas/SportsPropsMarketData"
VariantData_TweetCountVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- TWEET_COUNT
examples:
- TWEET_COUNT
- $ref: "#/components/schemas/TweetCountVariantData"
```
# Remove orders (/api/orders/remove-orders)
`POST https://api.predict.fun/v1/orders/remove`
Remove orders from the orderbook for the authenticated signer (max 100).
This will not cancel the order on-chain.
Requires JWT or project authentication.
```yaml
paths:
/orders/remove:
post:
tags:
- Orders
summary: Remove orders
description: |-
Remove orders from the orderbook for the authenticated signer (max 100).
This will not cancel the order on-chain.
Requires JWT or project authentication.
requestBody:
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/RemoveOrdersRequest"
required: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/RemoveOrdersResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
RemoveOrdersData:
type: object
title: RemoveOrdersData
description: Remove orders request data
required:
- ids
properties:
ids:
type: array
description: An array of order IDs (max 100)
items:
type: string
maxItems: 100
minItems: 1
RemoveOrdersRequest:
type: object
title: RemoveOrdersRequest
description: Remove orders request
required:
- data
properties:
data:
$ref: "#/components/schemas/RemoveOrdersData"
RemoveOrdersResponse:
type: object
title: RemoveOrdersResponse
description: Response for POST /v1/orders/remove
required:
- success
- removed
- noop
- rejected
properties:
success:
type: boolean
removed:
type: array
description: Orders that were successfully removed
items:
type: string
noop:
type: array
description: Orders that were not removed because they were already filled,
removed or cancelled
items:
type: string
rejected:
type: array
description: >-
Orders whose removal was rejected because they are still within
their
market's removal lock window. These may be retried after the order's
removal lock expires.
items:
type: string
```
# Remove orders by hash (/api/orders/remove-orders-by-hash)
`POST https://api.predict.fun/v1/orders/remove-by-hash`
Remove orders from the orderbook by their hash for the authenticated signer (max 100).
This will not cancel the order on-chain.
Requires JWT or project authentication.
```yaml
paths:
/orders/remove-by-hash:
post:
tags:
- Orders
summary: Remove orders by hash
description: >-
Remove orders from the orderbook by their hash for the authenticated
signer (max 100).
This will not cancel the order on-chain.
Requires JWT or project authentication.
requestBody:
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/RemoveOrdersByHashRequest"
required: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/RemoveOrdersResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
RemoveOrdersByHashData:
type: object
title: RemoveOrdersByHashData
description: Remove orders by hash request data
required:
- hashes
properties:
hashes:
type: array
description: An array of order hashes (0x-prefixed 32-byte hex strings, max 100)
items:
type: string
maxItems: 100
minItems: 1
RemoveOrdersByHashRequest:
type: object
title: RemoveOrdersByHashRequest
description: Remove orders by hash request
required:
- data
properties:
data:
$ref: "#/components/schemas/RemoveOrdersByHashData"
RemoveOrdersResponse:
type: object
title: RemoveOrdersResponse
description: Response for POST /v1/orders/remove
required:
- success
- removed
- noop
- rejected
properties:
success:
type: boolean
removed:
type: array
description: Orders that were successfully removed
items:
type: string
noop:
type: array
description: Orders that were not removed because they were already filled,
removed or cancelled
items:
type: string
rejected:
type: array
description: >-
Orders whose removal was rejected because they are still within
their
market's removal lock window. These may be retried after the order's
removal lock expires.
items:
type: string
```
# Get connected account (/api/account/get-connected-account)
`GET https://api.predict.fun/v1/account`
Get information for the connected user account. `points` are for
one season, `season` or the current season by default.
Requires JWT authentication.
```yaml
paths:
/account:
get:
tags:
- Account
summary: Get connected account
description: |-
Get information for the connected user account. `points` are for
one season, `season` or the current season by default.
Requires JWT authentication.
parameters:
- name: season
schema:
type: integer
format: int32
in: query
description: >-
The id of the points season to report `points` for, which must
exist. Defaults to the
current season, the latest one to have started.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/AccountResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
AccountData:
type: object
title: AccountData
description: Account data
required:
- name
- address
- referral
- points
properties:
name:
type: string
address:
type: string
imageUrl:
type: string
referral:
$ref: "#/components/schemas/ReferralInfo"
points:
$ref: "#/components/schemas/PointsInfo"
AccountResponse:
type: object
title: AccountResponse
description: Response for GET /v1/account
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/AccountData"
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
PointsInfo:
type: object
title: PointsInfo
description: Points information
required:
- total
properties:
total:
type: number
format: double
description: The user's points total for `season`.
rank:
type: integer
format: int32
description: |-
The user's rank within `season`, or null if they have no points
in it yet.
season:
type: integer
format: int32
description: |-
The season these points are for: the one requested, or the current
season. Null only before any season exists.
ReferralInfo:
type: object
title: ReferralInfo
description: Referral information
required:
- status
properties:
code:
type: string
status:
$ref: "#/components/schemas/ReferralStatus"
ReferralStatus:
type: string
description: Referral status
enum:
- LOCKED
- UNLOCKED
```
# Get account activity (/api/account/get-account-activity)
`GET https://api.predict.fun/v1/account/activity`
Get a paginated list of trading activity including orders, matches,
conversions, merges, and splits for the authenticated user.
The `occurredAfter` and `occurredBefore` filters are unix timestamps in
milliseconds and both bounds are exclusive: only events that occurred
strictly after `occurredAfter` and strictly before `occurredBefore` are
returned.
Requires JWT authentication.
```yaml
paths:
/account/activity:
get:
tags:
- Account
summary: Get account activity
description: |-
Get a paginated list of trading activity including orders, matches,
conversions, merges, and splits for the authenticated user.
The `occurredAfter` and `occurredBefore` filters are unix timestamps in
milliseconds and both bounds are exclusive: only events that occurred
strictly after `occurredAfter` and strictly before `occurredBefore` are
returned.
Requires JWT authentication.
parameters:
- name: first
schema:
type: integer
format: int32
in: query
description: Page size, from 1 to 150. Defaults to 50. A value outside that
range is clamped.
required: false
deprecated: false
explode: true
- name: after
schema:
type: string
maxLength: 1024
in: query
description: The `cursor` from the previous page, to get the next one.
required: false
deprecated: false
explode: true
- name: eventTypes
schema:
type: array
items:
$ref: "#/components/schemas/ActivityEventName"
in: query
description: Filter by event types (comma-separated or repeated)
required: false
deprecated: false
explode: true
- name: occurredAfter
schema:
type: integer
format: int64
in: query
description: Only include events that occurred strictly after this unix
timestamp (milliseconds)
required: false
deprecated: false
explode: true
- name: occurredBefore
schema:
type: integer
format: int64
in: query
description: Only include events that occurred strictly before this unix
timestamp (milliseconds)
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ActivityResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
ActivityEvent:
type: object
title: ActivityEvent
description: Activity event data
required:
- name
- createdAt
- market
properties:
name:
$ref: "#/components/schemas/ActivityEventName"
createdAt:
type: string
transactionHash:
type: string
amountFilled:
type: string
priceExecuted:
type: string
order:
$ref: "#/components/schemas/ActivityOrderData"
market:
$ref: "#/components/schemas/Market"
outcome:
$ref: "#/components/schemas/Outcome"
ActivityEventName:
type: string
description: Activity event name
enum:
- CREATE
- MATCH_SUCCESS
- CANCEL
- INVALIDATE
- NO_MARKET_MATCH
- EXPIRED
- REJECTED_POST_ONLY
- CONVERT
- MERGE
- SPLIT
- REDEEM
- REFUND
ActivityOrderData:
type: object
title: ActivityOrderData
description: Order data in activity events
required:
- quoteType
- amount
- price
properties:
quoteType:
$ref: "#/components/schemas/QuoteType"
amount:
type: string
price:
type: string
fee:
description: The fee for the order, only present for MATCH_SUCCESS events
allOf:
- $ref: "#/components/schemas/Fee"
- description: The fee for the order, only present for MATCH_SUCCESS events
ActivityResponse:
type: object
title: ActivityResponse
description: Response for GET /v1/account/activity and GET
/v1/account/{address}/activity
required:
- success
- data
properties:
success:
type: boolean
cursor:
type: string
data:
type: array
items:
$ref: "#/components/schemas/ActivityEvent"
CryptoUpDownVariantData:
type: object
title: CryptoUpDownVariantData
description: Variant data for CRYPTO_UP_DOWN markets
required:
- priceFeedProvider
properties:
priceFeedProvider:
$ref: "#/components/schemas/PriceFeedProvider"
startPrice:
type: number
format: double
description: Starting price, null before market start
endPrice:
type: number
format: double
description: Ending price from Pyth oracle, null if not yet resolved
priceFeedId:
type: string
description: Pyth oracle price feed identifier
priceFeedSymbol:
type: string
description: Price feed symbol (e.g. "BTCUSDT" for Binance, "BTC_USD" for Pyth)
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
EsportsVariantData:
type: object
title: EsportsVariantData
description: Variant data for esports match categories sourced from Grid.gg.
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked series yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
Fee:
type: object
title: Fee
description: Fee information
required:
- amount
- type
properties:
amount:
type: string
description: The fee amount in wei
type:
description: The fee side, either COLLATERAL (e.g. USDT) or SHARES
allOf:
- $ref: "#/components/schemas/FeeType"
- description: The fee side, either COLLATERAL (e.g. USDT) or SHARES
FeeType:
type: string
description: Fee type
enum:
- COLLATERAL
- SHARES
Market:
type: object
title: Market
description: Full market data as returned by the API
required:
- id
- imageUrl
- title
- question
- description
- tradingStatus
- status
- isVisible
- isNegRisk
- isYieldBearing
- feeRateBps
- makerFeeBps
- oracleQuestionId
- conditionId
- resolverAddress
- outcomes
- spreadThreshold
- shareThreshold
- isBoosted
- polymarketConditionIds
- categorySlug
- createdAt
- decimalPrecision
- marketVariant
- rewards
properties:
id:
type: integer
format: int64
imageUrl:
type: string
title:
type: string
question:
type: string
description:
type: string
tradingStatus:
$ref: "#/components/schemas/MarketTradingStatus"
status:
$ref: "#/components/schemas/MarketStatus"
isVisible:
type: boolean
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
feeRateBps:
type: integer
format: int32
description: Taker fee in basis points, charged on each matched trade.
makerFeeBps:
type: integer
format: int32
description: |-
Maker fee in basis points. Always `0`: no market charges makers.
Defaults on decode so market entries cached before the field existed
still decode rather than reading as misses, and the default is the
only value it takes.
resolution:
$ref: "#/components/schemas/Outcome"
oracleQuestionId:
type: string
conditionId:
type: string
resolverAddress:
type: string
outcomes:
type: array
items:
$ref: "#/components/schemas/Outcome"
questionIndex:
type: integer
format: int32
spreadThreshold:
type: number
format: double
shareThreshold:
type: integer
format: int32
isBoosted:
type: boolean
boostStartsAt:
type: string
boostEndsAt:
type: string
polymarketConditionIds:
type: array
items:
type: string
kalshiMarketTicker:
type: string
categorySlug:
type: string
seriesSlug:
type: string
description: |-
Slug of the recurring series this market's category is a round of,
e.g. `"btc-updown-5m"`. Absent when it is not a round of one. The
series and its next rounds are at `GET /v1/series/{slug}`.
createdAt:
type: string
decimalPrecision:
type: integer
format: int32
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
allOf:
- $ref: "#/components/schemas/MarketVariantDetails"
- description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
market as a whole is about a single team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
market as a whole is about a single team.
deprecated: true
marketType:
description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
allOf:
- $ref: "#/components/schemas/MarketType"
- description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
rewards:
$ref: "#/components/schemas/MarketRewards"
MarketRewards:
type: object
title: MarketRewards
description: Reward schedule for a market.
required:
- schedule
properties:
current:
description: Active period at request time, or `null` if no rewards are accruing.
allOf:
- $ref: "#/components/schemas/RewardPeriod"
- description: Active period at request time, or `null` if no rewards are
accruing.
schedule:
type: array
description: Full schedule of past and future reward periods for this market.
items:
$ref: "#/components/schemas/RewardPeriod"
MarketStatus:
type: string
description: |-
Market lifecycle state, from registration through resolution.
`Removed` is a synthetic status reported for markets that have been
withdrawn, meaning it is not part of the normal lifecycle progression.
enum:
- REGISTERED
- PRICE_PROPOSED
- PRICE_DISPUTED
- PAUSED
- UNPAUSED
- RESOLVED
- REMOVED
MarketTradingStatus:
type: string
description: Trading status derived from market visibility and deletion state.
enum:
- OPEN
- MATCHING_NOT_ENABLED
- CANCEL_ONLY
- CLOSED
MarketType:
type: string
description: >-
Market type (DB `market.market_type_id` values as repr).
Classifies what kind of prediction an individual market represents,
independent of the category it belongs to. Works alongside
[`MarketVariant`]:
the variant describes how the category container renders; the market
type
describes the prediction mechanic of the individual market.
enum:
- SPORTS_MONEYLINE
- SPORTS_SPREADS
- SPORTS_TOTALS
- SPORTS_BOTH_TEAMS_TO_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_EXACT_SCORE
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_TEAM_TOTAL_CORNERS
- SPORTS_CORNERS_ODD_EVEN
- SPORTS_PLAYER_GOALS
- SPORTS_PLAYER_ASSISTS
- SPORTS_PLAYER_GOALS_PLUS_ASSISTS
- SPORTS_PLAYER_SHOTS
- SPORTS_PLAYER_SHOTS_ON_TARGET
- SPORTS_PLAYER_GOALKEEPER_SAVES
- SPORTS_TEAM_TO_ADVANCE
- SPORTS_EXTRA_TIME
- SPORTS_PENALTY_SHOOTOUT
- SPORTS_TEAM_TOTALS
- SPORTS_CHILD_MONEYLINE
- SPORTS_MAP_HANDICAP
- SPORTS_BOTH_TEAMS_TO_SCORE_FIRST_HALF
- SPORTS_BOTH_TEAMS_TO_SCORE_SECOND_HALF
- SPORTS_FIRST_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- SPORTS_FIRST_CORNER
- SPORTS_FIRST_HALF_TOTALS
- SPORTS_SECOND_HALF_TOTALS
- SPORTS_FIRST_HALF_TEAM_TOTALS
- SPORTS_SECOND_HALF_TEAM_TOTALS
- SPORTS_FIRST_BLOOD_GAME
- SPORTS_KILL_OVER_UNDER_GAME
- SPORTS_ROUND_HANDICAP
- SPORTS_ROUND_TOTALS
- SPORTS_ANYTIME_TOUCHDOWNS
- SPORTS_RACE_TO_POINTS
- SPORTS_ODD_EVEN
MarketVariant:
type: string
description: |-
Classifies the market template type.
Controls the UI layout and trading mechanics of a category. See also
[`MarketType`] which classifies individual markets within a category.
enum:
- DEFAULT
- SPORTS_MATCH
- CRYPTO_UP_DOWN
- TWEET_COUNT
- SPORTS_TEAM_MATCH
- SPORTS_NBA
- SPORTS_FIFA_WORLD_CUP
- SPORTS_EXACT_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_PROPS
- SPORTS_FIFA_FRIENDLIES
- ESPORTS_LOL
- ESPORTS_CS2
- ESPORTS_DOTA2
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- UP_DOWN
MarketVariantDetails:
type: object
title: MarketVariantDetails
description: >-
What a market is about, one key per kind of market.
Grouping by kind rather than discriminating on a type means a kind that
gains a payload is a new key, and one that loses it is a key removed,
with
nothing to keep in step. A market names the kinds that apply to it,
which
today is at most one.
Add a kind by adding a key. Each is filled independently, so a populator
sets its own key on the value already there rather than replacing it.
properties:
sports:
description: Set for a market of a sports category.
allOf:
- $ref: "#/components/schemas/SportsMarketDetails"
- description: Set for a market of a sports category.
Outcome:
type: object
title: Outcome
description: Outcome data (from markets, positions, etc.)/// Outcome data (from
markets, positions, etc.)
required:
- name
- indexSet
- onChainId
properties:
name:
type: string
indexSet:
type: integer
format: int32
onChainId:
type: string
description: bigint string
status:
$ref: "#/components/schemas/OutcomeStatus"
bestBid:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes, or
poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is embedded
in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the next.
That is what caps the shared-cache TTL on those routes at seconds,
and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes,
or poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is
embedded in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the
next.
That is what caps the shared-cache TTL on those routes at
seconds, and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
bestAsk:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead, and
why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead,
and why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
outcome resolves to a specific team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
outcome resolves to a specific team.
deprecated: true
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/OutcomeVariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this outcome is about. Absent when it is about neither team.
allOf:
- $ref: "#/components/schemas/OutcomeVariantDetails"
- description: What this outcome is about. Absent when it is about neither team.
OutcomeStatus:
type: string
description: Resolution status of a market outcome.
enum:
- WON
- LOST
OutcomeVariantData:
type: object
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
oneOf:
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
discriminator:
propertyName: type
mapping:
SPORTS_NBA: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_LOL: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_CS2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_DOTA2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
OutcomeVariantData_SportsTeamOutcomeData:
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/SportsTeamOutcomeData"
OutcomeVariantDetails:
type: object
title: OutcomeVariantDetails
description: |-
What an outcome is about, one key per kind of market.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for an outcome that resolves to a team.
allOf:
- $ref: "#/components/schemas/SportsOutcomeDetails"
- description: Set for an outcome that resolves to a team.
PriceFeedProvider:
type: string
description: Provider of the price feed backing a crypto market.
enum:
- PYTH
- BINANCE
- CHAINLINK
- ATLAS
PriceLevel:
type: object
title: PriceLevel
required:
- price
- size
properties:
price:
type: number
format: double
description: In [0.0, 1.0].
size:
type: number
format: double
QuoteType:
type: string
description: "Quote type: ask or bid."
enum:
- Ask
- Bid
RewardPeriod:
type: object
title: RewardPeriod
description: A single span during which a market accrues rewards at a fixed
hourly rate.
required:
- hourlyRate
- startsAt
- endsAt
properties:
hourlyRate:
type: integer
format: int32
description: Reward points earned per hour while this period is active.
startsAt:
type: string
endsAt:
type: string
SportsDataProvider:
type: string
description: Sports data provider.
enum:
- PREDICT_SPORTS
- GRID
- POLYMARKET
SportsEventTeam:
type: object
title: SportsEventTeam
description: A sportsdata provider team as exposed in category variant data.
required:
- id
properties:
id:
type: integer
format: int64
description: Team identifier.
name:
type: string
abbreviation:
type: string
description: Team key abbreviation (e.g., "MIN", "SA"). Null when not available.
providerTeamId:
type: string
description: The team identifier used by the sportsdata provider. Null when no
game is linked.
isHome:
type: boolean
description: >-
Marks the side the fixture lists as home, which may be a neutral
venue. Null when the
provider does not say.
record:
description: Omitted when the provider sends none, or sends one whose format is
not known.
allOf:
- $ref: "#/components/schemas/SportsTeamRecord"
- description: Omitted when the provider sends none, or sends one whose format is
not known.
color:
type: string
description: >-
Team colour as a hex string from the provider. Omitted when the
provider does not send
one.
SportsFifaFriendliesVariantData:
type: object
title: SportsFifaFriendliesVariantData
description: Variant data for SPORTS_FIFA_FRIENDLIES categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsFifaWorldCupVariantData:
type: object
title: SportsFifaWorldCupVariantData
description: Variant data for SPORTS_FIFA_WORLD_CUP categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsMarketDetails:
type: object
title: SportsMarketDetails
description: What a market of a sports category is about.
properties:
provider:
description: The provider that links the team. Absent when no team is named.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team. Absent when no team is named.
team:
description: The team this market is about, when it is about one. .
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this market is about, when it is about one. .
line:
type: number
format: double
description: >-
The line this market is about: a total, a spread, or a player count.
TODO which side of a spread the line runs is not stated. It belongs
to
the market's `team`, so it needs the importer to record the subject:
polymarket orders a spread's outcomes subject first, and where the
feed
carries `marketMetadata.opticOddsTeamId` that agrees with it. Until
then
only the deprecated `variantData.spreadSide` says anything, and only
for
soccer, where a slug pattern happens to name the side.
gameNumber:
type: integer
format: int32
SportsNbaVariantData:
type: object
title: SportsNbaVariantData
description: Variant data for SPORTS_NBA categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsOutcomeDetails:
type: object
title: SportsOutcomeDetails
description: >-
What an outcome of a sports market is about.
Carries no type of its own, for the same reason as
[`SportsMarketDetails`].
required:
- provider
- team
properties:
provider:
description: The provider that links the team.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team.
team:
description: The team this outcome resolves to.
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this outcome resolves to.
SportsPropsMarketData:
type: object
title: SportsPropsMarketData
description: |-
Per-market data for `SPORTS_PROPS` prop markets.
Fields are market-type-specific: `spreadSide` is set for spread markets,
`line` is set for totals markets. Both-teams-to-score markets emit no
`variantData` of this shape.
properties:
spreadSide:
description: Which side of the parent match this spread market is on. Present
for spread markets only.
allOf:
- $ref: "#/components/schemas/TeamSide"
- description: Which side of the parent match this spread market is on. Present
for spread markets only.
line:
type: number
format: double
description: The line value for this totals market. Present for totals markets
only.
SportsTeamOutcomeData:
type: object
title: SportsTeamOutcomeData
description: Outcome variant data for sports markets where the outcome maps to a team.
required:
- provider
- team
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
team:
$ref: "#/components/schemas/SportsEventTeam"
SportsTeamRecord:
type: object
title: SportsTeamRecord
description: A team's win-loss record, in one shape whatever the sport or provider.
required:
- wins
- losses
properties:
wins:
type: integer
format: int32
losses:
type: integer
format: int32
draws:
type: integer
format: int32
description: Ties count as draws. Omitted where the sport's record has no draws,
as in basketball.
overtimeLosses:
type: integer
format: int32
description: Ice hockey losses after regulation, counted apart from `losses`.
Omitted elsewhere.
Team:
type: object
title: Team
description: Sports team identity.
required:
- id
- name
- abbreviation
- league
properties:
id:
type: integer
format: int64
name:
type: string
abbreviation:
type: string
alias:
type: string
league:
type: string
TeamSide:
type: string
description: Which side of a sports match a team plays on.
enum:
- HOME
- AWAY
TweetCountVariantData:
type: object
title: TweetCountVariantData
description: Variant data for TWEET_COUNT markets
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: X (Twitter) account username being tracked
tweetCount:
type: integer
format: int64
description: Current count of tweets within the category date range
VariantData:
type: object
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
oneOf:
- $ref: "#/components/schemas/VariantData_CryptoUpDownVariantData"
- $ref: "#/components/schemas/VariantData_TweetCountVariantData"
- $ref: "#/components/schemas/VariantData_SportsNbaVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
- $ref: "#/components/schemas/VariantData_SportsPropsMarketData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
discriminator:
propertyName: type
mapping:
CRYPTO_UP_DOWN: "#/components/schemas/VariantData_CryptoUpDownVariantData"
TWEET_COUNT: "#/components/schemas/VariantData_TweetCountVariantData"
SPORTS_NBA: "#/components/schemas/VariantData_SportsNbaVariantData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
SPORTS_PROPS: "#/components/schemas/VariantData_SportsPropsMarketData"
ESPORTS_LOL: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_CS2: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_DOTA2: "#/components/schemas/VariantData_EsportsVariantData"
VariantData_CryptoUpDownVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- CRYPTO_UP_DOWN
examples:
- CRYPTO_UP_DOWN
- $ref: "#/components/schemas/CryptoUpDownVariantData"
VariantData_EsportsVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/EsportsVariantData"
VariantData_SportsFifaFriendliesVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_FRIENDLIES
examples:
- SPORTS_FIFA_FRIENDLIES
- $ref: "#/components/schemas/SportsFifaFriendliesVariantData"
VariantData_SportsFifaWorldCupVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_WORLD_CUP
examples:
- SPORTS_FIFA_WORLD_CUP
- $ref: "#/components/schemas/SportsFifaWorldCupVariantData"
VariantData_SportsNbaVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_NBA
examples:
- SPORTS_NBA
- $ref: "#/components/schemas/SportsNbaVariantData"
VariantData_SportsPropsMarketData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_PROPS
examples:
- SPORTS_PROPS
- $ref: "#/components/schemas/SportsPropsMarketData"
VariantData_TweetCountVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- TWEET_COUNT
examples:
- TWEET_COUNT
- $ref: "#/components/schemas/TweetCountVariantData"
```
# Get weekly points breakdown (/api/account/get-weekly-points-breakdown)
`GET https://api.predict.fun/v1/account/points/weekly`
Returns the authenticated user's per-week points history for one
season, `season` or the current season by default, alongside each
week's points budget. Entries are ordered chronologically from week 1
of the season.
The current in-progress round is included with `calculated: false`
until it closes.
Requires JWT authentication.
```yaml
paths:
/account/points/weekly:
get:
tags:
- Account
summary: Get weekly points breakdown
description: |-
Returns the authenticated user's per-week points history for one
season, `season` or the current season by default, alongside each
week's points budget. Entries are ordered chronologically from week 1
of the season.
The current in-progress round is included with `calculated: false`
until it closes.
Requires JWT authentication.
parameters:
- name: season
schema:
type: integer
format: int32
in: query
description: >-
The id of the points season to list the weeks of, which must exist.
Defaults to the
current season, the latest one to have started.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/WeeklyPointsResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
WeeklyPointsEntry:
type: object
title: WeeklyPointsEntry
description: A single week of points data
required:
- week
- startTime
- endTime
- userPoints
- userReferralPoints
- allocationAmount
- calculated
properties:
week:
type: integer
format: int32
description: Week number within the season, starting at 1.
startTime:
type: string
description: Round start time, RFC3339.
endTime:
type: string
description: Round end time, RFC3339.
userPoints:
type: number
format: double
description: |-
Points earned by the authenticated user that week, from every
source, as in the account's total.
`0` until the weekly calculation is finalised, check `calculated`
to disambiguate from a real zero.
userReferralPoints:
type: number
format: double
description: Subset of points attributable to referral sources.
allocationAmount:
type: integer
format: int32
description: The budgeted point allocation for the round.
calculated:
type: boolean
description: |-
Whether the weekly calculation has been finalised.
When `false`, the point fields will be `0`, as the round is still
in-progress / "TBD". Distribution happens on a near-weekly cadence.
WeeklyPointsResponse:
type: object
title: WeeklyPointsResponse
description: Response for GET /v1/account/points/weekly
required:
- success
- data
properties:
success:
type: boolean
data:
type: array
items:
$ref: "#/components/schemas/WeeklyPointsEntry"
```
# Get account by address (/api/account/get-account-by-address)
`GET https://api.predict.fun/v1/account/{address}`
Get the public profile of any wallet address: its display name, its
profile image once it has passed moderation, and its leaderboard
points and rank. A wallet that never set up a profile has a `null`
name. An address with no wallet returns 404.
```yaml
paths:
/account/{address}:
get:
tags:
- Account
summary: Get account by address
description: |-
Get the public profile of any wallet address: its display name, its
profile image once it has passed moderation, and its leaderboard
points and rank. A wallet that never set up a profile has a `null`
name. An address with no wallet returns 404.
parameters:
- name: address
schema:
type: string
in: path
description: The wallet's address. For a Predict account, use the account's
address.
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/PublicAccountResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
PointsInfo:
type: object
title: PointsInfo
description: Points information
required:
- total
properties:
total:
type: number
format: double
description: The user's points total for `season`.
rank:
type: integer
format: int32
description: |-
The user's rank within `season`, or null if they have no points
in it yet.
season:
type: integer
format: int32
description: |-
The season these points are for: the one requested, or the current
season. Null only before any season exists.
PublicAccountData:
type: object
title: PublicAccountData
description: The public profile of a wallet
required:
- address
- points
properties:
name:
type: string
description: The name the wallet set on its profile. `null` when it has none.
address:
type: string
imageUrl:
type: string
description: The profile image, once it has passed moderation.
points:
$ref: "#/components/schemas/PointsInfo"
PublicAccountResponse:
type: object
title: PublicAccountResponse
description: Response for GET /v1/account/{address}
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/PublicAccountData"
```
# Get account activity by address (/api/account/get-account-activity-by-address)
`GET https://api.predict.fun/v1/account/{address}/activity`
Get a paginated list of the conversions, merges, splits, redemptions
and refunds of any wallet address. Order events are not included. The
fills of an address are available from `GET /v1/orders/matches` with
`signerAddress`. An address with no account returns an empty list.
The `occurredAfter` and `occurredBefore` filters are unix timestamps in
milliseconds and both bounds are exclusive: only events that occurred
strictly after `occurredAfter` and strictly before `occurredBefore` are
returned.
```yaml
paths:
/account/{address}/activity:
get:
tags:
- Account
summary: Get account activity by address
description: |-
Get a paginated list of the conversions, merges, splits, redemptions
and refunds of any wallet address. Order events are not included. The
fills of an address are available from `GET /v1/orders/matches` with
`signerAddress`. An address with no account returns an empty list.
The `occurredAfter` and `occurredBefore` filters are unix timestamps in
milliseconds and both bounds are exclusive: only events that occurred
strictly after `occurredAfter` and strictly before `occurredBefore` are
returned.
parameters:
- name: address
schema:
type: string
in: path
description: The wallet's address. For a Predict account, use the account's
address.
required: true
deprecated: false
explode: true
- name: first
schema:
type: integer
format: int32
in: query
description: Page size, from 1 to 150. Defaults to 50. A value outside that
range is clamped.
required: false
deprecated: false
explode: true
- name: after
schema:
type: string
maxLength: 1024
in: query
description: The `cursor` from the previous page, to get the next one.
required: false
deprecated: false
explode: true
- name: eventTypes
schema:
type: array
items:
$ref: "#/components/schemas/PublicActivityEventName"
in: query
description: Filter by event types (comma-separated or repeated)
required: false
deprecated: false
explode: true
- name: occurredAfter
schema:
type: integer
format: int64
in: query
description: Only include events that occurred strictly after this unix
timestamp (milliseconds)
required: false
deprecated: false
explode: true
- name: occurredBefore
schema:
type: integer
format: int64
in: query
description: Only include events that occurred strictly before this unix
timestamp (milliseconds)
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ActivityResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ActivityEvent:
type: object
title: ActivityEvent
description: Activity event data
required:
- name
- createdAt
- market
properties:
name:
$ref: "#/components/schemas/ActivityEventName"
createdAt:
type: string
transactionHash:
type: string
amountFilled:
type: string
priceExecuted:
type: string
order:
$ref: "#/components/schemas/ActivityOrderData"
market:
$ref: "#/components/schemas/Market"
outcome:
$ref: "#/components/schemas/Outcome"
ActivityEventName:
type: string
description: Activity event name
enum:
- CREATE
- MATCH_SUCCESS
- CANCEL
- INVALIDATE
- NO_MARKET_MATCH
- EXPIRED
- REJECTED_POST_ONLY
- CONVERT
- MERGE
- SPLIT
- REDEEM
- REFUND
ActivityOrderData:
type: object
title: ActivityOrderData
description: Order data in activity events
required:
- quoteType
- amount
- price
properties:
quoteType:
$ref: "#/components/schemas/QuoteType"
amount:
type: string
price:
type: string
fee:
description: The fee for the order, only present for MATCH_SUCCESS events
allOf:
- $ref: "#/components/schemas/Fee"
- description: The fee for the order, only present for MATCH_SUCCESS events
ActivityResponse:
type: object
title: ActivityResponse
description: Response for GET /v1/account/activity and GET
/v1/account/{address}/activity
required:
- success
- data
properties:
success:
type: boolean
cursor:
type: string
data:
type: array
items:
$ref: "#/components/schemas/ActivityEvent"
CryptoUpDownVariantData:
type: object
title: CryptoUpDownVariantData
description: Variant data for CRYPTO_UP_DOWN markets
required:
- priceFeedProvider
properties:
priceFeedProvider:
$ref: "#/components/schemas/PriceFeedProvider"
startPrice:
type: number
format: double
description: Starting price, null before market start
endPrice:
type: number
format: double
description: Ending price from Pyth oracle, null if not yet resolved
priceFeedId:
type: string
description: Pyth oracle price feed identifier
priceFeedSymbol:
type: string
description: Price feed symbol (e.g. "BTCUSDT" for Binance, "BTC_USD" for Pyth)
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
EsportsVariantData:
type: object
title: EsportsVariantData
description: Variant data for esports match categories sourced from Grid.gg.
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked series yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
Fee:
type: object
title: Fee
description: Fee information
required:
- amount
- type
properties:
amount:
type: string
description: The fee amount in wei
type:
description: The fee side, either COLLATERAL (e.g. USDT) or SHARES
allOf:
- $ref: "#/components/schemas/FeeType"
- description: The fee side, either COLLATERAL (e.g. USDT) or SHARES
FeeType:
type: string
description: Fee type
enum:
- COLLATERAL
- SHARES
Market:
type: object
title: Market
description: Full market data as returned by the API
required:
- id
- imageUrl
- title
- question
- description
- tradingStatus
- status
- isVisible
- isNegRisk
- isYieldBearing
- feeRateBps
- makerFeeBps
- oracleQuestionId
- conditionId
- resolverAddress
- outcomes
- spreadThreshold
- shareThreshold
- isBoosted
- polymarketConditionIds
- categorySlug
- createdAt
- decimalPrecision
- marketVariant
- rewards
properties:
id:
type: integer
format: int64
imageUrl:
type: string
title:
type: string
question:
type: string
description:
type: string
tradingStatus:
$ref: "#/components/schemas/MarketTradingStatus"
status:
$ref: "#/components/schemas/MarketStatus"
isVisible:
type: boolean
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
feeRateBps:
type: integer
format: int32
description: Taker fee in basis points, charged on each matched trade.
makerFeeBps:
type: integer
format: int32
description: |-
Maker fee in basis points. Always `0`: no market charges makers.
Defaults on decode so market entries cached before the field existed
still decode rather than reading as misses, and the default is the
only value it takes.
resolution:
$ref: "#/components/schemas/Outcome"
oracleQuestionId:
type: string
conditionId:
type: string
resolverAddress:
type: string
outcomes:
type: array
items:
$ref: "#/components/schemas/Outcome"
questionIndex:
type: integer
format: int32
spreadThreshold:
type: number
format: double
shareThreshold:
type: integer
format: int32
isBoosted:
type: boolean
boostStartsAt:
type: string
boostEndsAt:
type: string
polymarketConditionIds:
type: array
items:
type: string
kalshiMarketTicker:
type: string
categorySlug:
type: string
seriesSlug:
type: string
description: |-
Slug of the recurring series this market's category is a round of,
e.g. `"btc-updown-5m"`. Absent when it is not a round of one. The
series and its next rounds are at `GET /v1/series/{slug}`.
createdAt:
type: string
decimalPrecision:
type: integer
format: int32
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
allOf:
- $ref: "#/components/schemas/MarketVariantDetails"
- description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
market as a whole is about a single team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
market as a whole is about a single team.
deprecated: true
marketType:
description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
allOf:
- $ref: "#/components/schemas/MarketType"
- description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
rewards:
$ref: "#/components/schemas/MarketRewards"
MarketRewards:
type: object
title: MarketRewards
description: Reward schedule for a market.
required:
- schedule
properties:
current:
description: Active period at request time, or `null` if no rewards are accruing.
allOf:
- $ref: "#/components/schemas/RewardPeriod"
- description: Active period at request time, or `null` if no rewards are
accruing.
schedule:
type: array
description: Full schedule of past and future reward periods for this market.
items:
$ref: "#/components/schemas/RewardPeriod"
MarketStatus:
type: string
description: |-
Market lifecycle state, from registration through resolution.
`Removed` is a synthetic status reported for markets that have been
withdrawn, meaning it is not part of the normal lifecycle progression.
enum:
- REGISTERED
- PRICE_PROPOSED
- PRICE_DISPUTED
- PAUSED
- UNPAUSED
- RESOLVED
- REMOVED
MarketTradingStatus:
type: string
description: Trading status derived from market visibility and deletion state.
enum:
- OPEN
- MATCHING_NOT_ENABLED
- CANCEL_ONLY
- CLOSED
MarketType:
type: string
description: >-
Market type (DB `market.market_type_id` values as repr).
Classifies what kind of prediction an individual market represents,
independent of the category it belongs to. Works alongside
[`MarketVariant`]:
the variant describes how the category container renders; the market
type
describes the prediction mechanic of the individual market.
enum:
- SPORTS_MONEYLINE
- SPORTS_SPREADS
- SPORTS_TOTALS
- SPORTS_BOTH_TEAMS_TO_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_EXACT_SCORE
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_TEAM_TOTAL_CORNERS
- SPORTS_CORNERS_ODD_EVEN
- SPORTS_PLAYER_GOALS
- SPORTS_PLAYER_ASSISTS
- SPORTS_PLAYER_GOALS_PLUS_ASSISTS
- SPORTS_PLAYER_SHOTS
- SPORTS_PLAYER_SHOTS_ON_TARGET
- SPORTS_PLAYER_GOALKEEPER_SAVES
- SPORTS_TEAM_TO_ADVANCE
- SPORTS_EXTRA_TIME
- SPORTS_PENALTY_SHOOTOUT
- SPORTS_TEAM_TOTALS
- SPORTS_CHILD_MONEYLINE
- SPORTS_MAP_HANDICAP
- SPORTS_BOTH_TEAMS_TO_SCORE_FIRST_HALF
- SPORTS_BOTH_TEAMS_TO_SCORE_SECOND_HALF
- SPORTS_FIRST_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- SPORTS_FIRST_CORNER
- SPORTS_FIRST_HALF_TOTALS
- SPORTS_SECOND_HALF_TOTALS
- SPORTS_FIRST_HALF_TEAM_TOTALS
- SPORTS_SECOND_HALF_TEAM_TOTALS
- SPORTS_FIRST_BLOOD_GAME
- SPORTS_KILL_OVER_UNDER_GAME
- SPORTS_ROUND_HANDICAP
- SPORTS_ROUND_TOTALS
- SPORTS_ANYTIME_TOUCHDOWNS
- SPORTS_RACE_TO_POINTS
- SPORTS_ODD_EVEN
MarketVariant:
type: string
description: |-
Classifies the market template type.
Controls the UI layout and trading mechanics of a category. See also
[`MarketType`] which classifies individual markets within a category.
enum:
- DEFAULT
- SPORTS_MATCH
- CRYPTO_UP_DOWN
- TWEET_COUNT
- SPORTS_TEAM_MATCH
- SPORTS_NBA
- SPORTS_FIFA_WORLD_CUP
- SPORTS_EXACT_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_PROPS
- SPORTS_FIFA_FRIENDLIES
- ESPORTS_LOL
- ESPORTS_CS2
- ESPORTS_DOTA2
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- UP_DOWN
MarketVariantDetails:
type: object
title: MarketVariantDetails
description: >-
What a market is about, one key per kind of market.
Grouping by kind rather than discriminating on a type means a kind that
gains a payload is a new key, and one that loses it is a key removed,
with
nothing to keep in step. A market names the kinds that apply to it,
which
today is at most one.
Add a kind by adding a key. Each is filled independently, so a populator
sets its own key on the value already there rather than replacing it.
properties:
sports:
description: Set for a market of a sports category.
allOf:
- $ref: "#/components/schemas/SportsMarketDetails"
- description: Set for a market of a sports category.
Outcome:
type: object
title: Outcome
description: Outcome data (from markets, positions, etc.)/// Outcome data (from
markets, positions, etc.)
required:
- name
- indexSet
- onChainId
properties:
name:
type: string
indexSet:
type: integer
format: int32
onChainId:
type: string
description: bigint string
status:
$ref: "#/components/schemas/OutcomeStatus"
bestBid:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes, or
poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is embedded
in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the next.
That is what caps the shared-cache TTL on those routes at seconds,
and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes,
or poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is
embedded in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the
next.
That is what caps the shared-cache TTL on those routes at
seconds, and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
bestAsk:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead, and
why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead,
and why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
outcome resolves to a specific team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
outcome resolves to a specific team.
deprecated: true
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/OutcomeVariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this outcome is about. Absent when it is about neither team.
allOf:
- $ref: "#/components/schemas/OutcomeVariantDetails"
- description: What this outcome is about. Absent when it is about neither team.
OutcomeStatus:
type: string
description: Resolution status of a market outcome.
enum:
- WON
- LOST
OutcomeVariantData:
type: object
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
oneOf:
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
discriminator:
propertyName: type
mapping:
SPORTS_NBA: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_LOL: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_CS2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_DOTA2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
OutcomeVariantData_SportsTeamOutcomeData:
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/SportsTeamOutcomeData"
OutcomeVariantDetails:
type: object
title: OutcomeVariantDetails
description: |-
What an outcome is about, one key per kind of market.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for an outcome that resolves to a team.
allOf:
- $ref: "#/components/schemas/SportsOutcomeDetails"
- description: Set for an outcome that resolves to a team.
PriceFeedProvider:
type: string
description: Provider of the price feed backing a crypto market.
enum:
- PYTH
- BINANCE
- CHAINLINK
- ATLAS
PriceLevel:
type: object
title: PriceLevel
required:
- price
- size
properties:
price:
type: number
format: double
description: In [0.0, 1.0].
size:
type: number
format: double
PublicActivityEventName:
type: string
description: |-
Activity event name that can be read for any address.
These are the on-chain position changes of a wallet. Order lifecycle
events stay private to the wallet owner.
enum:
- CONVERT
- MERGE
- SPLIT
- REDEEM
- REFUND
QuoteType:
type: string
description: "Quote type: ask or bid."
enum:
- Ask
- Bid
RewardPeriod:
type: object
title: RewardPeriod
description: A single span during which a market accrues rewards at a fixed
hourly rate.
required:
- hourlyRate
- startsAt
- endsAt
properties:
hourlyRate:
type: integer
format: int32
description: Reward points earned per hour while this period is active.
startsAt:
type: string
endsAt:
type: string
SportsDataProvider:
type: string
description: Sports data provider.
enum:
- PREDICT_SPORTS
- GRID
- POLYMARKET
SportsEventTeam:
type: object
title: SportsEventTeam
description: A sportsdata provider team as exposed in category variant data.
required:
- id
properties:
id:
type: integer
format: int64
description: Team identifier.
name:
type: string
abbreviation:
type: string
description: Team key abbreviation (e.g., "MIN", "SA"). Null when not available.
providerTeamId:
type: string
description: The team identifier used by the sportsdata provider. Null when no
game is linked.
isHome:
type: boolean
description: >-
Marks the side the fixture lists as home, which may be a neutral
venue. Null when the
provider does not say.
record:
description: Omitted when the provider sends none, or sends one whose format is
not known.
allOf:
- $ref: "#/components/schemas/SportsTeamRecord"
- description: Omitted when the provider sends none, or sends one whose format is
not known.
color:
type: string
description: >-
Team colour as a hex string from the provider. Omitted when the
provider does not send
one.
SportsFifaFriendliesVariantData:
type: object
title: SportsFifaFriendliesVariantData
description: Variant data for SPORTS_FIFA_FRIENDLIES categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsFifaWorldCupVariantData:
type: object
title: SportsFifaWorldCupVariantData
description: Variant data for SPORTS_FIFA_WORLD_CUP categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsMarketDetails:
type: object
title: SportsMarketDetails
description: What a market of a sports category is about.
properties:
provider:
description: The provider that links the team. Absent when no team is named.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team. Absent when no team is named.
team:
description: The team this market is about, when it is about one. .
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this market is about, when it is about one. .
line:
type: number
format: double
description: >-
The line this market is about: a total, a spread, or a player count.
TODO which side of a spread the line runs is not stated. It belongs
to
the market's `team`, so it needs the importer to record the subject:
polymarket orders a spread's outcomes subject first, and where the
feed
carries `marketMetadata.opticOddsTeamId` that agrees with it. Until
then
only the deprecated `variantData.spreadSide` says anything, and only
for
soccer, where a slug pattern happens to name the side.
gameNumber:
type: integer
format: int32
SportsNbaVariantData:
type: object
title: SportsNbaVariantData
description: Variant data for SPORTS_NBA categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsOutcomeDetails:
type: object
title: SportsOutcomeDetails
description: >-
What an outcome of a sports market is about.
Carries no type of its own, for the same reason as
[`SportsMarketDetails`].
required:
- provider
- team
properties:
provider:
description: The provider that links the team.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team.
team:
description: The team this outcome resolves to.
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this outcome resolves to.
SportsPropsMarketData:
type: object
title: SportsPropsMarketData
description: |-
Per-market data for `SPORTS_PROPS` prop markets.
Fields are market-type-specific: `spreadSide` is set for spread markets,
`line` is set for totals markets. Both-teams-to-score markets emit no
`variantData` of this shape.
properties:
spreadSide:
description: Which side of the parent match this spread market is on. Present
for spread markets only.
allOf:
- $ref: "#/components/schemas/TeamSide"
- description: Which side of the parent match this spread market is on. Present
for spread markets only.
line:
type: number
format: double
description: The line value for this totals market. Present for totals markets
only.
SportsTeamOutcomeData:
type: object
title: SportsTeamOutcomeData
description: Outcome variant data for sports markets where the outcome maps to a team.
required:
- provider
- team
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
team:
$ref: "#/components/schemas/SportsEventTeam"
SportsTeamRecord:
type: object
title: SportsTeamRecord
description: A team's win-loss record, in one shape whatever the sport or provider.
required:
- wins
- losses
properties:
wins:
type: integer
format: int32
losses:
type: integer
format: int32
draws:
type: integer
format: int32
description: Ties count as draws. Omitted where the sport's record has no draws,
as in basketball.
overtimeLosses:
type: integer
format: int32
description: Ice hockey losses after regulation, counted apart from `losses`.
Omitted elsewhere.
Team:
type: object
title: Team
description: Sports team identity.
required:
- id
- name
- abbreviation
- league
properties:
id:
type: integer
format: int64
name:
type: string
abbreviation:
type: string
alias:
type: string
league:
type: string
TeamSide:
type: string
description: Which side of a sports match a team plays on.
enum:
- HOME
- AWAY
TweetCountVariantData:
type: object
title: TweetCountVariantData
description: Variant data for TWEET_COUNT markets
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: X (Twitter) account username being tracked
tweetCount:
type: integer
format: int64
description: Current count of tweets within the category date range
VariantData:
type: object
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
oneOf:
- $ref: "#/components/schemas/VariantData_CryptoUpDownVariantData"
- $ref: "#/components/schemas/VariantData_TweetCountVariantData"
- $ref: "#/components/schemas/VariantData_SportsNbaVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
- $ref: "#/components/schemas/VariantData_SportsPropsMarketData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
discriminator:
propertyName: type
mapping:
CRYPTO_UP_DOWN: "#/components/schemas/VariantData_CryptoUpDownVariantData"
TWEET_COUNT: "#/components/schemas/VariantData_TweetCountVariantData"
SPORTS_NBA: "#/components/schemas/VariantData_SportsNbaVariantData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
SPORTS_PROPS: "#/components/schemas/VariantData_SportsPropsMarketData"
ESPORTS_LOL: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_CS2: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_DOTA2: "#/components/schemas/VariantData_EsportsVariantData"
VariantData_CryptoUpDownVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- CRYPTO_UP_DOWN
examples:
- CRYPTO_UP_DOWN
- $ref: "#/components/schemas/CryptoUpDownVariantData"
VariantData_EsportsVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/EsportsVariantData"
VariantData_SportsFifaFriendliesVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_FRIENDLIES
examples:
- SPORTS_FIFA_FRIENDLIES
- $ref: "#/components/schemas/SportsFifaFriendliesVariantData"
VariantData_SportsFifaWorldCupVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_WORLD_CUP
examples:
- SPORTS_FIFA_WORLD_CUP
- $ref: "#/components/schemas/SportsFifaWorldCupVariantData"
VariantData_SportsNbaVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_NBA
examples:
- SPORTS_NBA
- $ref: "#/components/schemas/SportsNbaVariantData"
VariantData_SportsPropsMarketData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_PROPS
examples:
- SPORTS_PROPS
- $ref: "#/components/schemas/SportsPropsMarketData"
VariantData_TweetCountVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- TWEET_COUNT
examples:
- TWEET_COUNT
- $ref: "#/components/schemas/TweetCountVariantData"
```
# Get PnL history by address (/api/account/get-pnl-history-by-address)
`GET https://api.predict.fun/v1/account/{address}/pnl`
Cumulative profit and loss in USD for any wallet, the series the
predict.fun profile chart shows. `period` picks the window and with it
the spacing: hourly points for `1d`, daily for `7d` and `30d`, and the
whole history for `all` (the default). The latest point is the current
PnL.
The whole series comes back in one response, so there is no cursor.
Results are cached for up to 30 seconds, so polling faster than that
returns the same series. An address with no account returns an empty
series.
```yaml
paths:
/account/{address}/pnl:
get:
tags:
- Account
summary: Get PnL history by address
description: |-
Cumulative profit and loss in USD for any wallet, the series the
predict.fun profile chart shows. `period` picks the window and with it
the spacing: hourly points for `1d`, daily for `7d` and `30d`, and the
whole history for `all` (the default). The latest point is the current
PnL.
The whole series comes back in one response, so there is no cursor.
Results are cached for up to 30 seconds, so polling faster than that
returns the same series. An address with no account returns an empty
series.
parameters:
- name: address
schema:
type: string
in: path
description: The wallet's address. For a Predict account, use the account's
address.
required: true
deprecated: false
explode: true
- name: period
schema:
$ref: "#/components/schemas/PnlPeriod"
in: query
description: Window of history to return. Defaults to `all`.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/WalletPnlResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
PnlPeriod:
type: string
description: |-
Window of PnL history to return. Each value is a period the upstream PnL
history service computes natively, so a request maps to exactly one
upstream call and nothing is trimmed or resampled here.
enum:
- 1d
- 7d
- 30d
- all
PnlPoint:
type: object
title: PnlPoint
description: One point of a wallet's cumulative PnL
required:
- x
- y
properties:
x:
type: integer
format: int64
description: Unix timestamp (seconds) at the start of the bucket
y:
type: number
format: double
description: Cumulative PnL in USD as of this bucket
WalletPnlData:
type: object
title: WalletPnlData
description: A wallet's PnL history
required:
- period
- points
properties:
period:
$ref: "#/components/schemas/PnlPeriod"
points:
type: array
description: Oldest first. Empty for an address that has never traded.
items:
$ref: "#/components/schemas/PnlPoint"
WalletPnlResponse:
type: object
title: WalletPnlResponse
description: Response for GET /v1/account/{address}/pnl
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/WalletPnlData"
```
# Set a referral (/api/account/set-a-referral)
`POST https://api.predict.fun/v1/account/referral`
Set a referral code if not already set.
Requires JWT or project authentication. Project auth requires an
EIP-712 signature in the `x-signature` header.
```yaml
paths:
/account/referral:
post:
tags:
- Account
summary: Set a referral
description: |-
Set a referral code if not already set.
Requires JWT or project authentication. Project auth requires an
EIP-712 signature in the `x-signature` header.
requestBody:
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/SetReferralRequest"
required: true
responses:
"201":
description: Created
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/SetReferralResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
SetReferralData:
type: object
title: SetReferralData
description: Set referral data
required:
- referralCode
properties:
referralCode:
type: string
description: a string 5 character(s) long
maxLength: 5
minLength: 5
SetReferralRequest:
type: object
title: SetReferralRequest
description: Set referral request
required:
- data
properties:
data:
$ref: "#/components/schemas/SetReferralData"
SetReferralResponse:
type: object
title: SetReferralResponse
description: Response for POST /v1/account/referral
required:
- success
properties:
success:
type: boolean
```
# Get maker rebate events (/api/fee-events/get-maker-rebate-events)
`GET https://api.predict.fun/v1/maker-rebates`
Returns paginated on-chain maker rebate earnings for the authenticated wallet,
newest first.
The `occurred_after` and `occurred_before` filters are unix timestamps in
milliseconds and both bounds are exclusive: only events that occurred
strictly after `occurred_after` and strictly before `occurred_before` are
returned. Neither bound is carried in the pagination cursor, so send the
same filters again when requesting the next page.
```yaml
paths:
/maker-rebates:
get:
tags:
- Fee Events
summary: Get maker rebate events
description: >-
Returns paginated on-chain maker rebate earnings for the authenticated
wallet,
newest first.
The `occurred_after` and `occurred_before` filters are unix timestamps
in
milliseconds and both bounds are exclusive: only events that occurred
strictly after `occurred_after` and strictly before `occurred_before`
are
returned. Neither bound is carried in the pagination cursor, so send the
same filters again when requesting the next page.
parameters:
- name: first
schema:
type: integer
format: int32
in: query
description: Page size, from 1 to 150. Defaults to 50. A value outside that
range is clamped.
required: false
deprecated: false
explode: true
- name: after
schema:
type: string
maxLength: 1024
in: query
description: The `cursor` from the previous page, to get the next one.
required: false
deprecated: false
explode: true
- name: fee_in_collateral
schema:
type: boolean
in: query
description: >-
Set to `true` for the amounts paid in USDT, or `false` for those
paid in outcome
tokens.
required: true
deprecated: false
explode: true
- name: occurred_after
schema:
type: integer
format: int64
in: query
description: Only include events that occurred strictly after this unix
timestamp (milliseconds)
required: false
deprecated: false
explode: true
- name: occurred_before
schema:
type: integer
format: int64
in: query
description: Only include events that occurred strictly before this unix
timestamp (milliseconds)
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/FeeEventsResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
FeeEventData:
type: object
title: FeeEventData
description: A single on-chain fee distribution event (referral fee or maker rebate).
required:
- transactionHash
- createdAt
- takerFeeTokenId
- amount
- price
properties:
transactionHash:
type: string
createdAt:
type: string
takerFeeTokenId:
type: string
amount:
type: string
marketQuestion:
type: string
marketOutcomeName:
type: string
price:
type: string
FeeEventsResponse:
type: object
title: FeeEventsResponse
description: Paginated fee event response.
required:
- success
- data
properties:
success:
type: boolean
cursor:
type: string
data:
type: array
items:
$ref: "#/components/schemas/FeeEventData"
```
# Get referral fee events (/api/fee-events/get-referral-fee-events)
`GET https://api.predict.fun/v1/referral-fees`
Returns paginated on-chain referral fee earnings for the authenticated wallet,
newest first.
The `occurred_after` and `occurred_before` filters are unix timestamps in
milliseconds and both bounds are exclusive: only events that occurred
strictly after `occurred_after` and strictly before `occurred_before` are
returned. Neither bound is carried in the pagination cursor, so send the
same filters again when requesting the next page.
```yaml
paths:
/referral-fees:
get:
tags:
- Fee Events
summary: Get referral fee events
description: >-
Returns paginated on-chain referral fee earnings for the authenticated
wallet,
newest first.
The `occurred_after` and `occurred_before` filters are unix timestamps
in
milliseconds and both bounds are exclusive: only events that occurred
strictly after `occurred_after` and strictly before `occurred_before`
are
returned. Neither bound is carried in the pagination cursor, so send the
same filters again when requesting the next page.
parameters:
- name: first
schema:
type: integer
format: int32
in: query
description: Page size, from 1 to 150. Defaults to 50. A value outside that
range is clamped.
required: false
deprecated: false
explode: true
- name: after
schema:
type: string
maxLength: 1024
in: query
description: The `cursor` from the previous page, to get the next one.
required: false
deprecated: false
explode: true
- name: fee_in_collateral
schema:
type: boolean
in: query
description: >-
Set to `true` for the amounts paid in USDT, or `false` for those
paid in outcome
tokens.
required: true
deprecated: false
explode: true
- name: occurred_after
schema:
type: integer
format: int64
in: query
description: Only include events that occurred strictly after this unix
timestamp (milliseconds)
required: false
deprecated: false
explode: true
- name: occurred_before
schema:
type: integer
format: int64
in: query
description: Only include events that occurred strictly before this unix
timestamp (milliseconds)
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/FeeEventsResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
FeeEventData:
type: object
title: FeeEventData
description: A single on-chain fee distribution event (referral fee or maker rebate).
required:
- transactionHash
- createdAt
- takerFeeTokenId
- amount
- price
properties:
transactionHash:
type: string
createdAt:
type: string
takerFeeTokenId:
type: string
amount:
type: string
marketQuestion:
type: string
marketOutcomeName:
type: string
price:
type: string
FeeEventsResponse:
type: object
title: FeeEventsResponse
description: Paginated fee event response.
required:
- success
- data
properties:
success:
type: boolean
cursor:
type: string
data:
type: array
items:
$ref: "#/components/schemas/FeeEventData"
```
# Get positions (/api/positions/get-positions)
`GET https://api.predict.fun/v1/positions`
Get data about your positions.
Requires JWT authentication.
```yaml
paths:
/positions:
get:
tags:
- Positions
summary: Get positions
description: |-
Get data about your positions.
Requires JWT authentication.
parameters:
- name: first
schema:
type: integer
format: int32
in: query
description: Page size, from 1 to 100. Defaults to 20. A value outside that
range is clamped.
required: false
deprecated: false
explode: true
- name: after
schema:
type: string
maxLength: 1024
in: query
description: The `cursor` from the previous page, to get the next one.
required: false
deprecated: false
explode: true
- name: marketId
schema:
type: integer
format: int64
in: query
description: Only positions in this market. Cannot be combined with `marketIds`.
required: false
deprecated: false
explode: true
- name: marketIds
schema:
type: array
items:
type: integer
format: int64
in: query
description: |-
Only positions in these markets (comma-separated or repeated, up to
100). Cannot be combined with `marketId`.
required: false
deprecated: false
explode: true
- name: categoryId
schema:
type: string
maxLength: 256
in: query
description: Only positions in the category with this slug, which markets return
as `categorySlug`.
required: false
deprecated: false
explode: true
- name: isResolved
schema:
type: boolean
in: query
description: >-
Set to `true` for only positions in resolved markets, or `false` for
only those in
unresolved markets. Both are listed by default.
required: false
deprecated: false
explode: true
- name: includeLost
schema:
type: boolean
in: query
description: |-
Also list positions in outcomes that settled as losing. Off by
default, since those need no action from the holder.
required: false
deprecated: false
explode: true
- name: sort
schema:
$ref: "#/components/schemas/PositionSort"
in: query
description: >-
How to order the positions. Defaults to `EVENT_BLOCK_DESC`, which
lists the most
recently changed positions first.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/PositionsResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
CryptoUpDownVariantData:
type: object
title: CryptoUpDownVariantData
description: Variant data for CRYPTO_UP_DOWN markets
required:
- priceFeedProvider
properties:
priceFeedProvider:
$ref: "#/components/schemas/PriceFeedProvider"
startPrice:
type: number
format: double
description: Starting price, null before market start
endPrice:
type: number
format: double
description: Ending price from Pyth oracle, null if not yet resolved
priceFeedId:
type: string
description: Pyth oracle price feed identifier
priceFeedSymbol:
type: string
description: Price feed symbol (e.g. "BTCUSDT" for Binance, "BTC_USD" for Pyth)
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
EsportsVariantData:
type: object
title: EsportsVariantData
description: Variant data for esports match categories sourced from Grid.gg.
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked series yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
Market:
type: object
title: Market
description: Full market data as returned by the API
required:
- id
- imageUrl
- title
- question
- description
- tradingStatus
- status
- isVisible
- isNegRisk
- isYieldBearing
- feeRateBps
- makerFeeBps
- oracleQuestionId
- conditionId
- resolverAddress
- outcomes
- spreadThreshold
- shareThreshold
- isBoosted
- polymarketConditionIds
- categorySlug
- createdAt
- decimalPrecision
- marketVariant
- rewards
properties:
id:
type: integer
format: int64
imageUrl:
type: string
title:
type: string
question:
type: string
description:
type: string
tradingStatus:
$ref: "#/components/schemas/MarketTradingStatus"
status:
$ref: "#/components/schemas/MarketStatus"
isVisible:
type: boolean
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
feeRateBps:
type: integer
format: int32
description: Taker fee in basis points, charged on each matched trade.
makerFeeBps:
type: integer
format: int32
description: |-
Maker fee in basis points. Always `0`: no market charges makers.
Defaults on decode so market entries cached before the field existed
still decode rather than reading as misses, and the default is the
only value it takes.
resolution:
$ref: "#/components/schemas/Outcome"
oracleQuestionId:
type: string
conditionId:
type: string
resolverAddress:
type: string
outcomes:
type: array
items:
$ref: "#/components/schemas/Outcome"
questionIndex:
type: integer
format: int32
spreadThreshold:
type: number
format: double
shareThreshold:
type: integer
format: int32
isBoosted:
type: boolean
boostStartsAt:
type: string
boostEndsAt:
type: string
polymarketConditionIds:
type: array
items:
type: string
kalshiMarketTicker:
type: string
categorySlug:
type: string
seriesSlug:
type: string
description: |-
Slug of the recurring series this market's category is a round of,
e.g. `"btc-updown-5m"`. Absent when it is not a round of one. The
series and its next rounds are at `GET /v1/series/{slug}`.
createdAt:
type: string
decimalPrecision:
type: integer
format: int32
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
allOf:
- $ref: "#/components/schemas/MarketVariantDetails"
- description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
market as a whole is about a single team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
market as a whole is about a single team.
deprecated: true
marketType:
description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
allOf:
- $ref: "#/components/schemas/MarketType"
- description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
rewards:
$ref: "#/components/schemas/MarketRewards"
MarketRewards:
type: object
title: MarketRewards
description: Reward schedule for a market.
required:
- schedule
properties:
current:
description: Active period at request time, or `null` if no rewards are accruing.
allOf:
- $ref: "#/components/schemas/RewardPeriod"
- description: Active period at request time, or `null` if no rewards are
accruing.
schedule:
type: array
description: Full schedule of past and future reward periods for this market.
items:
$ref: "#/components/schemas/RewardPeriod"
MarketStatus:
type: string
description: |-
Market lifecycle state, from registration through resolution.
`Removed` is a synthetic status reported for markets that have been
withdrawn, meaning it is not part of the normal lifecycle progression.
enum:
- REGISTERED
- PRICE_PROPOSED
- PRICE_DISPUTED
- PAUSED
- UNPAUSED
- RESOLVED
- REMOVED
MarketTradingStatus:
type: string
description: Trading status derived from market visibility and deletion state.
enum:
- OPEN
- MATCHING_NOT_ENABLED
- CANCEL_ONLY
- CLOSED
MarketType:
type: string
description: >-
Market type (DB `market.market_type_id` values as repr).
Classifies what kind of prediction an individual market represents,
independent of the category it belongs to. Works alongside
[`MarketVariant`]:
the variant describes how the category container renders; the market
type
describes the prediction mechanic of the individual market.
enum:
- SPORTS_MONEYLINE
- SPORTS_SPREADS
- SPORTS_TOTALS
- SPORTS_BOTH_TEAMS_TO_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_EXACT_SCORE
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_TEAM_TOTAL_CORNERS
- SPORTS_CORNERS_ODD_EVEN
- SPORTS_PLAYER_GOALS
- SPORTS_PLAYER_ASSISTS
- SPORTS_PLAYER_GOALS_PLUS_ASSISTS
- SPORTS_PLAYER_SHOTS
- SPORTS_PLAYER_SHOTS_ON_TARGET
- SPORTS_PLAYER_GOALKEEPER_SAVES
- SPORTS_TEAM_TO_ADVANCE
- SPORTS_EXTRA_TIME
- SPORTS_PENALTY_SHOOTOUT
- SPORTS_TEAM_TOTALS
- SPORTS_CHILD_MONEYLINE
- SPORTS_MAP_HANDICAP
- SPORTS_BOTH_TEAMS_TO_SCORE_FIRST_HALF
- SPORTS_BOTH_TEAMS_TO_SCORE_SECOND_HALF
- SPORTS_FIRST_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- SPORTS_FIRST_CORNER
- SPORTS_FIRST_HALF_TOTALS
- SPORTS_SECOND_HALF_TOTALS
- SPORTS_FIRST_HALF_TEAM_TOTALS
- SPORTS_SECOND_HALF_TEAM_TOTALS
- SPORTS_FIRST_BLOOD_GAME
- SPORTS_KILL_OVER_UNDER_GAME
- SPORTS_ROUND_HANDICAP
- SPORTS_ROUND_TOTALS
- SPORTS_ANYTIME_TOUCHDOWNS
- SPORTS_RACE_TO_POINTS
- SPORTS_ODD_EVEN
MarketVariant:
type: string
description: |-
Classifies the market template type.
Controls the UI layout and trading mechanics of a category. See also
[`MarketType`] which classifies individual markets within a category.
enum:
- DEFAULT
- SPORTS_MATCH
- CRYPTO_UP_DOWN
- TWEET_COUNT
- SPORTS_TEAM_MATCH
- SPORTS_NBA
- SPORTS_FIFA_WORLD_CUP
- SPORTS_EXACT_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_PROPS
- SPORTS_FIFA_FRIENDLIES
- ESPORTS_LOL
- ESPORTS_CS2
- ESPORTS_DOTA2
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- UP_DOWN
MarketVariantDetails:
type: object
title: MarketVariantDetails
description: >-
What a market is about, one key per kind of market.
Grouping by kind rather than discriminating on a type means a kind that
gains a payload is a new key, and one that loses it is a key removed,
with
nothing to keep in step. A market names the kinds that apply to it,
which
today is at most one.
Add a kind by adding a key. Each is filled independently, so a populator
sets its own key on the value already there rather than replacing it.
properties:
sports:
description: Set for a market of a sports category.
allOf:
- $ref: "#/components/schemas/SportsMarketDetails"
- description: Set for a market of a sports category.
Outcome:
type: object
title: Outcome
description: Outcome data (from markets, positions, etc.)/// Outcome data (from
markets, positions, etc.)
required:
- name
- indexSet
- onChainId
properties:
name:
type: string
indexSet:
type: integer
format: int32
onChainId:
type: string
description: bigint string
status:
$ref: "#/components/schemas/OutcomeStatus"
bestBid:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes, or
poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is embedded
in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the next.
That is what caps the shared-cache TTL on those routes at seconds,
and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes,
or poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is
embedded in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the
next.
That is what caps the shared-cache TTL on those routes at
seconds, and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
bestAsk:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead, and
why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead,
and why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
outcome resolves to a specific team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
outcome resolves to a specific team.
deprecated: true
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/OutcomeVariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this outcome is about. Absent when it is about neither team.
allOf:
- $ref: "#/components/schemas/OutcomeVariantDetails"
- description: What this outcome is about. Absent when it is about neither team.
OutcomeStatus:
type: string
description: Resolution status of a market outcome.
enum:
- WON
- LOST
OutcomeVariantData:
type: object
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
oneOf:
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
discriminator:
propertyName: type
mapping:
SPORTS_NBA: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_LOL: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_CS2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_DOTA2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
OutcomeVariantData_SportsTeamOutcomeData:
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/SportsTeamOutcomeData"
OutcomeVariantDetails:
type: object
title: OutcomeVariantDetails
description: |-
What an outcome is about, one key per kind of market.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for an outcome that resolves to a team.
allOf:
- $ref: "#/components/schemas/SportsOutcomeDetails"
- description: Set for an outcome that resolves to a team.
PositionData:
type: object
title: PositionData
description: Position data
required:
- id
- market
- outcome
- amount
- valueUsd
- averageBuyPriceUsd
- pnlUsd
properties:
id:
type: string
market:
$ref: "#/components/schemas/Market"
outcome:
$ref: "#/components/schemas/Outcome"
amount:
type: string
description: bigint string
valueUsd:
type: string
averageBuyPriceUsd:
type: string
pnlUsd:
type: string
PositionSort:
type: string
description: Sort options for position queries.
enum:
- AMOUNT_DESC
- EVENT_BLOCK_ASC
- EVENT_BLOCK_DESC
- SHARES_VALUE_DESC
- RETURN_DESC
PositionsResponse:
type: object
title: PositionsResponse
description: Response for GET /v1/positions
required:
- success
- data
properties:
success:
type: boolean
cursor:
type: string
data:
type: array
items:
$ref: "#/components/schemas/PositionData"
PriceFeedProvider:
type: string
description: Provider of the price feed backing a crypto market.
enum:
- PYTH
- BINANCE
- CHAINLINK
- ATLAS
PriceLevel:
type: object
title: PriceLevel
required:
- price
- size
properties:
price:
type: number
format: double
description: In [0.0, 1.0].
size:
type: number
format: double
RewardPeriod:
type: object
title: RewardPeriod
description: A single span during which a market accrues rewards at a fixed
hourly rate.
required:
- hourlyRate
- startsAt
- endsAt
properties:
hourlyRate:
type: integer
format: int32
description: Reward points earned per hour while this period is active.
startsAt:
type: string
endsAt:
type: string
SportsDataProvider:
type: string
description: Sports data provider.
enum:
- PREDICT_SPORTS
- GRID
- POLYMARKET
SportsEventTeam:
type: object
title: SportsEventTeam
description: A sportsdata provider team as exposed in category variant data.
required:
- id
properties:
id:
type: integer
format: int64
description: Team identifier.
name:
type: string
abbreviation:
type: string
description: Team key abbreviation (e.g., "MIN", "SA"). Null when not available.
providerTeamId:
type: string
description: The team identifier used by the sportsdata provider. Null when no
game is linked.
isHome:
type: boolean
description: >-
Marks the side the fixture lists as home, which may be a neutral
venue. Null when the
provider does not say.
record:
description: Omitted when the provider sends none, or sends one whose format is
not known.
allOf:
- $ref: "#/components/schemas/SportsTeamRecord"
- description: Omitted when the provider sends none, or sends one whose format is
not known.
color:
type: string
description: >-
Team colour as a hex string from the provider. Omitted when the
provider does not send
one.
SportsFifaFriendliesVariantData:
type: object
title: SportsFifaFriendliesVariantData
description: Variant data for SPORTS_FIFA_FRIENDLIES categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsFifaWorldCupVariantData:
type: object
title: SportsFifaWorldCupVariantData
description: Variant data for SPORTS_FIFA_WORLD_CUP categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsMarketDetails:
type: object
title: SportsMarketDetails
description: What a market of a sports category is about.
properties:
provider:
description: The provider that links the team. Absent when no team is named.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team. Absent when no team is named.
team:
description: The team this market is about, when it is about one. .
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this market is about, when it is about one. .
line:
type: number
format: double
description: >-
The line this market is about: a total, a spread, or a player count.
TODO which side of a spread the line runs is not stated. It belongs
to
the market's `team`, so it needs the importer to record the subject:
polymarket orders a spread's outcomes subject first, and where the
feed
carries `marketMetadata.opticOddsTeamId` that agrees with it. Until
then
only the deprecated `variantData.spreadSide` says anything, and only
for
soccer, where a slug pattern happens to name the side.
gameNumber:
type: integer
format: int32
SportsNbaVariantData:
type: object
title: SportsNbaVariantData
description: Variant data for SPORTS_NBA categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsOutcomeDetails:
type: object
title: SportsOutcomeDetails
description: >-
What an outcome of a sports market is about.
Carries no type of its own, for the same reason as
[`SportsMarketDetails`].
required:
- provider
- team
properties:
provider:
description: The provider that links the team.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team.
team:
description: The team this outcome resolves to.
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this outcome resolves to.
SportsPropsMarketData:
type: object
title: SportsPropsMarketData
description: |-
Per-market data for `SPORTS_PROPS` prop markets.
Fields are market-type-specific: `spreadSide` is set for spread markets,
`line` is set for totals markets. Both-teams-to-score markets emit no
`variantData` of this shape.
properties:
spreadSide:
description: Which side of the parent match this spread market is on. Present
for spread markets only.
allOf:
- $ref: "#/components/schemas/TeamSide"
- description: Which side of the parent match this spread market is on. Present
for spread markets only.
line:
type: number
format: double
description: The line value for this totals market. Present for totals markets
only.
SportsTeamOutcomeData:
type: object
title: SportsTeamOutcomeData
description: Outcome variant data for sports markets where the outcome maps to a team.
required:
- provider
- team
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
team:
$ref: "#/components/schemas/SportsEventTeam"
SportsTeamRecord:
type: object
title: SportsTeamRecord
description: A team's win-loss record, in one shape whatever the sport or provider.
required:
- wins
- losses
properties:
wins:
type: integer
format: int32
losses:
type: integer
format: int32
draws:
type: integer
format: int32
description: Ties count as draws. Omitted where the sport's record has no draws,
as in basketball.
overtimeLosses:
type: integer
format: int32
description: Ice hockey losses after regulation, counted apart from `losses`.
Omitted elsewhere.
Team:
type: object
title: Team
description: Sports team identity.
required:
- id
- name
- abbreviation
- league
properties:
id:
type: integer
format: int64
name:
type: string
abbreviation:
type: string
alias:
type: string
league:
type: string
TeamSide:
type: string
description: Which side of a sports match a team plays on.
enum:
- HOME
- AWAY
TweetCountVariantData:
type: object
title: TweetCountVariantData
description: Variant data for TWEET_COUNT markets
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: X (Twitter) account username being tracked
tweetCount:
type: integer
format: int64
description: Current count of tweets within the category date range
VariantData:
type: object
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
oneOf:
- $ref: "#/components/schemas/VariantData_CryptoUpDownVariantData"
- $ref: "#/components/schemas/VariantData_TweetCountVariantData"
- $ref: "#/components/schemas/VariantData_SportsNbaVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
- $ref: "#/components/schemas/VariantData_SportsPropsMarketData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
discriminator:
propertyName: type
mapping:
CRYPTO_UP_DOWN: "#/components/schemas/VariantData_CryptoUpDownVariantData"
TWEET_COUNT: "#/components/schemas/VariantData_TweetCountVariantData"
SPORTS_NBA: "#/components/schemas/VariantData_SportsNbaVariantData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
SPORTS_PROPS: "#/components/schemas/VariantData_SportsPropsMarketData"
ESPORTS_LOL: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_CS2: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_DOTA2: "#/components/schemas/VariantData_EsportsVariantData"
VariantData_CryptoUpDownVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- CRYPTO_UP_DOWN
examples:
- CRYPTO_UP_DOWN
- $ref: "#/components/schemas/CryptoUpDownVariantData"
VariantData_EsportsVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/EsportsVariantData"
VariantData_SportsFifaFriendliesVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_FRIENDLIES
examples:
- SPORTS_FIFA_FRIENDLIES
- $ref: "#/components/schemas/SportsFifaFriendliesVariantData"
VariantData_SportsFifaWorldCupVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_WORLD_CUP
examples:
- SPORTS_FIFA_WORLD_CUP
- $ref: "#/components/schemas/SportsFifaWorldCupVariantData"
VariantData_SportsNbaVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_NBA
examples:
- SPORTS_NBA
- $ref: "#/components/schemas/SportsNbaVariantData"
VariantData_SportsPropsMarketData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_PROPS
examples:
- SPORTS_PROPS
- $ref: "#/components/schemas/SportsPropsMarketData"
VariantData_TweetCountVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- TWEET_COUNT
examples:
- TWEET_COUNT
- $ref: "#/components/schemas/TweetCountVariantData"
```
# Get positions by address (/api/positions/get-positions-by-address)
`GET https://api.predict.fun/v1/positions/{address}`
Get positions for a specific wallet address.
```yaml
paths:
/positions/{address}:
get:
tags:
- Positions
summary: Get positions by address
description: Get positions for a specific wallet address.
parameters:
- name: address
schema:
type: string
in: path
description: The wallet's address. For a Predict account, use the account's
address.
required: true
deprecated: false
explode: true
- name: first
schema:
type: integer
format: int32
in: query
description: Page size, from 1 to 100. Defaults to 20. A value outside that
range is clamped.
required: false
deprecated: false
explode: true
- name: after
schema:
type: string
maxLength: 1024
in: query
description: The `cursor` from the previous page, to get the next one.
required: false
deprecated: false
explode: true
- name: marketId
schema:
type: integer
format: int64
in: query
description: Only positions in this market. Cannot be combined with `marketIds`.
required: false
deprecated: false
explode: true
- name: marketIds
schema:
type: array
items:
type: integer
format: int64
in: query
description: |-
Only positions in these markets (comma-separated or repeated, up to
100). Cannot be combined with `marketId`.
required: false
deprecated: false
explode: true
- name: categoryId
schema:
type: string
maxLength: 256
in: query
description: Only positions in the category with this slug, which markets return
as `categorySlug`.
required: false
deprecated: false
explode: true
- name: isResolved
schema:
type: boolean
in: query
description: >-
Set to `true` for only positions in resolved markets, or `false` for
only those in
unresolved markets. Both are listed by default.
required: false
deprecated: false
explode: true
- name: includeLost
schema:
type: boolean
in: query
description: |-
Also list positions in outcomes that settled as losing. Off by
default, since those need no action from the holder.
required: false
deprecated: false
explode: true
- name: sort
schema:
$ref: "#/components/schemas/PositionSort"
in: query
description: >-
How to order the positions. Defaults to `EVENT_BLOCK_DESC`, which
lists the most
recently changed positions first.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/PositionsResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
CryptoUpDownVariantData:
type: object
title: CryptoUpDownVariantData
description: Variant data for CRYPTO_UP_DOWN markets
required:
- priceFeedProvider
properties:
priceFeedProvider:
$ref: "#/components/schemas/PriceFeedProvider"
startPrice:
type: number
format: double
description: Starting price, null before market start
endPrice:
type: number
format: double
description: Ending price from Pyth oracle, null if not yet resolved
priceFeedId:
type: string
description: Pyth oracle price feed identifier
priceFeedSymbol:
type: string
description: Price feed symbol (e.g. "BTCUSDT" for Binance, "BTC_USD" for Pyth)
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
EsportsVariantData:
type: object
title: EsportsVariantData
description: Variant data for esports match categories sourced from Grid.gg.
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked series yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
Market:
type: object
title: Market
description: Full market data as returned by the API
required:
- id
- imageUrl
- title
- question
- description
- tradingStatus
- status
- isVisible
- isNegRisk
- isYieldBearing
- feeRateBps
- makerFeeBps
- oracleQuestionId
- conditionId
- resolverAddress
- outcomes
- spreadThreshold
- shareThreshold
- isBoosted
- polymarketConditionIds
- categorySlug
- createdAt
- decimalPrecision
- marketVariant
- rewards
properties:
id:
type: integer
format: int64
imageUrl:
type: string
title:
type: string
question:
type: string
description:
type: string
tradingStatus:
$ref: "#/components/schemas/MarketTradingStatus"
status:
$ref: "#/components/schemas/MarketStatus"
isVisible:
type: boolean
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
feeRateBps:
type: integer
format: int32
description: Taker fee in basis points, charged on each matched trade.
makerFeeBps:
type: integer
format: int32
description: |-
Maker fee in basis points. Always `0`: no market charges makers.
Defaults on decode so market entries cached before the field existed
still decode rather than reading as misses, and the default is the
only value it takes.
resolution:
$ref: "#/components/schemas/Outcome"
oracleQuestionId:
type: string
conditionId:
type: string
resolverAddress:
type: string
outcomes:
type: array
items:
$ref: "#/components/schemas/Outcome"
questionIndex:
type: integer
format: int32
spreadThreshold:
type: number
format: double
shareThreshold:
type: integer
format: int32
isBoosted:
type: boolean
boostStartsAt:
type: string
boostEndsAt:
type: string
polymarketConditionIds:
type: array
items:
type: string
kalshiMarketTicker:
type: string
categorySlug:
type: string
seriesSlug:
type: string
description: |-
Slug of the recurring series this market's category is a round of,
e.g. `"btc-updown-5m"`. Absent when it is not a round of one. The
series and its next rounds are at `GET /v1/series/{slug}`.
createdAt:
type: string
decimalPrecision:
type: integer
format: int32
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
allOf:
- $ref: "#/components/schemas/MarketVariantDetails"
- description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
market as a whole is about a single team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
market as a whole is about a single team.
deprecated: true
marketType:
description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
allOf:
- $ref: "#/components/schemas/MarketType"
- description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
rewards:
$ref: "#/components/schemas/MarketRewards"
MarketRewards:
type: object
title: MarketRewards
description: Reward schedule for a market.
required:
- schedule
properties:
current:
description: Active period at request time, or `null` if no rewards are accruing.
allOf:
- $ref: "#/components/schemas/RewardPeriod"
- description: Active period at request time, or `null` if no rewards are
accruing.
schedule:
type: array
description: Full schedule of past and future reward periods for this market.
items:
$ref: "#/components/schemas/RewardPeriod"
MarketStatus:
type: string
description: |-
Market lifecycle state, from registration through resolution.
`Removed` is a synthetic status reported for markets that have been
withdrawn, meaning it is not part of the normal lifecycle progression.
enum:
- REGISTERED
- PRICE_PROPOSED
- PRICE_DISPUTED
- PAUSED
- UNPAUSED
- RESOLVED
- REMOVED
MarketTradingStatus:
type: string
description: Trading status derived from market visibility and deletion state.
enum:
- OPEN
- MATCHING_NOT_ENABLED
- CANCEL_ONLY
- CLOSED
MarketType:
type: string
description: >-
Market type (DB `market.market_type_id` values as repr).
Classifies what kind of prediction an individual market represents,
independent of the category it belongs to. Works alongside
[`MarketVariant`]:
the variant describes how the category container renders; the market
type
describes the prediction mechanic of the individual market.
enum:
- SPORTS_MONEYLINE
- SPORTS_SPREADS
- SPORTS_TOTALS
- SPORTS_BOTH_TEAMS_TO_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_EXACT_SCORE
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_TEAM_TOTAL_CORNERS
- SPORTS_CORNERS_ODD_EVEN
- SPORTS_PLAYER_GOALS
- SPORTS_PLAYER_ASSISTS
- SPORTS_PLAYER_GOALS_PLUS_ASSISTS
- SPORTS_PLAYER_SHOTS
- SPORTS_PLAYER_SHOTS_ON_TARGET
- SPORTS_PLAYER_GOALKEEPER_SAVES
- SPORTS_TEAM_TO_ADVANCE
- SPORTS_EXTRA_TIME
- SPORTS_PENALTY_SHOOTOUT
- SPORTS_TEAM_TOTALS
- SPORTS_CHILD_MONEYLINE
- SPORTS_MAP_HANDICAP
- SPORTS_BOTH_TEAMS_TO_SCORE_FIRST_HALF
- SPORTS_BOTH_TEAMS_TO_SCORE_SECOND_HALF
- SPORTS_FIRST_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- SPORTS_FIRST_CORNER
- SPORTS_FIRST_HALF_TOTALS
- SPORTS_SECOND_HALF_TOTALS
- SPORTS_FIRST_HALF_TEAM_TOTALS
- SPORTS_SECOND_HALF_TEAM_TOTALS
- SPORTS_FIRST_BLOOD_GAME
- SPORTS_KILL_OVER_UNDER_GAME
- SPORTS_ROUND_HANDICAP
- SPORTS_ROUND_TOTALS
- SPORTS_ANYTIME_TOUCHDOWNS
- SPORTS_RACE_TO_POINTS
- SPORTS_ODD_EVEN
MarketVariant:
type: string
description: |-
Classifies the market template type.
Controls the UI layout and trading mechanics of a category. See also
[`MarketType`] which classifies individual markets within a category.
enum:
- DEFAULT
- SPORTS_MATCH
- CRYPTO_UP_DOWN
- TWEET_COUNT
- SPORTS_TEAM_MATCH
- SPORTS_NBA
- SPORTS_FIFA_WORLD_CUP
- SPORTS_EXACT_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_PROPS
- SPORTS_FIFA_FRIENDLIES
- ESPORTS_LOL
- ESPORTS_CS2
- ESPORTS_DOTA2
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- UP_DOWN
MarketVariantDetails:
type: object
title: MarketVariantDetails
description: >-
What a market is about, one key per kind of market.
Grouping by kind rather than discriminating on a type means a kind that
gains a payload is a new key, and one that loses it is a key removed,
with
nothing to keep in step. A market names the kinds that apply to it,
which
today is at most one.
Add a kind by adding a key. Each is filled independently, so a populator
sets its own key on the value already there rather than replacing it.
properties:
sports:
description: Set for a market of a sports category.
allOf:
- $ref: "#/components/schemas/SportsMarketDetails"
- description: Set for a market of a sports category.
Outcome:
type: object
title: Outcome
description: Outcome data (from markets, positions, etc.)/// Outcome data (from
markets, positions, etc.)
required:
- name
- indexSet
- onChainId
properties:
name:
type: string
indexSet:
type: integer
format: int32
onChainId:
type: string
description: bigint string
status:
$ref: "#/components/schemas/OutcomeStatus"
bestBid:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes, or
poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is embedded
in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the next.
That is what caps the shared-cache TTL on those routes at seconds,
and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes,
or poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is
embedded in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the
next.
That is what caps the shared-cache TTL on those routes at
seconds, and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
bestAsk:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead, and
why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead,
and why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
outcome resolves to a specific team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
outcome resolves to a specific team.
deprecated: true
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/OutcomeVariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this outcome is about. Absent when it is about neither team.
allOf:
- $ref: "#/components/schemas/OutcomeVariantDetails"
- description: What this outcome is about. Absent when it is about neither team.
OutcomeStatus:
type: string
description: Resolution status of a market outcome.
enum:
- WON
- LOST
OutcomeVariantData:
type: object
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
oneOf:
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
discriminator:
propertyName: type
mapping:
SPORTS_NBA: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_LOL: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_CS2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_DOTA2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
OutcomeVariantData_SportsTeamOutcomeData:
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/SportsTeamOutcomeData"
OutcomeVariantDetails:
type: object
title: OutcomeVariantDetails
description: |-
What an outcome is about, one key per kind of market.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for an outcome that resolves to a team.
allOf:
- $ref: "#/components/schemas/SportsOutcomeDetails"
- description: Set for an outcome that resolves to a team.
PositionData:
type: object
title: PositionData
description: Position data
required:
- id
- market
- outcome
- amount
- valueUsd
- averageBuyPriceUsd
- pnlUsd
properties:
id:
type: string
market:
$ref: "#/components/schemas/Market"
outcome:
$ref: "#/components/schemas/Outcome"
amount:
type: string
description: bigint string
valueUsd:
type: string
averageBuyPriceUsd:
type: string
pnlUsd:
type: string
PositionSort:
type: string
description: Sort options for position queries.
enum:
- AMOUNT_DESC
- EVENT_BLOCK_ASC
- EVENT_BLOCK_DESC
- SHARES_VALUE_DESC
- RETURN_DESC
PositionsResponse:
type: object
title: PositionsResponse
description: Response for GET /v1/positions
required:
- success
- data
properties:
success:
type: boolean
cursor:
type: string
data:
type: array
items:
$ref: "#/components/schemas/PositionData"
PriceFeedProvider:
type: string
description: Provider of the price feed backing a crypto market.
enum:
- PYTH
- BINANCE
- CHAINLINK
- ATLAS
PriceLevel:
type: object
title: PriceLevel
required:
- price
- size
properties:
price:
type: number
format: double
description: In [0.0, 1.0].
size:
type: number
format: double
RewardPeriod:
type: object
title: RewardPeriod
description: A single span during which a market accrues rewards at a fixed
hourly rate.
required:
- hourlyRate
- startsAt
- endsAt
properties:
hourlyRate:
type: integer
format: int32
description: Reward points earned per hour while this period is active.
startsAt:
type: string
endsAt:
type: string
SportsDataProvider:
type: string
description: Sports data provider.
enum:
- PREDICT_SPORTS
- GRID
- POLYMARKET
SportsEventTeam:
type: object
title: SportsEventTeam
description: A sportsdata provider team as exposed in category variant data.
required:
- id
properties:
id:
type: integer
format: int64
description: Team identifier.
name:
type: string
abbreviation:
type: string
description: Team key abbreviation (e.g., "MIN", "SA"). Null when not available.
providerTeamId:
type: string
description: The team identifier used by the sportsdata provider. Null when no
game is linked.
isHome:
type: boolean
description: >-
Marks the side the fixture lists as home, which may be a neutral
venue. Null when the
provider does not say.
record:
description: Omitted when the provider sends none, or sends one whose format is
not known.
allOf:
- $ref: "#/components/schemas/SportsTeamRecord"
- description: Omitted when the provider sends none, or sends one whose format is
not known.
color:
type: string
description: >-
Team colour as a hex string from the provider. Omitted when the
provider does not send
one.
SportsFifaFriendliesVariantData:
type: object
title: SportsFifaFriendliesVariantData
description: Variant data for SPORTS_FIFA_FRIENDLIES categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsFifaWorldCupVariantData:
type: object
title: SportsFifaWorldCupVariantData
description: Variant data for SPORTS_FIFA_WORLD_CUP categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsMarketDetails:
type: object
title: SportsMarketDetails
description: What a market of a sports category is about.
properties:
provider:
description: The provider that links the team. Absent when no team is named.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team. Absent when no team is named.
team:
description: The team this market is about, when it is about one. .
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this market is about, when it is about one. .
line:
type: number
format: double
description: >-
The line this market is about: a total, a spread, or a player count.
TODO which side of a spread the line runs is not stated. It belongs
to
the market's `team`, so it needs the importer to record the subject:
polymarket orders a spread's outcomes subject first, and where the
feed
carries `marketMetadata.opticOddsTeamId` that agrees with it. Until
then
only the deprecated `variantData.spreadSide` says anything, and only
for
soccer, where a slug pattern happens to name the side.
gameNumber:
type: integer
format: int32
SportsNbaVariantData:
type: object
title: SportsNbaVariantData
description: Variant data for SPORTS_NBA categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsOutcomeDetails:
type: object
title: SportsOutcomeDetails
description: >-
What an outcome of a sports market is about.
Carries no type of its own, for the same reason as
[`SportsMarketDetails`].
required:
- provider
- team
properties:
provider:
description: The provider that links the team.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team.
team:
description: The team this outcome resolves to.
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this outcome resolves to.
SportsPropsMarketData:
type: object
title: SportsPropsMarketData
description: |-
Per-market data for `SPORTS_PROPS` prop markets.
Fields are market-type-specific: `spreadSide` is set for spread markets,
`line` is set for totals markets. Both-teams-to-score markets emit no
`variantData` of this shape.
properties:
spreadSide:
description: Which side of the parent match this spread market is on. Present
for spread markets only.
allOf:
- $ref: "#/components/schemas/TeamSide"
- description: Which side of the parent match this spread market is on. Present
for spread markets only.
line:
type: number
format: double
description: The line value for this totals market. Present for totals markets
only.
SportsTeamOutcomeData:
type: object
title: SportsTeamOutcomeData
description: Outcome variant data for sports markets where the outcome maps to a team.
required:
- provider
- team
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
team:
$ref: "#/components/schemas/SportsEventTeam"
SportsTeamRecord:
type: object
title: SportsTeamRecord
description: A team's win-loss record, in one shape whatever the sport or provider.
required:
- wins
- losses
properties:
wins:
type: integer
format: int32
losses:
type: integer
format: int32
draws:
type: integer
format: int32
description: Ties count as draws. Omitted where the sport's record has no draws,
as in basketball.
overtimeLosses:
type: integer
format: int32
description: Ice hockey losses after regulation, counted apart from `losses`.
Omitted elsewhere.
Team:
type: object
title: Team
description: Sports team identity.
required:
- id
- name
- abbreviation
- league
properties:
id:
type: integer
format: int64
name:
type: string
abbreviation:
type: string
alias:
type: string
league:
type: string
TeamSide:
type: string
description: Which side of a sports match a team plays on.
enum:
- HOME
- AWAY
TweetCountVariantData:
type: object
title: TweetCountVariantData
description: Variant data for TWEET_COUNT markets
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: X (Twitter) account username being tracked
tweetCount:
type: integer
format: int64
description: Current count of tweets within the category date range
VariantData:
type: object
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
oneOf:
- $ref: "#/components/schemas/VariantData_CryptoUpDownVariantData"
- $ref: "#/components/schemas/VariantData_TweetCountVariantData"
- $ref: "#/components/schemas/VariantData_SportsNbaVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
- $ref: "#/components/schemas/VariantData_SportsPropsMarketData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
discriminator:
propertyName: type
mapping:
CRYPTO_UP_DOWN: "#/components/schemas/VariantData_CryptoUpDownVariantData"
TWEET_COUNT: "#/components/schemas/VariantData_TweetCountVariantData"
SPORTS_NBA: "#/components/schemas/VariantData_SportsNbaVariantData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
SPORTS_PROPS: "#/components/schemas/VariantData_SportsPropsMarketData"
ESPORTS_LOL: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_CS2: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_DOTA2: "#/components/schemas/VariantData_EsportsVariantData"
VariantData_CryptoUpDownVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- CRYPTO_UP_DOWN
examples:
- CRYPTO_UP_DOWN
- $ref: "#/components/schemas/CryptoUpDownVariantData"
VariantData_EsportsVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/EsportsVariantData"
VariantData_SportsFifaFriendliesVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_FRIENDLIES
examples:
- SPORTS_FIFA_FRIENDLIES
- $ref: "#/components/schemas/SportsFifaFriendliesVariantData"
VariantData_SportsFifaWorldCupVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_WORLD_CUP
examples:
- SPORTS_FIFA_WORLD_CUP
- $ref: "#/components/schemas/SportsFifaWorldCupVariantData"
VariantData_SportsNbaVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_NBA
examples:
- SPORTS_NBA
- $ref: "#/components/schemas/SportsNbaVariantData"
VariantData_SportsPropsMarketData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_PROPS
examples:
- SPORTS_PROPS
- $ref: "#/components/schemas/SportsPropsMarketData"
VariantData_TweetCountVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- TWEET_COUNT
examples:
- TWEET_COUNT
- $ref: "#/components/schemas/TweetCountVariantData"
```
# Join an activity (/api/activity/join-an-activity)
`POST https://api.predict.fun/v1/activities/{activityCode}/join`
Registers the signed-in wallet for the activity named by `activityCode`, for example
`lol-worlds`.
```yaml
paths:
/activities/{activityCode}/join:
post:
tags:
- Activity
summary: Join an activity
description: >-
Registers the signed-in wallet for the activity named by `activityCode`,
for example
`lol-worlds`.
parameters:
- name: activityCode
schema:
type: string
in: path
description: The activity's code, for example `lol-worlds`.
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ActivityRegistrationResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ActivityErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
ActivityErrorDetails:
type: object
title: ActivityErrorDetails
required:
- reason
- retryable
- violations
properties:
reason:
type: string
retryable:
type: boolean
violations:
type: array
items:
$ref: "#/components/schemas/ActivityViolation"
ActivityErrorResponse:
type: object
title: ActivityErrorResponse
description: Activity-specific extension of the standard 400 error response.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
details:
$ref: "#/components/schemas/ActivityErrorDetails"
ActivityRegistration:
type: object
title: ActivityRegistration
required:
- joined
properties:
joined:
type: boolean
joinedAt:
type: string
ActivityRegistrationResponse:
type: object
title: ActivityRegistrationResponse
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/ActivityRegistration"
ActivityViolation:
type: object
title: ActivityViolation
required:
- inputIndex
- questionId
- optionId
- code
- retryable
- message
properties:
inputIndex:
type: integer
format: uint64
questionId:
type: string
optionId:
type: string
code:
type: string
retryable:
type: boolean
message:
type: string
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
```
# Get activity registration (/api/activity/get-activity-registration)
`GET https://api.predict.fun/v1/activities/{activityCode}/me/registration`
The signed-in wallet's registration for the activity named by `activityCode`, for
example `lol-worlds`.
```yaml
paths:
/activities/{activityCode}/me/registration:
get:
tags:
- Activity
summary: Get activity registration
description: >-
The signed-in wallet's registration for the activity named by
`activityCode`, for
example `lol-worlds`.
parameters:
- name: activityCode
schema:
type: string
in: path
description: The activity's code, for example `lol-worlds`.
required: true
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ActivityRegistrationResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ActivityErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
BearerAuth: []
components:
schemas:
ActivityErrorDetails:
type: object
title: ActivityErrorDetails
required:
- reason
- retryable
- violations
properties:
reason:
type: string
retryable:
type: boolean
violations:
type: array
items:
$ref: "#/components/schemas/ActivityViolation"
ActivityErrorResponse:
type: object
title: ActivityErrorResponse
description: Activity-specific extension of the standard 400 error response.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
details:
$ref: "#/components/schemas/ActivityErrorDetails"
ActivityRegistration:
type: object
title: ActivityRegistration
required:
- joined
properties:
joined:
type: boolean
joinedAt:
type: string
ActivityRegistrationResponse:
type: object
title: ActivityRegistrationResponse
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/ActivityRegistration"
ActivityViolation:
type: object
title: ActivityViolation
required:
- inputIndex
- questionId
- optionId
- code
- retryable
- message
properties:
inputIndex:
type: integer
format: uint64
questionId:
type: string
optionId:
type: string
code:
type: string
retryable:
type: boolean
message:
type: string
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
```
# Search categories and markets (/api/search/search-categories-and-markets)
`GET https://api.predict.fun/v1/search`
Full-text search across categories and markets.
Returns separate arrays for each type, sorted by relevance.
```yaml
paths:
/search:
get:
tags:
- Search
summary: Search categories and markets
description: |-
Full-text search across categories and markets.
Returns separate arrays for each type, sorted by relevance.
parameters:
- name: query
schema:
type: string
maxLength: 256
in: query
description: >-
The text to search for. It is matched against titles, market
questions and tag
names.
required: true
deprecated: false
explode: true
- name: includeResolved
schema:
type: boolean
in: query
description: >-
Whether to also return resolved categories and the markets in them.
Defaults to
`false`.
required: false
deprecated: false
explode: true
- name: limit
schema:
type: integer
format: uint64
in: query
description: Most results of each type to return, from 1 to 50. Defaults to 10.
required: false
deprecated: false
explode: true
- name: includeStats
schema:
type: boolean
in: query
description: >-
Whether to fill in `stats` with volume and liquidity figures.
Defaults to `false`,
which leaves `stats` null.
required: false
deprecated: false
explode: true
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/SearchResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
CategoryStatsData:
type: object
title: CategoryStatsData
description: Category statistics data
required:
- totalLiquidityUsd
- volumeTotalUsd
- volume24hUsd
- holdersCount
properties:
totalLiquidityUsd:
type: number
format: double
volumeTotalUsd:
type: number
format: double
volume24hUsd:
type: number
format: double
holdersCount:
type: integer
format: int64
CategoryStatus:
type: string
description: Category status
enum:
- OPEN
- RESOLVED
- REMOVED
CategoryVariantDetails:
type: object
title: CategoryVariantDetails
description: |-
What a category is about, one key per kind of category.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for a sports category.
allOf:
- $ref: "#/components/schemas/SportsCategoryDetails"
- description: Set for a sports category.
crypto:
description: >-
Set for a crypto up down category.
Superseded by `up_down`, which says the same thing for every asset
class. Both are populated for crypto so existing readers keep
working.
allOf:
- $ref: "#/components/schemas/UpDownCategoryDetails"
- description: >-
Set for a crypto up down category.
Superseded by `up_down`, which says the same thing for every
asset
class. Both are populated for crypto so existing readers keep
working.
upDown:
description: Set for an up down price category, whatever the asset class.
allOf:
- $ref: "#/components/schemas/UpDownCategoryDetails"
- description: Set for an up down price category, whatever the asset class.
tweet:
description: Set for a tweet count category.
allOf:
- $ref: "#/components/schemas/TweetCategoryDetails"
- description: Set for a tweet count category.
CategoryWithStats:
type: object
title: CategoryWithStats
description: Category data with optional inline statistics.
required:
- id
- slug
- title
- description
- imageUrl
- isNegRisk
- protocol
- isYieldBearing
- marketVariant
- createdAt
- publishedAt
- markets
- startsAt
- status
- isVisible
- resolutionProvider
- tags
properties:
id:
type: integer
format: int64
slug:
type: string
title:
type: string
shortTitle:
type: string
description: Short, human-readable label, e.g. `"BTC Up or Down 15m"`. `null`
when not available.
seriesSlug:
type: string
description: >-
Slug of the recurring series this category is a round of, e.g.
`"btc-updown-5m"`. Absent when it is not a round of one. The series
and
its next rounds are at `GET /v1/series/{slug}`.
description:
type: string
imageUrl:
type: string
isNegRisk:
type: boolean
protocol:
$ref: "#/components/schemas/Protocol"
isYieldBearing:
type: boolean
negRiskOnChainId:
type: string
description: On-chain NegRisk market ID as a 32-byte hex string.
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this category is about, replacing `variantData`.
allOf:
- $ref: "#/components/schemas/CategoryVariantDetails"
- description: What this category is about, replacing `variantData`.
createdAt:
type: string
publishedAt:
type: string
markets:
type: array
items:
$ref: "#/components/schemas/Market"
startsAt:
type: string
endsAt:
type: string
tradingSession:
description: >-
Exchange session containing this Up/Down round's entire `startsAt`
to `endsAt` window.
Session times can differ from the round's times and remain available
after closing.
Returns `null` when no applicable session covers the complete round.
Use each market's `tradingStatus` for its current trading status.
allOf:
- $ref: "#/components/schemas/TradingSession"
- description: >-
Exchange session containing this Up/Down round's entire
`startsAt` to `endsAt` window.
Session times can differ from the round's times and remain
available after closing.
Returns `null` when no applicable session covers the complete
round.
Use each market's `tradingStatus` for its current trading
status.
status:
$ref: "#/components/schemas/CategoryStatus"
isVisible:
type: boolean
resolutionProvider:
$ref: "#/components/schemas/ResolutionProvider"
tags:
type: array
items:
$ref: "#/components/schemas/Tag"
teams:
type: array
description: |-
Deprecated in favour of `variantDetails.sports.teams`. The teams
playing, where the category is a fixture.
items:
$ref: "#/components/schemas/Team"
deprecated: true
parentSlug:
type: string
description: The slug of the parent category, when this is a prop/child market.
stats:
$ref: "#/components/schemas/CategoryStatsData"
CryptoUpDownVariantData:
type: object
title: CryptoUpDownVariantData
description: Variant data for CRYPTO_UP_DOWN markets
required:
- priceFeedProvider
properties:
priceFeedProvider:
$ref: "#/components/schemas/PriceFeedProvider"
startPrice:
type: number
format: double
description: Starting price, null before market start
endPrice:
type: number
format: double
description: Ending price from Pyth oracle, null if not yet resolved
priceFeedId:
type: string
description: Pyth oracle price feed identifier
priceFeedSymbol:
type: string
description: Price feed symbol (e.g. "BTCUSDT" for Binance, "BTC_USD" for Pyth)
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
EsportsVariantData:
type: object
title: EsportsVariantData
description: Variant data for esports match categories sourced from Grid.gg.
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked series yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
Market:
type: object
title: Market
description: Full market data as returned by the API
required:
- id
- imageUrl
- title
- question
- description
- tradingStatus
- status
- isVisible
- isNegRisk
- isYieldBearing
- feeRateBps
- makerFeeBps
- oracleQuestionId
- conditionId
- resolverAddress
- outcomes
- spreadThreshold
- shareThreshold
- isBoosted
- polymarketConditionIds
- categorySlug
- createdAt
- decimalPrecision
- marketVariant
- rewards
properties:
id:
type: integer
format: int64
imageUrl:
type: string
title:
type: string
question:
type: string
description:
type: string
tradingStatus:
$ref: "#/components/schemas/MarketTradingStatus"
status:
$ref: "#/components/schemas/MarketStatus"
isVisible:
type: boolean
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
feeRateBps:
type: integer
format: int32
description: Taker fee in basis points, charged on each matched trade.
makerFeeBps:
type: integer
format: int32
description: |-
Maker fee in basis points. Always `0`: no market charges makers.
Defaults on decode so market entries cached before the field existed
still decode rather than reading as misses, and the default is the
only value it takes.
resolution:
$ref: "#/components/schemas/Outcome"
oracleQuestionId:
type: string
conditionId:
type: string
resolverAddress:
type: string
outcomes:
type: array
items:
$ref: "#/components/schemas/Outcome"
questionIndex:
type: integer
format: int32
spreadThreshold:
type: number
format: double
shareThreshold:
type: integer
format: int32
isBoosted:
type: boolean
boostStartsAt:
type: string
boostEndsAt:
type: string
polymarketConditionIds:
type: array
items:
type: string
kalshiMarketTicker:
type: string
categorySlug:
type: string
seriesSlug:
type: string
description: |-
Slug of the recurring series this market's category is a round of,
e.g. `"btc-updown-5m"`. Absent when it is not a round of one. The
series and its next rounds are at `GET /v1/series/{slug}`.
createdAt:
type: string
decimalPrecision:
type: integer
format: int32
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
allOf:
- $ref: "#/components/schemas/MarketVariantDetails"
- description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
market as a whole is about a single team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
market as a whole is about a single team.
deprecated: true
marketType:
description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
allOf:
- $ref: "#/components/schemas/MarketType"
- description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
rewards:
$ref: "#/components/schemas/MarketRewards"
MarketRewards:
type: object
title: MarketRewards
description: Reward schedule for a market.
required:
- schedule
properties:
current:
description: Active period at request time, or `null` if no rewards are accruing.
allOf:
- $ref: "#/components/schemas/RewardPeriod"
- description: Active period at request time, or `null` if no rewards are
accruing.
schedule:
type: array
description: Full schedule of past and future reward periods for this market.
items:
$ref: "#/components/schemas/RewardPeriod"
MarketStatsData:
type: object
title: MarketStatsData
description: Market statistics data
required:
- totalLiquidityUsd
- liquidity3cAskUsd
- volumeTotalUsd
- volume24hUsd
properties:
totalLiquidityUsd:
type: number
format: double
liquidity3cAskUsd:
type: number
format: double
volumeTotalUsd:
type: number
format: double
volume24hUsd:
type: number
format: double
MarketStatus:
type: string
description: |-
Market lifecycle state, from registration through resolution.
`Removed` is a synthetic status reported for markets that have been
withdrawn, meaning it is not part of the normal lifecycle progression.
enum:
- REGISTERED
- PRICE_PROPOSED
- PRICE_DISPUTED
- PAUSED
- UNPAUSED
- RESOLVED
- REMOVED
MarketTradingStatus:
type: string
description: Trading status derived from market visibility and deletion state.
enum:
- OPEN
- MATCHING_NOT_ENABLED
- CANCEL_ONLY
- CLOSED
MarketType:
type: string
description: >-
Market type (DB `market.market_type_id` values as repr).
Classifies what kind of prediction an individual market represents,
independent of the category it belongs to. Works alongside
[`MarketVariant`]:
the variant describes how the category container renders; the market
type
describes the prediction mechanic of the individual market.
enum:
- SPORTS_MONEYLINE
- SPORTS_SPREADS
- SPORTS_TOTALS
- SPORTS_BOTH_TEAMS_TO_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_EXACT_SCORE
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_TEAM_TOTAL_CORNERS
- SPORTS_CORNERS_ODD_EVEN
- SPORTS_PLAYER_GOALS
- SPORTS_PLAYER_ASSISTS
- SPORTS_PLAYER_GOALS_PLUS_ASSISTS
- SPORTS_PLAYER_SHOTS
- SPORTS_PLAYER_SHOTS_ON_TARGET
- SPORTS_PLAYER_GOALKEEPER_SAVES
- SPORTS_TEAM_TO_ADVANCE
- SPORTS_EXTRA_TIME
- SPORTS_PENALTY_SHOOTOUT
- SPORTS_TEAM_TOTALS
- SPORTS_CHILD_MONEYLINE
- SPORTS_MAP_HANDICAP
- SPORTS_BOTH_TEAMS_TO_SCORE_FIRST_HALF
- SPORTS_BOTH_TEAMS_TO_SCORE_SECOND_HALF
- SPORTS_FIRST_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- SPORTS_FIRST_CORNER
- SPORTS_FIRST_HALF_TOTALS
- SPORTS_SECOND_HALF_TOTALS
- SPORTS_FIRST_HALF_TEAM_TOTALS
- SPORTS_SECOND_HALF_TEAM_TOTALS
- SPORTS_FIRST_BLOOD_GAME
- SPORTS_KILL_OVER_UNDER_GAME
- SPORTS_ROUND_HANDICAP
- SPORTS_ROUND_TOTALS
- SPORTS_ANYTIME_TOUCHDOWNS
- SPORTS_RACE_TO_POINTS
- SPORTS_ODD_EVEN
MarketVariant:
type: string
description: |-
Classifies the market template type.
Controls the UI layout and trading mechanics of a category. See also
[`MarketType`] which classifies individual markets within a category.
enum:
- DEFAULT
- SPORTS_MATCH
- CRYPTO_UP_DOWN
- TWEET_COUNT
- SPORTS_TEAM_MATCH
- SPORTS_NBA
- SPORTS_FIFA_WORLD_CUP
- SPORTS_EXACT_SCORE
- SPORTS_HALFTIME_RESULT
- SPORTS_PROPS
- SPORTS_FIFA_FRIENDLIES
- ESPORTS_LOL
- ESPORTS_CS2
- ESPORTS_DOTA2
- SPORTS_FIRST_TO_SCORE
- SPORTS_TOTAL_CORNERS
- SPORTS_SECOND_HALF_RESULT
- UP_DOWN
MarketVariantDetails:
type: object
title: MarketVariantDetails
description: >-
What a market is about, one key per kind of market.
Grouping by kind rather than discriminating on a type means a kind that
gains a payload is a new key, and one that loses it is a key removed,
with
nothing to keep in step. A market names the kinds that apply to it,
which
today is at most one.
Add a kind by adding a key. Each is filled independently, so a populator
sets its own key on the value already there rather than replacing it.
properties:
sports:
description: Set for a market of a sports category.
allOf:
- $ref: "#/components/schemas/SportsMarketDetails"
- description: Set for a market of a sports category.
MarketWithStats:
type: object
title: MarketWithStats
description: Market data with optional inline statistics.
required:
- id
- imageUrl
- title
- question
- description
- tradingStatus
- status
- isVisible
- isNegRisk
- isYieldBearing
- feeRateBps
- makerFeeBps
- oracleQuestionId
- conditionId
- resolverAddress
- outcomes
- spreadThreshold
- shareThreshold
- isBoosted
- polymarketConditionIds
- categorySlug
- createdAt
- decimalPrecision
- marketVariant
- rewards
properties:
id:
type: integer
format: int64
imageUrl:
type: string
title:
type: string
question:
type: string
description:
type: string
tradingStatus:
$ref: "#/components/schemas/MarketTradingStatus"
status:
$ref: "#/components/schemas/MarketStatus"
isVisible:
type: boolean
isNegRisk:
type: boolean
isYieldBearing:
type: boolean
feeRateBps:
type: integer
format: int32
description: Taker fee in basis points, charged on each matched trade.
makerFeeBps:
type: integer
format: int32
description: |-
Maker fee in basis points. Always `0`: no market charges makers.
Defaults on decode so market entries cached before the field existed
still decode rather than reading as misses, and the default is the
only value it takes.
resolution:
$ref: "#/components/schemas/Outcome"
oracleQuestionId:
type: string
conditionId:
type: string
resolverAddress:
type: string
outcomes:
type: array
items:
$ref: "#/components/schemas/Outcome"
questionIndex:
type: integer
format: int32
spreadThreshold:
type: number
format: double
shareThreshold:
type: integer
format: int32
isBoosted:
type: boolean
boostStartsAt:
type: string
boostEndsAt:
type: string
polymarketConditionIds:
type: array
items:
type: string
kalshiMarketTicker:
type: string
categorySlug:
type: string
seriesSlug:
type: string
description: |-
Slug of the recurring series this market's category is a round of,
e.g. `"btc-updown-5m"`. Absent when it is not a round of one. The
series and its next rounds are at `GET /v1/series/{slug}`.
createdAt:
type: string
decimalPrecision:
type: integer
format: int32
marketVariant:
$ref: "#/components/schemas/MarketVariant"
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/VariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
allOf:
- $ref: "#/components/schemas/MarketVariantDetails"
- description: >-
What this market is about. Absent when the market is about the
fixture
as a whole, whose teams its outcomes name.
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
market as a whole is about a single team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
market as a whole is about a single team.
deprecated: true
marketType:
description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
allOf:
- $ref: "#/components/schemas/MarketType"
- description: |-
Classification of the individual market's prediction mechanic.
Null for markets created before this field was introduced.
rewards:
$ref: "#/components/schemas/MarketRewards"
stats:
$ref: "#/components/schemas/MarketStatsData"
Outcome:
type: object
title: Outcome
description: Outcome data (from markets, positions, etc.)/// Outcome data (from
markets, positions, etc.)
required:
- name
- indexSet
- onChainId
properties:
name:
type: string
indexSet:
type: integer
format: int32
onChainId:
type: string
description: bigint string
status:
$ref: "#/components/schemas/OutcomeStatus"
bestBid:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes, or
poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is embedded
in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the next.
That is what caps the shared-cache TTL on those routes at seconds,
and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: subscribe to the WebSocket firehose for live quotes,
or poll
`GET /v1/markets/:id/quote` (or `GET /v1/markets/quotes` for a
batch),
which returns the same price levels without the catalogue around
them.
Those routes quote the market once, against the outcome whose
`indexSet`
is 1, so a consumer of the other outcome derives it as described
there
rather than reading it pre-inverted from here.
Top-of-book moves on every trade, and because `Outcome` is
embedded in
`Market` and `Market` in `Category`, these two fields make every
market
listing and every category page change from one second to the
next.
That is what caps the shared-cache TTL on those routes at
seconds, and
it is why a majority of their cache entries expire into a full
origin
fetch rather than a revalidation. Nothing else in the catalogue
payload
changes anywhere near this fast.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
bestAsk:
description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead, and
why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
allOf:
- $ref: "#/components/schemas/PriceLevel"
- description: >-
`None` for resolved outcomes or when the side is empty.
Deprecated: see [`Outcome::best_bid`] for what to use instead,
and why.
Still populated; the attribute is a signal to consumers, not a
removal.
deprecated: true
team:
description: |-
Deprecated in favour of `variantDetails.sports.team`. Set when this
outcome resolves to a specific team.
deprecated: true
allOf:
- $ref: "#/components/schemas/Team"
- description: >-
Deprecated in favour of `variantDetails.sports.team`. Set when
this
outcome resolves to a specific team.
deprecated: true
variantData:
description: |-
Deprecated in favour of `variantDetails`, which says the same thing
without a type of its own.
deprecated: true
allOf:
- $ref: "#/components/schemas/OutcomeVariantData"
- description: >-
Deprecated in favour of `variantDetails`, which says the same
thing
without a type of its own.
deprecated: true
variantDetails:
description: What this outcome is about. Absent when it is about neither team.
allOf:
- $ref: "#/components/schemas/OutcomeVariantDetails"
- description: What this outcome is about. Absent when it is about neither team.
OutcomeStatus:
type: string
description: Resolution status of a market outcome.
enum:
- WON
- LOST
OutcomeVariantData:
type: object
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
oneOf:
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
- $ref: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
discriminator:
propertyName: type
mapping:
SPORTS_NBA: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_LOL: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_CS2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
ESPORTS_DOTA2: "#/components/schemas/OutcomeVariantData_SportsTeamOutcomeData"
OutcomeVariantData_SportsTeamOutcomeData:
description: |-
Outcome-level variant data, discriminated by sport type.
Different leagues carry different outcome metadata.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/SportsTeamOutcomeData"
OutcomeVariantDetails:
type: object
title: OutcomeVariantDetails
description: |-
What an outcome is about, one key per kind of market.
See [`MarketVariantDetails`].
properties:
sports:
description: Set for an outcome that resolves to a team.
allOf:
- $ref: "#/components/schemas/SportsOutcomeDetails"
- description: Set for an outcome that resolves to a team.
PriceFeedProvider:
type: string
description: Provider of the price feed backing a crypto market.
enum:
- PYTH
- BINANCE
- CHAINLINK
- ATLAS
PriceLevel:
type: object
title: PriceLevel
required:
- price
- size
properties:
price:
type: number
format: double
description: In [0.0, 1.0].
size:
type: number
format: double
Protocol:
type: string
description: |-
The protocol a category's markets trade on. Every market in a category
shares it, and it decides which exchange contracts a client talks to.
enum:
- LEGACY
- PREDICT
ResolutionProvider:
type: string
description: Resolution provider for a category (maps to
`resolution_provider_type` table).
enum:
- PREDICT_DOT_FUN
- THREE_PO
- CHAINLINK
- ATLAS
RewardPeriod:
type: object
title: RewardPeriod
description: A single span during which a market accrues rewards at a fixed
hourly rate.
required:
- hourlyRate
- startsAt
- endsAt
properties:
hourlyRate:
type: integer
format: int32
description: Reward points earned per hour while this period is active.
startsAt:
type: string
endsAt:
type: string
ScoreboardSource:
type: string
description: The source a scoreboard is built on.
enum:
- GRID
- POLYMARKET
- PREDICT_DOT_FUN
SearchData:
type: object
title: SearchData
description: Search results data
required:
- categories
- markets
properties:
categories:
type: array
items:
$ref: "#/components/schemas/CategoryWithStats"
markets:
type: array
items:
$ref: "#/components/schemas/MarketWithStats"
SearchResponse:
type: object
title: SearchResponse
description: Response for GET /v1/search
required:
- success
- data
properties:
success:
type: boolean
data:
$ref: "#/components/schemas/SearchData"
SportsCategoryDetails:
type: object
title: SportsCategoryDetails
description: What a sports category is about.
required:
- provider
- teams
properties:
provider:
description: The provider that supplies the fixture.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that supplies the fixture.
providerEventId:
type: string
description: The provider's own id for the fixture, where it has one.
teams:
type: array
description: The two sides of the fixture.
items:
$ref: "#/components/schemas/SportsEventTeam"
scoreboard:
description: Absent until a source has reported on the match.
allOf:
- $ref: "#/components/schemas/SportsScoreboard"
- description: Absent until a source has reported on the match.
SportsDataProvider:
type: string
description: Sports data provider.
enum:
- PREDICT_SPORTS
- GRID
- POLYMARKET
SportsEventTeam:
type: object
title: SportsEventTeam
description: A sportsdata provider team as exposed in category variant data.
required:
- id
properties:
id:
type: integer
format: int64
description: Team identifier.
name:
type: string
abbreviation:
type: string
description: Team key abbreviation (e.g., "MIN", "SA"). Null when not available.
providerTeamId:
type: string
description: The team identifier used by the sportsdata provider. Null when no
game is linked.
isHome:
type: boolean
description: >-
Marks the side the fixture lists as home, which may be a neutral
venue. Null when the
provider does not say.
record:
description: Omitted when the provider sends none, or sends one whose format is
not known.
allOf:
- $ref: "#/components/schemas/SportsTeamRecord"
- description: Omitted when the provider sends none, or sends one whose format is
not known.
color:
type: string
description: >-
Team colour as a hex string from the provider. Omitted when the
provider does not send
one.
SportsFifaFriendliesVariantData:
type: object
title: SportsFifaFriendliesVariantData
description: Variant data for SPORTS_FIFA_FRIENDLIES categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsFifaWorldCupVariantData:
type: object
title: SportsFifaWorldCupVariantData
description: Variant data for SPORTS_FIFA_WORLD_CUP categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsMarketDetails:
type: object
title: SportsMarketDetails
description: What a market of a sports category is about.
properties:
provider:
description: The provider that links the team. Absent when no team is named.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team. Absent when no team is named.
team:
description: The team this market is about, when it is about one. .
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this market is about, when it is about one. .
line:
type: number
format: double
description: >-
The line this market is about: a total, a spread, or a player count.
TODO which side of a spread the line runs is not stated. It belongs
to
the market's `team`, so it needs the importer to record the subject:
polymarket orders a spread's outcomes subject first, and where the
feed
carries `marketMetadata.opticOddsTeamId` that agrees with it. Until
then
only the deprecated `variantData.spreadSide` says anything, and only
for
soccer, where a slug pattern happens to name the side.
gameNumber:
type: integer
format: int32
SportsNbaVariantData:
type: object
title: SportsNbaVariantData
description: Variant data for SPORTS_NBA categories (SportsDataIO).
required:
- provider
- teams
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
providerEventId:
type: string
description: Null when the category has no linked game yet.
teams:
type: array
items:
$ref: "#/components/schemas/SportsEventTeam"
SportsOutcomeDetails:
type: object
title: SportsOutcomeDetails
description: >-
What an outcome of a sports market is about.
Carries no type of its own, for the same reason as
[`SportsMarketDetails`].
required:
- provider
- team
properties:
provider:
description: The provider that links the team.
allOf:
- $ref: "#/components/schemas/SportsDataProvider"
- description: The provider that links the team.
team:
description: The team this outcome resolves to.
allOf:
- $ref: "#/components/schemas/SportsEventTeam"
- description: The team this outcome resolves to.
SportsPropsMarketData:
type: object
title: SportsPropsMarketData
description: |-
Per-market data for `SPORTS_PROPS` prop markets.
Fields are market-type-specific: `spreadSide` is set for spread markets,
`line` is set for totals markets. Both-teams-to-score markets emit no
`variantData` of this shape.
properties:
spreadSide:
description: Which side of the parent match this spread market is on. Present
for spread markets only.
allOf:
- $ref: "#/components/schemas/TeamSide"
- description: Which side of the parent match this spread market is on. Present
for spread markets only.
line:
type: number
format: double
description: The line value for this totals market. Present for totals markets
only.
SportsScoreboard:
type: object
title: SportsScoreboard
description: How a match stands.
required:
- source
- score
- games
properties:
source:
description: The source the record is built on.
allOf:
- $ref: "#/components/schemas/ScoreboardSource"
- description: The source the record is built on.
bestOf:
type: integer
format: int32
isLive:
type: boolean
finished:
type: boolean
currentGame:
type: integer
format: int32
description: Counted from one.
period:
type: string
description: "As the feed labels it: `1H`, `Q3`, `2/3`."
clock:
type: string
description: >-
The game clock as the live feed shows it. Its meaning depends on the
sport: time left in
the period for basketball, time played for soccer.
score:
type: array
description: Games won in a series, the match score otherwise.
items:
$ref: "#/components/schemas/SportsTeamScore"
games:
type: array
items:
$ref: "#/components/schemas/SportsScoreboardGame"
SportsScoreboardGame:
type: object
title: SportsScoreboardGame
description: One game of a best-of series.
required:
- gameNumber
- isLive
- finished
- scores
properties:
gameNumber:
type: integer
format: int32
description: Counted from one.
isLive:
type: boolean
finished:
type: boolean
winnerTeamId:
type: integer
format: int64
scores:
type: array
description: Empty when only the winner is known.
items:
$ref: "#/components/schemas/SportsTeamScore"
SportsTeamOutcomeData:
type: object
title: SportsTeamOutcomeData
description: Outcome variant data for sports markets where the outcome maps to a team.
required:
- provider
- team
properties:
provider:
$ref: "#/components/schemas/SportsDataProvider"
team:
$ref: "#/components/schemas/SportsEventTeam"
SportsTeamRecord:
type: object
title: SportsTeamRecord
description: A team's win-loss record, in one shape whatever the sport or provider.
required:
- wins
- losses
properties:
wins:
type: integer
format: int32
losses:
type: integer
format: int32
draws:
type: integer
format: int32
description: Ties count as draws. Omitted where the sport's record has no draws,
as in basketball.
overtimeLosses:
type: integer
format: int32
description: Ice hockey losses after regulation, counted apart from `losses`.
Omitted elsewhere.
SportsTeamScore:
type: object
title: SportsTeamScore
description: One team's count in a series or a game.
required:
- teamId
- score
properties:
teamId:
type: integer
format: int64
description: The id the category's `teams` entries carry.
score:
type: integer
format: int32
description: Games won, goals, rounds or kills, by what the entry is.
Tag:
type: object
title: Tag
description: Tag data
required:
- id
- name
properties:
id:
type: string
description: bigint string
name:
type: string
level:
type: integer
format: int32
description: >-
Hierarchy level of the tag (1, 2, or 3), or null for flat tags. Tags
form a
tree up to three levels deep, e.g. Sports -> Soccer -> EPL.
parentId:
type: string
description: >-
Id of the parent tag as a bigint string, or null for root and flat
tags.
Together with `level` this allows rendering nested tag menus.
makerRebateBps:
type: integer
format: int32
description: >-
Maker rebate in basis points for fills on categories carrying this
tag,
or null if no rebate applies.
Team:
type: object
title: Team
description: Sports team identity.
required:
- id
- name
- abbreviation
- league
properties:
id:
type: integer
format: int64
name:
type: string
abbreviation:
type: string
alias:
type: string
league:
type: string
TeamSide:
type: string
description: Which side of a sports match a team plays on.
enum:
- HOME
- AWAY
TradingSession:
type: object
title: TradingSession
description: Exchange session during which the settlement price is live, without
trading buffers.
required:
- opensAt
- closesAt
properties:
opensAt:
type: string
description: Session opening time as an ISO 8601 UTC timestamp with millisecond
precision.
closesAt:
type: string
description: Session closing time as an ISO 8601 UTC timestamp with millisecond
precision.
TweetCategoryDetails:
type: object
title: TweetCategoryDetails
description: What a tweet count category is about.
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: The account whose posts are counted.
tweetCount:
type: integer
format: int64
description: Posts counted so far within the category's window.
TweetCountVariantData:
type: object
title: TweetCountVariantData
description: Variant data for TWEET_COUNT markets
required:
- xAccountUsername
- tweetCount
properties:
xAccountUsername:
type: string
description: X (Twitter) account username being tracked
tweetCount:
type: integer
format: int64
description: Current count of tweets within the category date range
UpDownCategoryDetails:
type: object
title: UpDownCategoryDetails
description: What an up down price category is about, whatever the asset class.
required:
- priceFeedProvider
properties:
priceFeedProvider:
description: Who publishes the price this category settles against.
allOf:
- $ref: "#/components/schemas/PriceFeedProvider"
- description: Who publishes the price this category settles against.
priceFeedId:
type: string
description: The feed's own identifier, where it has one.
priceFeedSymbol:
type: string
description: The symbol the feed publishes under, eg. `BTCUSDT` or `SPYUSDT`.
startPrice:
type: number
format: double
description: The price at the start of the window, once the window has opened.
endPrice:
type: number
format: double
description: The price at the end of the window, once it has closed.
VariantData:
type: object
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
oneOf:
- $ref: "#/components/schemas/VariantData_CryptoUpDownVariantData"
- $ref: "#/components/schemas/VariantData_TweetCountVariantData"
- $ref: "#/components/schemas/VariantData_SportsNbaVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
- $ref: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
- $ref: "#/components/schemas/VariantData_SportsPropsMarketData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
- $ref: "#/components/schemas/VariantData_EsportsVariantData"
discriminator:
propertyName: type
mapping:
CRYPTO_UP_DOWN: "#/components/schemas/VariantData_CryptoUpDownVariantData"
TWEET_COUNT: "#/components/schemas/VariantData_TweetCountVariantData"
SPORTS_NBA: "#/components/schemas/VariantData_SportsNbaVariantData"
SPORTS_FIFA_WORLD_CUP: "#/components/schemas/VariantData_SportsFifaWorldCupVariantData"
SPORTS_FIFA_FRIENDLIES: "#/components/schemas/VariantData_SportsFifaFriendliesVariantData"
SPORTS_PROPS: "#/components/schemas/VariantData_SportsPropsMarketData"
ESPORTS_LOL: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_CS2: "#/components/schemas/VariantData_EsportsVariantData"
ESPORTS_DOTA2: "#/components/schemas/VariantData_EsportsVariantData"
VariantData_CryptoUpDownVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- CRYPTO_UP_DOWN
examples:
- CRYPTO_UP_DOWN
- $ref: "#/components/schemas/CryptoUpDownVariantData"
VariantData_EsportsVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- ESPORTS_DOTA2
examples:
- ESPORTS_DOTA2
- $ref: "#/components/schemas/EsportsVariantData"
VariantData_SportsFifaFriendliesVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_FRIENDLIES
examples:
- SPORTS_FIFA_FRIENDLIES
- $ref: "#/components/schemas/SportsFifaFriendliesVariantData"
VariantData_SportsFifaWorldCupVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_FIFA_WORLD_CUP
examples:
- SPORTS_FIFA_WORLD_CUP
- $ref: "#/components/schemas/SportsFifaWorldCupVariantData"
VariantData_SportsNbaVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_NBA
examples:
- SPORTS_NBA
- $ref: "#/components/schemas/SportsNbaVariantData"
VariantData_SportsPropsMarketData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- SPORTS_PROPS
examples:
- SPORTS_PROPS
- $ref: "#/components/schemas/SportsPropsMarketData"
VariantData_TweetCountVariantData:
description: >-
Variant-specific metadata, discriminated by the `type` field.
Known variant types are deserialized into typed structs. Unknown variant
types are handled gracefully by the [`deserialize_variant_data`] helper
on parent structs so that new upstream types don't break
deserialization.
allOf:
- type: object
required:
- type
properties:
type:
type: string
enum:
- TWEET_COUNT
examples:
- TWEET_COUNT
- $ref: "#/components/schemas/TweetCountVariantData"
```
# Get available languages (/api/translations/get-available-languages)
`GET https://api.predict.fun/v1/languages`
Get all enabled translation languages. Use the returned codes with the
`/categories/:slug/translations` endpoint.
```yaml
paths:
/languages:
get:
tags:
- Translations
summary: Get available languages
description: |-
Get all enabled translation languages. Use the returned codes with the
`/categories/:slug/translations` endpoint.
responses:
"200":
description: ""
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/LanguagesResponse"
"400":
description: Bad request (400) - Invalid input or parameters
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"401":
description: Unauthorized (401) - Missing or invalid authentication
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"403":
description: Forbidden (403) - Valid auth but insufficient permissions
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Not found (404) - Resource doesn't exist
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"410":
description: Gone (410) - Resource has been permanently removed
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"429":
description: Too many requests (429) - Rate limit exceeded
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"500":
description: Internal server error (500) - Unexpected error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"502":
description: Bad gateway (502) - Upstream API error
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
"503":
description: Service unavailable (503) - Upstream API unreachable
content:
application/json; charset=utf-8:
schema:
$ref: "#/components/schemas/ErrorResponse"
security:
- ApiKeyAuth: []
components:
schemas:
ErrorCode:
type: string
description: Machine-readable error codes for all API error responses.
enum:
- unauthorized
- forbidden
- not_found
- gone
- too_many_requests
- internal_server_error
- bad_gateway
- service_unavailable
- bad_request
- activity_invalid_input
- activity_lock_rejected
- activity_state_conflict
- invalid_cursor
- token_not_found
- create_order_invalid_fee_rate_bps
- create_order_invalid_nonce
- create_order_invalid_salt
- create_order_invalid_slippage_bps
- create_order_invalid_signer_address
- create_order_invalid_token_id
- create_order_invalid_signature_hex
- create_order_invalid_expiration_timestamp
- create_order_invalid_numeric_value
- create_order_invalid_decimal_value
- create_order_market_token_not_found
- create_order_market_not_trading
- create_order_market_orders_disabled
- create_order_trading_disabled
- create_order_signer_mismatch
- create_order_reserved_balance_policy_invalid
- create_order_fill_or_kill_not_supported
- create_order_post_only_not_supported
- create_order_maker_signer_mismatch
- create_order_expiry_too_far
- create_order_expiry_too_soon
- create_order_min_order_value_not_met
- create_order_min_order_size_not_met
- create_order_limit_amounts_mismatch
- create_order_price_precision_too_high
- create_order_market_amounts_mismatch
- create_order_slippage_non_market
- create_order_maker_fee_out_of_range
- create_order_taker_fee_out_of_range
- create_order_fee_rate_too_low
- create_order_price_field_zero
- create_order_amount_field_zero
- create_order_price_field_precision_invalid
- create_order_contract_order_expired
- create_order_contract_invalid_signature
- create_order_contract_fee_too_high
- create_order_contract_invalid_token_id
- create_order_contract_order_filled_or_cancelled
- create_order_contract_invalid_nonce
- create_order_contract_invalid_signature_length
- create_order_contract_paused
- create_order_exchange_paused
- create_order_unsupported_wallet
- create_order_hash_mismatch
- create_order_duplicate_order
- create_order_max_orders_per_market_exceeded
- create_order_insufficient_collateral_allowance
- create_order_insufficient_collateral_balance
- create_order_exchange_not_approved
- create_order_neg_risk_adapter_not_approved
- create_order_insufficient_shares_balance
- create_order_price_out_of_range
- blocktrade_duplicate_order
- blocktrade_self_fulfil
- blocktrade_fulfil_symmetry
- blocktrade_complement_not_supported
- blocktrade_max_open_orders_exceeded
ErrorResponse:
type: object
title: ErrorResponse
description: |-
Structured error response body.
Every error path in the API produces this shape.
required:
- success
- code
- error
- message
- timestamp
properties:
success:
type: boolean
description: Always `false` for errors
code:
type: integer
format: uint16
description: HTTP status code
error:
description: |-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g. `unauthorized`).
allOf:
- $ref: "#/components/schemas/ErrorCode"
- description: >-
Stable machine-readable error code for client-side matching.
For 400 responses this is the granular bad-request code (e.g.
`create_order_insufficient_collateral_allowance`). For all other
responses it is the HTTP-status-derived code (e.g.
`unauthorized`).
message:
type: string
description: Human-readable error message
timestamp:
type: string
description: RFC 3339 timestamp of when the error occurred
trace:
type: string
description: Trace ID for correlating with server logs
examples:
- code: 500
error: internal_server_error
message: Internal server error
success: false
timestamp: 2026-01-01T00:00:00.000000Z
trace: null
Language:
type: object
title: Language
required:
- code
- name
properties:
code:
type: string
name:
type: string
LanguagesResponse:
type: object
title: LanguagesResponse
description: Response for GET /v1/languages
required:
- success
- data
properties:
success:
type: boolean
data:
type: array
items:
$ref: "#/components/schemas/Language"
```
# Subscribe (/websocket/requests/subscribe)
You send these messages to Predict WebSocket API.
Address: `/ws`
## Servers
- `wss://ws.predict.fun` (BNB Mainnet, wss)
- `wss://ws-testnet.predict.fun` (BNB Testnet, wss)
## Authorization
Connecting to `mainnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
Connecting to `testnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
## Messages
### Subscribe request
Content type: `application/json`
Payload: `SubscribePayload`
Example payload:
```json
{
"method": "subscribe",
"requestId": 1,
"params": [
"predictOrderbook/123"
]
}
```
## Reply
Sent to `/ws`.
### Response
Content type: `application/json`
Payload: `ResponsePayload`
Example payload:
```json
{
"type": "R",
"requestId": 1,
"success": true
}
```
## Types
```ts
export type SubscribeMessage = SubscribePayload;
export interface SubscribePayload {
method: "subscribe";
requestId: RequestId;
/** The topic to subscribe to. Only the first entry is read. */
params: Topic[];
}
/**
* The answer to a subscribe, unsubscribe or setLanguage request. A frame the server cannot
* read (invalid JSON, an unknown `method`, or a missing `requestId` or `params`) is
* answered with `requestId` `-1` and the error `invalid_json`. A frame over 8 KiB closes
* the connection.
*
*/
export interface ResponsePayload {
type: "R";
requestId: RequestId;
success: boolean;
error?: Error;
}
/**
* A number you choose, echoed on the response so you can match the two. Use a
* non-negative one: the server answers a frame it cannot read with `-1`.
*
*/
export type RequestId = number;
/** A topic name and its parameter, such as `predictOrderbook/123`. */
export type Topic = string;
/** Present only when `success` is `false`. */
export interface Error {
/**
* - `invalid_json`: the frame could not be read as a request.
* - `invalid_topic`: the topic is missing, unknown or has an invalid parameter.
* - `invalid_params`: setLanguage without a language code.
* - `invalid_credentials`: the wallet JWT is invalid, expired or revoked.
* - `internal_server_error`: the server failed to check the request.
*
*/
code: "invalid_json" | "invalid_topic" | "invalid_params" | "invalid_credentials" | "internal_server_error";
/** What was wrong. Absent for `invalid_json`. */
message?: string;
}
```
# Unsubscribe (/websocket/requests/unsubscribe)
You send these messages to Predict WebSocket API.
Address: `/ws`
## Servers
- `wss://ws.predict.fun` (BNB Mainnet, wss)
- `wss://ws-testnet.predict.fun` (BNB Testnet, wss)
## Authorization
Connecting to `mainnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
Connecting to `testnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
## Messages
### Unsubscribe request
Content type: `application/json`
Payload: `UnsubscribePayload`
Example payload:
```json
{
"method": "unsubscribe",
"requestId": 2,
"params": [
"predictOrderbook/123"
]
}
```
## Reply
Sent to `/ws`.
### Response
Content type: `application/json`
Payload: `ResponsePayload`
Example payload:
```json
{
"type": "R",
"requestId": 1,
"success": true
}
```
## Types
```ts
export type UnsubscribeMessage = UnsubscribePayload;
export interface UnsubscribePayload {
method: "unsubscribe";
requestId: RequestId;
/** The topic to unsubscribe from. Only the first entry is read. */
params: Topic[];
}
/**
* The answer to a subscribe, unsubscribe or setLanguage request. A frame the server cannot
* read (invalid JSON, an unknown `method`, or a missing `requestId` or `params`) is
* answered with `requestId` `-1` and the error `invalid_json`. A frame over 8 KiB closes
* the connection.
*
*/
export interface ResponsePayload {
type: "R";
requestId: RequestId;
success: boolean;
error?: Error;
}
/**
* A number you choose, echoed on the response so you can match the two. Use a
* non-negative one: the server answers a frame it cannot read with `-1`.
*
*/
export type RequestId = number;
/** A topic name and its parameter, such as `predictOrderbook/123`. */
export type Topic = string;
/** Present only when `success` is `false`. */
export interface Error {
/**
* - `invalid_json`: the frame could not be read as a request.
* - `invalid_topic`: the topic is missing, unknown or has an invalid parameter.
* - `invalid_params`: setLanguage without a language code.
* - `invalid_credentials`: the wallet JWT is invalid, expired or revoked.
* - `internal_server_error`: the server failed to check the request.
*
*/
code: "invalid_json" | "invalid_topic" | "invalid_params" | "invalid_credentials" | "internal_server_error";
/** What was wrong. Absent for `invalid_json`. */
message?: string;
}
```
# Set language (/websocket/requests/set-language)
You send these messages to Predict WebSocket API.
Address: `/ws`
## Servers
- `wss://ws.predict.fun` (BNB Mainnet, wss)
- `wss://ws-testnet.predict.fun` (BNB Testnet, wss)
## Authorization
Connecting to `mainnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
Connecting to `testnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
## Messages
### Set language request
Content type: `application/json`
Payload: `SetLanguagePayload`
Example payload:
```json
{
"method": "setLanguage",
"requestId": 3,
"params": [
"es"
]
}
```
## Reply
Sent to `/ws`.
### Response
Content type: `application/json`
Payload: `ResponsePayload`
Example payload:
```json
{
"type": "R",
"requestId": 1,
"success": true
}
```
## Types
```ts
export type SetLanguageMessage = SetLanguagePayload;
export interface SetLanguagePayload {
method: "setLanguage";
requestId: RequestId;
/** The language code. Only the first entry is read. */
params: string[];
}
/**
* The answer to a subscribe, unsubscribe or setLanguage request. A frame the server cannot
* read (invalid JSON, an unknown `method`, or a missing `requestId` or `params`) is
* answered with `requestId` `-1` and the error `invalid_json`. A frame over 8 KiB closes
* the connection.
*
*/
export interface ResponsePayload {
type: "R";
requestId: RequestId;
success: boolean;
error?: Error;
}
/**
* A number you choose, echoed on the response so you can match the two. Use a
* non-negative one: the server answers a frame it cannot read with `-1`.
*
*/
export type RequestId = number;
/** Present only when `success` is `false`. */
export interface Error {
/**
* - `invalid_json`: the frame could not be read as a request.
* - `invalid_topic`: the topic is missing, unknown or has an invalid parameter.
* - `invalid_params`: setLanguage without a language code.
* - `invalid_credentials`: the wallet JWT is invalid, expired or revoked.
* - `internal_server_error`: the server failed to check the request.
*
*/
code: "invalid_json" | "invalid_topic" | "invalid_params" | "invalid_credentials" | "internal_server_error";
/** What was wrong. Absent for `invalid_json`. */
message?: string;
}
```
# Heartbeat (/websocket/connection/heartbeat)
Predict WebSocket API sends these messages to you.
Address: `/ws`
## Servers
- `wss://ws.predict.fun` (BNB Mainnet, wss)
- `wss://ws-testnet.predict.fun` (BNB Testnet, wss)
## Authorization
Connecting to `mainnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
Connecting to `testnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
## Messages
### Heartbeat
Content type: `application/json`
Payload: `HeartbeatPayload`
Example payload:
```json
{
"type": "M",
"topic": "heartbeat",
"data": 1736696400000
}
```
## Reply
Sent to `/ws`.
### Heartbeat echo
Content type: `application/json`
Payload: `HeartbeatReplyPayload`
Example payload:
```json
{
"method": "heartbeat",
"data": 1736696400000
}
```
## Types
```ts
export type HeartbeatMessage = HeartbeatPayload;
export interface HeartbeatPayload {
type: "M";
topic: "heartbeat";
/** The server time, to echo back. */
data: number;
}
export interface HeartbeatReplyPayload {
method: "heartbeat";
/** The `data` of the latest heartbeat, unchanged. */
data: number;
}
```
# Reconnect notice (/websocket/connection/reconnect-notice)
Predict WebSocket API sends these messages to you.
Address: `/ws`
## Servers
- `wss://ws.predict.fun` (BNB Mainnet, wss)
- `wss://ws-testnet.predict.fun` (BNB Testnet, wss)
## Authorization
Connecting to `mainnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
Connecting to `testnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
## Messages
### Reconnect notice
Content type: `application/json`
Payload: `ReconnectPayload`
Example payload:
```json
{
"type": "M",
"topic": "system",
"data": {
"event": "reconnect",
"reason": "server_shutdown",
"graceMs": 7431
}
}
```
## Types
```ts
export type ReconnectMessage = ReconnectPayload;
export interface ReconnectPayload {
type: "M";
/** Reserved. It cannot be subscribed to, and its messages arrive unasked. */
topic: "system";
data: {
/** `reconnect`. Treat an unknown value as reconnect soon. */
event: string;
/** `server_shutdown`. Treat an unknown value as reconnect soon. */
reason: string;
/** Roughly how long the connection keeps delivering before it closes. */
graceMs: number;
};
}
```
# Order book (/websocket/topics/order-book)
Predict WebSocket API sends these messages to you.
Address: `/ws`
## Servers
- `wss://ws.predict.fun` (BNB Mainnet, wss)
- `wss://ws-testnet.predict.fun` (BNB Testnet, wss)
## Authorization
Connecting to `mainnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
Connecting to `testnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
## Messages
### Order book
Content type: `application/json`
Payload: `OrderbookPayload`
Example payload:
```json
{
"type": "M",
"topic": "predictOrderbook/123",
"data": {
"version": 1,
"marketId": 123,
"updateTimestampMs": 1736696400000,
"orderCount": 42,
"asks": [
[
0.62,
1500
],
[
0.63,
800
]
],
"bids": [
[
0.61,
2000
],
[
0.6,
1200
]
],
"lastOrderSettled": {
"id": "987654321",
"price": "0.62",
"kind": "LIMIT",
"marketId": 123,
"side": "Ask",
"outcome": "Yes"
},
"settlementsPending": {
"asks": [
[
0.62,
310
]
],
"bids": []
}
}
}
```
## Types
```ts
export type OrderbookMessage = OrderbookPayload;
export type OrderbookPayload = TopicMessage & {
data?: Orderbook;
};
export interface TopicMessage {
type: "M";
/** The topic string the subscription was made with. */
topic: string;
}
export interface Orderbook {
version: 1;
marketId: number;
updateTimestampMs: number;
orderCount: number;
/** Ask levels, lowest price first. */
asks: PriceLevel[];
/** Bid levels, highest price first. */
bids: PriceLevel[];
/** The latest settled order, or `null` before the first settlement. */
lastOrderSettled: null | SettledOrder;
/**
* The orders whose settlement is in flight, per price. `asks` holds the resting asks
* and `bids` the resting bids, with prices on the YES scale, so an ask for NO appears
* under `asks` at its YES price.
*
*/
settlementsPending: {
asks: PendingSettlementLevel[];
bids: PendingSettlementLevel[];
};
}
/** `[price, quantity]`. The price is the YES price between 0 and 1, the quantity is in shares. */
export type PriceLevel = number[];
export interface SettledOrder {
id: string;
/** The YES price, with 2 decimals. */
price: string;
/** The order's strategy. */
kind: "LIMIT" | "MARKET";
side: "Ask" | "Bid";
outcome: "Yes" | "No";
marketId: number;
}
/**
* `[price, value]`. The price is the YES price between 0 and 1. The value is in USDT: the
* shares being settled at that price, multiplied by the price.
*
*/
export type PendingSettlementLevel = number[];
```
# Top of book (/websocket/topics/top-of-book)
Predict WebSocket API sends these messages to you.
Address: `/ws`
## Servers
- `wss://ws.predict.fun` (BNB Mainnet, wss)
- `wss://ws-testnet.predict.fun` (BNB Testnet, wss)
## Authorization
Connecting to `mainnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
Connecting to `testnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
## Messages
### Top of book
Content type: `application/json`
Payload: `TopOfBookPayload`
Example payload:
```json
{
"type": "M",
"topic": "predictTopOfBook/123",
"data": {
"marketId": 123,
"bestBid": [
0.61,
2000
],
"bestAsk": [
0.62,
1500
],
"lastOrderSettled": {
"id": "987654321",
"price": "0.62",
"kind": "LIMIT",
"marketId": 123,
"side": "Ask",
"outcome": "Yes"
}
}
}
```
## Types
```ts
export type TopOfBookMessage = TopOfBookPayload;
export type TopOfBookPayload = TopicMessage & {
data?: TopOfBook;
};
export interface TopicMessage {
type: "M";
/** The topic string the subscription was made with. */
topic: string;
}
/**
* The first level on each side of the market's order book. It has no timestamp, because a
* message is only sent on a change. To know how fresh the book is, read the order book.
*
*/
export interface TopOfBook {
marketId: number;
/** The highest bid, or `null` when there are no bids. */
bestBid: null | PriceLevel;
/** The lowest ask, or `null` when there are no asks. */
bestAsk: null | PriceLevel;
/** The latest settled order, or `null` before the first settlement. */
lastOrderSettled: null | SettledOrder;
}
/** `[price, quantity]`. The price is the YES price between 0 and 1, the quantity is in shares. */
export type PriceLevel = number[];
export interface SettledOrder {
id: string;
/** The YES price, with 2 decimals. */
price: string;
/** The order's strategy. */
kind: "LIMIT" | "MARKET";
side: "Ask" | "Bid";
outcome: "Yes" | "No";
marketId: number;
}
```
# Trading status (/websocket/topics/trading-status)
Predict WebSocket API sends these messages to you.
Address: `/ws`
## Servers
- `wss://ws.predict.fun` (BNB Mainnet, wss)
- `wss://ws-testnet.predict.fun` (BNB Testnet, wss)
## Authorization
Connecting to `mainnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
Connecting to `testnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
## Messages
### Trading status
Content type: `application/json`
Payload: `TradingStatusPayload`
Example payload:
```json
{
"type": "M",
"topic": "predictTradingStatus/123",
"data": {
"kind": "tradingStatusUpdate",
"tsMs": 1736696400000,
"marketId": 123,
"tradingStatus": "OPEN"
}
}
```
## Types
```ts
export type TradingStatusMessage = TradingStatusPayload;
export type TradingStatusPayload = TopicMessage & {
data?: {
kind: "tradingStatusUpdate";
tsMs: number;
marketId: number;
tradingStatus: "OPEN" | "MATCHING_NOT_ENABLED" | "CANCEL_ONLY" | "CLOSED";
};
};
export interface TopicMessage {
type: "M";
/** The topic string the subscription was made with. */
topic: string;
}
```
# Market status (/websocket/topics/market-status)
Predict WebSocket API sends these messages to you.
Address: `/ws`
## Servers
- `wss://ws.predict.fun` (BNB Mainnet, wss)
- `wss://ws-testnet.predict.fun` (BNB Testnet, wss)
## Authorization
Connecting to `mainnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
Connecting to `testnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
## Messages
### Market status
Content type: `application/json`
Payload: `MarketStatusPayload`
Example payload:
```json
{
"type": "M",
"topic": "predictMarketStatus/123",
"data": {
"kind": "marketStatusUpdate",
"tsMs": 1736696400000,
"marketId": 123,
"status": "RESOLVED",
"marketOutcomes": [
{
"label": "Yes",
"indexSet": 1,
"price": "1000000000000000000",
"onChainId": "4567890123456789012345678901234567890"
},
{
"label": "No",
"indexSet": 2,
"price": "0",
"onChainId": "9876543210987654321098765432109876543"
}
]
}
}
```
## Types
```ts
export type MarketStatusMessage = MarketStatusPayload;
export type MarketStatusPayload = TopicMessage & {
data?: {
kind: "marketStatusUpdate";
tsMs: number;
marketId: number;
status: "REGISTERED" | "PRICE_DISPUTED" | "RESOLVED";
/** Each outcome's final price. Sent with `RESOLVED`. */
marketOutcomes?: ResolvedOutcome[];
};
};
export interface TopicMessage {
type: "M";
/** The topic string the subscription was made with. */
topic: string;
}
export interface ResolvedOutcome {
label: string;
indexSet: number;
/** The price in wei, where `1000000000000000000` is 1. */
price: "0" | "500000000000000000" | "1000000000000000000";
/** The outcome's on-chain token ID, in decimal. */
onChainId: string;
}
```
# Market changed (/websocket/topics/market-changed)
Predict WebSocket API sends these messages to you.
Address: `/ws`
## Servers
- `wss://ws.predict.fun` (BNB Mainnet, wss)
- `wss://ws-testnet.predict.fun` (BNB Testnet, wss)
## Authorization
Connecting to `mainnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
Connecting to `testnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
## Messages
### Market changed
Content type: `application/json`
Payload: `MarketChangedPayload`
Example payload:
```json
{
"type": "M",
"topic": "predictMarketChanged/123",
"data": {
"kind": "marketChanged",
"patchKind": null,
"tsMs": 1736696400000,
"marketId": 123
}
}
```
## Types
```ts
export type MarketChangedMessage = MarketChangedPayload;
export type MarketChangedPayload = TopicMessage & {
data?: {
kind: "marketChanged";
/**
* What changed. `null` for a general change. `marketRewards` comes without a
* `patch`. The other values come with one.
*
*/
patchKind: null | "marketRewards" | "translationUpdate" | "bulletinBoardUpdate" | "cryptoUpDownVariantData";
tsMs: number;
marketId: number;
/** The changed data, keyed by what it is. */
patch?: TranslationUpdate | {
bulletinBoardUpdate: {
id: number;
marketId: number;
content: string;
createdAt: string;
updatedAt: null | string;
};
} | {
/** The price feed of an up-or-down crypto market. */
variantData: {
priceFeedProvider: "BINANCE" | "CHAINLINK" | "ATLAS";
startPrice: number | null;
endPrice: number | null;
/** `null` for Binance, a hex feed ID otherwise. */
priceFeedId: string | null;
priceFeedSymbol: string | null;
};
};
};
};
export interface TopicMessage {
type: "M";
/** The topic string the subscription was made with. */
topic: string;
}
export interface TranslationUpdate {
/** A translation changed. Refetch the text in that language. */
translationUpdate: {
languageCode: string;
field: string;
};
}
```
# Category changed (/websocket/topics/category-changed)
Predict WebSocket API sends these messages to you.
Address: `/ws`
## Servers
- `wss://ws.predict.fun` (BNB Mainnet, wss)
- `wss://ws-testnet.predict.fun` (BNB Testnet, wss)
## Authorization
Connecting to `mainnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
Connecting to `testnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
## Messages
### Category changed
Content type: `application/json`
Payload: `CategoryChangedPayload`
Example payload:
```json
{
"type": "M",
"topic": "predictCategoryChanged/45",
"data": {
"kind": "categoryChanged",
"patchKind": null,
"tsMs": 1736696400000,
"categoryId": 45,
"slug": "politics"
}
}
```
## Types
```ts
export type CategoryChangedMessage = CategoryChangedPayload;
export type CategoryChangedPayload = TopicMessage & {
data?: {
kind: "categoryChanged";
/** What changed, `null` for a general change. */
patchKind: null | "translationUpdate" | "volumeUpdate" | "tradingSessionUpdate";
tsMs: number;
categoryId: number;
slug: string;
/** The changed data, keyed by what it is. */
patch?: TranslationUpdate | {
volumeUpdate: {
volumeTotalUsd: number;
};
} | {
tradingSessionUpdate: {
/** The current trading session, or `null` outside one. */
tradingSession: null | {
opensAt: string;
closesAt: string;
};
};
};
} | {
categoryId: number;
tsMs: number;
};
};
export interface TopicMessage {
type: "M";
/** The topic string the subscription was made with. */
topic: string;
}
export interface TranslationUpdate {
/** A translation changed. Refetch the text in that language. */
translationUpdate: {
languageCode: string;
field: string;
};
}
```
# Wallet events (/websocket/topics/wallet-events)
Predict WebSocket API sends these messages to you.
Address: `/ws`
## Servers
- `wss://ws.predict.fun` (BNB Mainnet, wss)
- `wss://ws-testnet.predict.fun` (BNB Testnet, wss)
## Authorization
Connecting to `mainnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
Connecting to `testnet` takes one of:
- `apiKeyHeader` (httpApiKey in header `x-api-key`): The API key in the handshake's `x-api-key` header. Use this where you can.
- `apiKeyQuery` (httpApiKey in query `apiKey`): The API key as the `apiKey` query parameter, for clients that cannot set headers.
## Messages
### Wallet event
Content type: `application/json`
Payload: `WalletEventPayload`
Example payload:
```json
{
"type": "M",
"topic": "predictWalletEvents/eyJhbGciOi...",
"data": {
"type": "orderAccepted",
"orderId": "123456789",
"orderHash": "0x3f1c...9a2b",
"walletAddress": "0x8ba1f109551bD432803012645Ac136ddd64DBA72",
"timestamp": 1736696400000,
"details": {
"marketId": 123,
"outcomeIndex": 1,
"marketQuestion": "Will X happen?",
"outcome": "YES",
"outcomeName": "Yes",
"quoteType": "BID",
"quantity": "100.000",
"quantityFilled": "0.000",
"price": "0.620",
"value": "62.00",
"valueFilled": "0.00",
"strategyType": "LIMIT",
"categorySlug": "politics"
}
}
}
```
## Types
```ts
export type WalletEventsMessage = WalletEventPayload;
export type WalletEventPayload = TopicMessage & {
data?: OrderAccepted | OrderNotAccepted | OrderMarketMatchPlan | OrderExpired | OrderCancelled | OrderTransactionSubmitted | OrderTransactionSuccess | OrderTransactionFailed;
};
export interface TopicMessage {
type: "M";
/** The topic string the subscription was made with. */
topic: string;
}
/** The order was placed in the book. */
export type OrderAccepted = WalletEvent & {
type?: "orderAccepted";
};
/** The order was rejected. */
export type OrderNotAccepted = WalletEvent & {
type?: "orderNotAccepted";
reason: "noMarketMatch" | "rejectedDuplicate" | "rejectedPostOnly";
/**
* Sent with `noMarketMatch`: the settlement that failed, or `null` when nothing
* matched.
*
*/
settlementId?: string | null;
};
/** How a market order is going to be filled. */
export type OrderMarketMatchPlan = WalletEvent & {
type?: "orderMarketMatchPlan";
/** In wei. */
amount: string;
/** In wei. */
amountFilled: string;
/** In wei. */
plannedFill: string;
/** In wei. */
remainderCancelled: string;
settlementIds: string[];
};
/** The order reached its end time. */
export type OrderExpired = WalletEvent & {
type?: "orderExpired";
};
/** The order was cancelled. */
export type OrderCancelled = WalletEvent & {
type?: "orderCancelled";
/** Present when self-trade prevention cancelled the order. */
reason?: "selfTradePrevention";
};
/**
* The order matched and its settlement was submitted on-chain. When two of the wallet's own
* orders trade with each other, each one gets an event, one as taker and one as maker.
*
*/
export type OrderTransactionSubmitted = WalletEvent & {
type?: "orderTransactionSubmitted";
settlementId: string;
kind: "PURCHASE" | "SALE";
isMaker: boolean;
fill: Fill;
};
/** The settlement succeeded on-chain. */
export type OrderTransactionSuccess = WalletEvent & {
type?: "orderTransactionSuccess";
settlementId: string;
fill: Fill;
isMaker?: boolean;
fee?: {
amountWei: string;
type: "COLLATERAL" | "SHARES";
};
};
/** The settlement failed on-chain. */
export type OrderTransactionFailed = WalletEvent & {
type?: "orderTransactionFailed";
settlementId: string;
fill: Fill;
};
/** The fields every wallet event has. */
export interface WalletEvent {
type: string;
orderId: string;
orderHash: string;
/** The wallet's checksummed address. Absent when it could not be looked up. */
walletAddress?: string;
timestamp: number;
details: OrderDetails;
}
export interface Fill {
executedPriceWei: string;
executedSizeWei: string;
/** The price times the size, divided by 1e18. */
executedValueWei: string;
}
export interface OrderDetails {
marketId: number;
/** The outcome's index set, `1` or `2` in a binary market. */
outcomeIndex: number;
quoteType: "BID" | "ASK";
/** Shares, with 3 decimals. */
quantity: string;
/** Shares, with 3 decimals. */
quantityFilled: string;
/** With 3 decimals. */
price: string;
/** With 2 decimals. */
value: string;
/** With 2 decimals. */
valueFilled: string;
marketQuestion: string;
categorySlug: string;
strategyType: "MARKET" | "LIMIT";
outcome: "YES" | "NO";
/** The outcome's name, in the language chosen with setLanguage. */
outcomeName: string;
}
```