# VPX: the Vancouver Prediction Exchange You're building on VPX (https://www.vancouverpx.ca), a Canadian prediction exchange: people trade YES/NO shares on real-world events through a limit order book. Trading uses play money (T$). Every account starts with T$10,000, written 1,000,000 because the API counts cents. VPX is not a licensed or regulated exchange. ## The API - Base URL: `https://www.vancouverpx.ca/api/v1`. JSON over HTTPS. Index of every endpoint: `GET https://www.vancouverpx.ca/api/v1`. - Full reference: https://www.vancouverpx.ca/llms-full.txt (markdown). OpenAPI 3.1: https://www.vancouverpx.ca/docs/api/openapi.json. Human docs: https://www.vancouverpx.ca/docs/api. - **Market data is public**: no key needed. **Your account and trading need a key**: `Authorization: Bearer $VPX_API_KEY`. - Wherever the API takes a market id, the market's `slug` works too. - Errors are `{"error": "...", "code": "..."}`. Branch on `code` (`INSUFFICIENT_FUNDS`, `MARKET_CLOSED`, …), never on the wording. - Lists page with `limit` and `cursor`: pass `nextCursor` back as `cursor` until it is `null`. - A parameter an endpoint doesn't take is refused (400, naming the ones it does), never ignored. - There are no websockets. Poll, at most a few requests a second, and back off when you get a 429 or a 5xx. - The market, account and trading endpoints are also MCP tools at https://www.vancouverpx.ca/api/mcp (Streamable HTTP, same key header). ## Getting an API key Read the key from the environment (`VPX_API_KEY`). Never print it, log it or commit it: keep it in a gitignored `.env`. If there is no key, get one yourself. Your person only has to press Approve: ```bash curl -s -X POST https://www.vancouverpx.ca/api/v1/keys/request -H "Content-Type: application/json" -d '{"name": "Claude Code"}' ``` The answer has a `url`, a `code` and a secret `token`. Open the `url` for your person (or show it), tell them the `code` to check, and ask them to sign in and press Approve. Meanwhile, every 3 seconds: ```bash curl -s -X POST https://www.vancouverpx.ca/api/v1/keys/claim -H "Content-Type: application/json" -d '{"token": ""}' ``` The answer is `pending` until they approve, then `approved` with `key`, once. Save it to `.env` as `VPX_API_KEY` straight away. Requests expire after 10 minutes. People can also make and revoke keys themselves at https://www.vancouverpx.ca/developer, and a key you no longer need can revoke itself: `DELETE /keys/current`. ## How VPX works - **Markets.** Each market asks a YES/NO question. Its `status` goes OPEN → CLOSED → RESOLVED, or CANCELED. Only OPEN markets trade. A market can stay OPEN for up to 6 hours after `closesAt` before VPX closes it, so stop trading at `closesAt` yourself. - **Prices and money are integer cents.** Prices run 1–99, and cash, `volume` and payouts are cents too. A YES and a NO share always pay 100¢ together, so buying NO at 40¢ is the same as selling YES at 60¢. Each market has one book, shown in YES terms: `bestBid`, `bestAsk`, `lastPrice`, `book` and the trade tape (`yesPrice`) are all YES prices. The NO price is 100 − YES. - **Orders** are priced in their own outcome's cents. A LIMIT order rests until it fills or you cancel it. A MARKET order fills what it can now and cancels the rest. Buying locks `price × quantity` cents; selling locks the shares. There is no shorting: to bet against YES, buy NO. VPX charges no fees, and has no self-trade prevention. - **Executions** come in three kinds. A `trade` is a buyer and a seller of the same outcome. A `marriage` is a YES buyer and a NO buyer whose prices add up to 100, creating a new pair of shares. A `divorce` is a YES seller and a NO seller handing a pair back for 100. - **Positions.** `quantity` counts every share you hold, including the `lockedQuantity` that your open sell orders hold. - **Resolution.** A winning share pays 100¢ and a losing one 0, automatically. See `GET /settlements`. Resolved shares stay in `/positions` with their `payout`. - **Groups.** A question with several answers ("Who wins Vancouver-Quilchena?") has one market per answer. In a `negRisk` group exactly one answer wins, so the YES prices add up to about 100 and the books share liquidity (`implied` on the order book). - **Unlisted** markets (`listed: false`) are left off the website's lists but trade like any other, and the API lists them with the rest. **Private** markets are for invited friends; each one gives its members a separate wallet of play money (`wallets` on `GET /account`). - **VPX Bots** (https://www.vancouverpx.ca/bots) trade through this same API. A bot's orders and fills appear in yours, marked with its `botId`. ## Endpoints | Method | Path | Key | What | | --- | --- | --- | --- | | GET | `/api/v1/markets` | — | Markets with their prices, newest first | | GET | `/api/v1/markets/{marketId}` | — | One market by id or slug | | GET | `/api/v1/markets/{marketId}/book` | — | Bids and offers, in YES terms | | GET | `/api/v1/markets/{marketId}/history` | — | The market's price chart, oldest first | | GET | `/api/v1/trades` | — | Executions on VPX, newest first | | GET | `/api/v1/groups` | — | Questions with several answers, newest first | | GET | `/api/v1/groups/{groupId}` | — | One group, with every market in it | | GET | `/api/v1` | — | Every endpoint, and who you are signed in as | | GET | `/api/v1/account` | key | Who you are and your cash | | GET | `/api/v1/positions` | key | The shares you hold, with their prices | | GET | `/api/v1/orders` | key | Your open orders, or your order history | | GET | `/api/v1/orders/{orderId}` | key | One of your orders, with its fills | | GET | `/api/v1/fills` | key | Every execution of your orders, newest first | | GET | `/api/v1/settlements` | key | What resolved markets paid you, newest first | | GET | `/api/v1/account/history` | key | Your main wallet's value, day by day | | POST | `/api/v1/orders` | key | Buy or sell YES or NO shares | | DELETE | `/api/v1/orders/{orderId}` | key | Take one of your orders off the book | | DELETE | `/api/v1/orders` | key | Cancel the orders you name, a market's, or all of them | | POST | `/api/v1/markets/{marketId}/split` | key | Pay 100¢ for one YES and one NO share | | POST | `/api/v1/markets/{marketId}/redeem` | key | Hand back YES+NO pairs for 100¢ each | | POST | `/api/v1/keys/request` | — | How an agent gets a key: its person approves it on the website | | POST | `/api/v1/keys/claim` | — | Poll until your person approves; then you get the key, once | | DELETE | `/api/v1/keys/current` | key | Stop the key you're calling with working, at once | ## Recipes - **Every open book in one call**: `GET /markets?status=OPEN&include=book`. - **Follow the tape**: call `GET /trades?since=` and drop ids you've already seen: an execution can be written a moment after the time it carries, and the overlap catches it. - **Your money adds up**: a wallet's `funded` + Σ fills (−price × quantity on a BUY, + on a SELL) + Σ settlement `payout` = its `balance`. Its value is `balance` + Σ positions × `bid`, and its profit is value − `funded`. Splits and redeems (YES+NO pairs for 100¢) leave no fill, so they are the only gap. - **Quote safely**: keep your order ids, re-quote only when the price moves, and when you stop, cancel what you placed: `DELETE /orders` with `{"ids": [...]}` in the body. `{"marketId": ...}` or `{"all": true}` would cancel every open order in that market or the account, the person's own and their VPX bots' included. If a request times out, check `GET /orders` before you send it again. - **Prices from elsewhere**: `venues` gives a market's Polymarket slug and Kalshi ticker, if VPX matched it (Polymarket quotes 0–1 and Kalshi dollars; VPX quotes cents). This file is written from the API itself, so it is always current: https://www.vancouverpx.ca/docs/api/claude.md # API reference Base URL: `https://www.vancouverpx.ca/api/v1`. JSON in, JSON out. Market data needs no key; your account and trading need `Authorization: Bearer `. ## Markets ### List markets `GET /api/v1/markets` · public, no key needed · [docs](https://www.vancouverpx.ca/docs/api/get-markets) Markets with their prices, newest first. Every public market, newest first, with its best bid and offer, last price and volume, including the ones the website doesn't list (`listed: false`), which trade like any other. Private markets show only to their members. Markets come without their description (their rules), to keep the list light for polling: add `include=description`, or get one market. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `status` | query | MarketStatus | no | Only markets with this status | | `category` | query | Category | no | | | `groupId` | query | string | no | Only this group's markets | | `ids` | query | string[] | no | Only these markets (ids or slugs) (comma-separated, at most 200) | | `q` | query | string | no | Only markets whose question contains this | | `include` | query | ("book" \| "description")[] | no | Add to each market: book (its resting orders; a neg-risk market's implied liquidity is on its order book endpoint), description (its rules). Comma-separated | | `limit` | query | integer | no | How many to return (1–1000, default 1000) Default 1000. | | `cursor` | query | string | no | From a previous page's `nextCursor` | ```bash curl "https://www.vancouverpx.ca/api/v1/markets?status=OPEN" ``` Answers `200` with an object: ```json { "markets": [ { "id": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "slug": "bc-ndp-most-seats-2026", "link": "https://www.vancouverpx.ca/market/bc-ndp-most-seats-2026", "question": "Will the BC NDP win the most seats in the 2026 BC election?", "category": "POLITICS", "status": "OPEN", "closesAt": "2026-11-21T03:00:00.000Z", "resolvesAt": "2026-11-22T08:00:00.000Z", "resolution": null, "yesLabel": "Yes", "noLabel": "No", "imageUrl": null, "listed": true, "private": false, "negRisk": true, "group": { "id": "7a0d4c3b-2e1f-4a9b-8c6d-5e4f3a2b1c0d", "question": "Which party will win the most seats in the 2026 BC election?", "itemTitle": "BC NDP", "size": 3 }, "venues": { "polymarketSlug": "bc-election-most-seats-ndp", "kalshiTicker": null }, "bestBid": 52, "bestAsk": 55, "lastPrice": 54, "volume": 152340, "createdAt": "2026-09-28T18:00:00.000Z", "updatedAt": "2026-10-26T21:14:09.000Z" } ], "nextCursor": null } ``` ### Get a market `GET /api/v1/markets/{marketId}` · public, no key needed · [docs](https://www.vancouverpx.ca/docs/api/get-market) One market by id or slug. One market, listed or not, by its id or its slug (the last part of its address on the website). Resolved markets carry their `resolution`: the winning outcome and what each share paid. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `marketId` | path | string | yes | The market's id, or its slug | | `include` | query | "book" | no | book: add its book of resting orders (a neg-risk market's implied liquidity is on its order book endpoint) | ```bash curl "https://www.vancouverpx.ca/api/v1/markets/3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11" ``` Answers `200` with an object: ```json { "id": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "slug": "bc-ndp-most-seats-2026", "link": "https://www.vancouverpx.ca/market/bc-ndp-most-seats-2026", "question": "Will the BC NDP win the most seats in the 2026 BC election?", "description": "Resolves YES if the BC NDP wins more seats than any other party, as reported by Elections BC.", "category": "POLITICS", "status": "OPEN", "closesAt": "2026-11-21T03:00:00.000Z", "resolvesAt": "2026-11-22T08:00:00.000Z", "resolution": null, "yesLabel": "Yes", "noLabel": "No", "imageUrl": null, "listed": true, "private": false, "negRisk": true, "group": { "id": "7a0d4c3b-2e1f-4a9b-8c6d-5e4f3a2b1c0d", "question": "Which party will win the most seats in the 2026 BC election?", "itemTitle": "BC NDP", "size": 3 }, "venues": { "polymarketSlug": "bc-election-most-seats-ndp", "kalshiTicker": null }, "bestBid": 52, "bestAsk": 55, "lastPrice": 54, "volume": 152340, "createdAt": "2026-09-28T18:00:00.000Z", "updatedAt": "2026-10-26T21:14:09.000Z" } ``` Errors: `MARKET_NOT_FOUND`. ### Get the order book `GET /api/v1/markets/{marketId}/book` · public, no key needed · [docs](https://www.vancouverpx.ca/docs/api/get-order-book) Bids and offers, in YES terms. The market's resting limit orders, aggregated by price, in YES terms: a bid to buy NO at 40¢ is an offer of YES at 60¢. For the NO side, mirror it: NO's best bid is 100 − YES's best offer. On a neg-risk market an order can also fill against the rest of its group (buying YES here is like selling YES in every other answer), so `implied` adds the bids and offers that liquidity makes. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `marketId` | path | string | yes | The market's id, or its slug | | `depth` | query | integer | no | Price levels per side (default: all) | ```bash curl "https://www.vancouverpx.ca/api/v1/markets/3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11/book" ``` Answers `200` with an object: ```json { "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "bids": [ { "price": 52, "quantity": 40 }, { "price": 50, "quantity": 120 } ], "asks": [ { "price": 55, "quantity": 25 }, { "price": 58, "quantity": 60 } ], "implied": { "bids": [ { "price": 51, "quantity": 10 } ], "asks": [] }, "lastPrice": 54, "time": "2026-10-27T17:06:12.004Z" } ``` Errors: `MARKET_NOT_FOUND`. ### Get price history `GET /api/v1/markets/{marketId}/history` · public, no key needed · [docs](https://www.vancouverpx.ca/docs/api/get-price-history) The market's price chart, oldest first. The YES price the website's chart shows, with the best bid and offer at the time, one point per interval (the last one in it), oldest first. VPX samples a market at most once a minute while it is watched or traded, so quiet periods have gaps. For every execution, use GET /trades. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `marketId` | path | string | yes | The market's id, or its slug | | `interval` | query | "raw" \| "1m" \| "5m" \| "1h" \| "1d" | no | Point spacing (default 1h) Default "1h". | | `since` | query | string (date-time) | no | From this time (ISO 8601, e.g. 2026-10-27T18:00:00Z) | | `until` | query | string (date-time) | no | Up to this time (ISO 8601, e.g. 2026-10-27T18:00:00Z) | ```bash curl "https://www.vancouverpx.ca/api/v1/markets/3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11/history?interval=1d" ``` Answers `200` with an object: ```json { "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "interval": "1d", "points": [ { "time": "2026-10-25T00:00:00.000Z", "price": 51, "bid": 50, "ask": 53 }, { "time": "2026-10-26T00:00:00.000Z", "price": 54, "bid": 52, "ask": 55 } ] } ``` Errors: `MARKET_NOT_FOUND`. ### List trades `GET /api/v1/trades` · public, no key needed · [docs](https://www.vancouverpx.ca/docs/api/get-trades) Executions on VPX, newest first. Every execution (trades, marriages and divorces) in YES terms, newest first, on the markets you name (ids or slugs) or on all of them. To follow the tape, each time ask for trades `since` a few seconds before the last answer's `now`, and drop ids you've already seen: an execution can be written a moment after the time it carries. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `marketId` | query | string[] | no | Only these markets (ids or slugs) (comma-separated, at most 200) | | `since` | query | string (date-time) | no | Only executions after this time (ISO 8601, e.g. 2026-10-27T18:00:00Z) | | `until` | query | string (date-time) | no | Only executions at or before this time (ISO 8601, e.g. 2026-10-27T18:00:00Z) | | `limit` | query | integer | no | How many to return (1–1000, default 100) Default 100. | | `cursor` | query | string | no | From a previous page's `nextCursor` | ```bash curl "https://www.vancouverpx.ca/api/v1/trades?marketId=3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11&limit=2" ``` Answers `200` with an object: ```json { "trades": [ { "id": "marriage:0c9e8d7f-6a5b-4c3d-2e1f-0a9b8c7d6e5f", "kind": "marriage", "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "yesPrice": 54, "quantity": 10, "executedAt": "2026-10-27T17:04:51.120Z" }, { "id": "trade:5d1e9c2a-7b3f-4e8d-a6c1-2f9b8e7d6c5a", "kind": "trade", "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "yesPrice": 53, "quantity": 4, "executedAt": "2026-10-27T17:03:00.000Z" } ], "nextCursor": "eyJ0IjoiMjAyNi0xMC0yN1QxNzowMzowMC4wMDBaIiwiaSI6InRyYWRlOjVkMWU5YzJhIn0", "now": "2026-10-27T17:06:12.004Z" } ``` ### List market groups `GET /api/v1/groups` · public, no key needed · [docs](https://www.vancouverpx.ca/docs/api/get-groups) Questions with several answers, newest first. A group is a question with several answers (a riding's candidates, a central bank's options), one yes/no market per answer. When the answers are exhaustive and exclusive (`negRisk`), exactly one resolves YES, so their YES prices add up to about 100. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `status` | query | MarketStatus | no | | | `limit` | query | integer | no | How many to return (1–200, default 100) Default 100. | | `cursor` | query | string | no | From a previous page's `nextCursor` | ```bash curl "https://www.vancouverpx.ca/api/v1/groups?status=OPEN" ``` Answers `200` with an object: ```json { "groups": [ { "id": "7a0d4c3b-2e1f-4a9b-8c6d-5e4f3a2b1c0d", "slug": "bc-election-2026-most-seats", "link": "https://www.vancouverpx.ca/market-group/bc-election-2026-most-seats", "question": "Which party will win the most seats in the 2026 BC election?", "description": null, "category": "POLITICS", "status": "OPEN", "closesAt": "2026-11-21T03:00:00.000Z", "resolvesAt": null, "listed": true, "negRisk": true, "markets": [ { "id": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "itemTitle": "BC NDP", "question": "Will the BC NDP win the most seats in the 2026 BC election?", "status": "OPEN", "bestBid": 52, "bestAsk": 55, "lastPrice": 54 } ] } ], "nextCursor": null } ``` ### Get a market group `GET /api/v1/groups/{groupId}` · public, no key needed · [docs](https://www.vancouverpx.ca/docs/api/get-group) One group, with every market in it. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `groupId` | path | string | yes | The group's id, or its slug | ```bash curl "https://www.vancouverpx.ca/api/v1/groups/7a0d4c3b-2e1f-4a9b-8c6d-5e4f3a2b1c0d" ``` Answers `200` with an object: ```json { "id": "7a0d4c3b-2e1f-4a9b-8c6d-5e4f3a2b1c0d", "slug": "bc-election-2026-most-seats", "link": "https://www.vancouverpx.ca/market-group/bc-election-2026-most-seats", "question": "Which party will win the most seats in the 2026 BC election?", "description": null, "category": "POLITICS", "status": "OPEN", "closesAt": "2026-11-21T03:00:00.000Z", "resolvesAt": null, "listed": true, "negRisk": true, "markets": [ { "id": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "slug": "bc-ndp-most-seats-2026", "link": "https://www.vancouverpx.ca/market/bc-ndp-most-seats-2026", "question": "Will the BC NDP win the most seats in the 2026 BC election?", "description": "Resolves YES if the BC NDP wins more seats than any other party, as reported by Elections BC.", "category": "POLITICS", "status": "OPEN", "closesAt": "2026-11-21T03:00:00.000Z", "resolvesAt": "2026-11-22T08:00:00.000Z", "resolution": null, "yesLabel": "Yes", "noLabel": "No", "imageUrl": null, "listed": true, "private": false, "negRisk": true, "group": { "id": "7a0d4c3b-2e1f-4a9b-8c6d-5e4f3a2b1c0d", "question": "Which party will win the most seats in the 2026 BC election?", "itemTitle": "BC NDP", "size": 3 }, "venues": { "polymarketSlug": "bc-election-most-seats-ndp", "kalshiTicker": null }, "bestBid": 52, "bestAsk": 55, "lastPrice": 54, "volume": 152340, "createdAt": "2026-09-28T18:00:00.000Z", "updatedAt": "2026-10-26T21:14:09.000Z" } ] } ``` Errors: `GROUP_NOT_FOUND`. ## Account ### API index `GET /api/v1` · public, no key needed · [docs](https://www.vancouverpx.ca/docs/api/get-index) Every endpoint, and who you are signed in as. The map of the API, for people and agents: every endpoint with its docs, and links to the OpenAPI spec, the MCP server and the agent guide. With a key it also says whose account the key is for. ```bash curl "https://www.vancouverpx.ca/api/v1" ``` Answers `200` with an object: ```json { "name": "Vancouver Prediction Exchange API", "version": "1", "docs": "https://www.vancouverpx.ca/docs/api", "openapi": "https://www.vancouverpx.ca/docs/api/openapi.json", "mcp": "https://www.vancouverpx.ca/api/mcp", "agents": "https://www.vancouverpx.ca/docs/api/claude.md", "you": null, "endpoints": [ { "method": "GET", "path": "/api/v1/markets", "summary": "Markets with their prices, newest first", "auth": "public", "docs": "https://www.vancouverpx.ca/docs/api/get-markets" } ] } ``` ### Get your account `GET /api/v1/account` · API key · [docs](https://www.vancouverpx.ca/docs/api/get-account) Who you are and your cash. Your user, your main wallet's cash, and every wallet you have: one per private market you joined, each with its own play money. Amounts are in cents: 1,000,000 is T$10,000, what every account starts with. `funded` is what VPX credited a wallet, so a wallet's profit is its cash plus its positions' value, minus `funded`. ```bash curl "https://www.vancouverpx.ca/api/v1/account" \ -H "Authorization: Bearer $VPX_API_KEY" ``` Answers `200` with an object: ```json { "userId": "u_8Kq2mZx4", "username": "brave-lion-42", "balance": 1024350, "locked": 3180, "available": 1021170, "wallets": [ { "id": "clx8w2k3p0001qz8r5t1y7u4v", "kind": "main", "marketId": null, "balance": 1024350, "locked": 3180, "available": 1021170, "funded": 1000000 } ], "via": { "kind": "key", "id": "clz3k9x2a0000ab12cd34ef56", "name": "Claude Code" } } ``` ### List your positions `GET /api/v1/positions` · API key · [docs](https://www.vancouverpx.ca/docs/api/get-positions) The shares you hold, with their prices. Every outcome you hold shares of, most recently changed first, with the market's best bid, best offer and last price in that outcome's cents, so `quantity × bid` is what you could sell for now. Shares of resolved markets stay listed with what they paid (`payout`). `quantity` includes the shares your open sell orders hold (`lockedQuantity`). | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `marketId` | query | string | no | Only this market (its id or slug) | ```bash curl "https://www.vancouverpx.ca/api/v1/positions" \ -H "Authorization: Bearer $VPX_API_KEY" ``` Answers `200` with an object: ```json { "positions": [ { "walletId": "clx8w2k3p0001qz8r5t1y7u4v", "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "marketQuestion": "Will the BC NDP win the most seats in the 2026 BC election?", "marketStatus": "OPEN", "private": false, "outcome": "YES", "quantity": 25, "lockedQuantity": 10, "bid": 52, "ask": 55, "lastPrice": 54, "payout": null, "updatedAt": "2026-10-27T17:05:00.000Z" } ] } ``` ### List your orders `GET /api/v1/orders` · API key · [docs](https://www.vancouverpx.ca/docs/api/get-orders) Your open orders, or your order history. Your orders, newest first: open ones by default, or `status=closed` (filled, cancelled) and `status=all` for your history. Orders your VPX bots placed are included, with their `botId`. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `status` | query | "open" \| "closed" \| "all" | no | open (default), closed or all Default "open". | | `marketId` | query | string | no | Only this market's orders (its id or slug) | | `limit` | query | integer | no | How many to return (1–1000, default 100) Default 100. | | `cursor` | query | string | no | From a previous page's `nextCursor` | ```bash curl "https://www.vancouverpx.ca/api/v1/orders?status=open" \ -H "Authorization: Bearer $VPX_API_KEY" ``` Answers `200` with an object: ```json { "orders": [ { "id": "9b2e5c1d-0f47-4d1e-8a55-6c2b7e3f9a10", "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "walletId": "clx8w2k3p0001qz8r5t1y7u4v", "side": "BUY", "outcome": "YES", "type": "LIMIT", "price": 53, "quantity": 10, "filledQuantity": 4, "remainingQuantity": 6, "status": "PARTIALLY_FILLED", "createdAt": "2026-10-27T17:05:00.000Z", "updatedAt": "2026-10-27T17:05:00.000Z", "canceledAt": null, "botId": null, "clientOrderId": null } ], "nextCursor": null } ``` ### Get an order `GET /api/v1/orders/{orderId}` · API key · [docs](https://www.vancouverpx.ca/docs/api/get-order) One of your orders, with its fills. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `orderId` | path | string | yes | | ```bash curl "https://www.vancouverpx.ca/api/v1/orders/9b2e5c1d-0f47-4d1e-8a55-6c2b7e3f9a10" \ -H "Authorization: Bearer $VPX_API_KEY" ``` Answers `200` with an object: ```json { "id": "9b2e5c1d-0f47-4d1e-8a55-6c2b7e3f9a10", "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "walletId": "clx8w2k3p0001qz8r5t1y7u4v", "side": "BUY", "outcome": "YES", "type": "LIMIT", "price": 53, "quantity": 10, "filledQuantity": 4, "remainingQuantity": 6, "status": "PARTIALLY_FILLED", "createdAt": "2026-10-27T17:05:00.000Z", "updatedAt": "2026-10-27T17:05:00.000Z", "canceledAt": null, "botId": null, "clientOrderId": null, "fills": [ { "id": "trade:5d1e9c2a-7b3f-4e8d-a6c1-2f9b8e7d6c5a:buy", "kind": "trade", "orderId": "9b2e5c1d-0f47-4d1e-8a55-6c2b7e3f9a10", "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "walletId": "clx8w2k3p0001qz8r5t1y7u4v", "side": "BUY", "outcome": "YES", "price": 53, "quantity": 4, "executedAt": "2026-10-27T17:05:00.000Z", "botId": null } ] } ``` Errors: `ORDER_NOT_FOUND`. ### List your fills `GET /api/v1/fills` · API key · [docs](https://www.vancouverpx.ca/docs/api/get-fills) Every execution of your orders, newest first. Each time one of your orders traded: what, at what price, how many. Cash moved by price × quantity, out on a BUY and in on a SELL; VPX charges no fees. With your settlements (GET /settlements) and starting balance (`funded` on GET /account), fills account for every cent in your wallets, except YES+NO pairs you split or redeemed, which leave no record. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `marketId` | query | string[] | no | Only these markets (ids or slugs) (comma-separated, at most 100) | | `orderId` | query | string | no | Only this order's fills | | `since` | query | string (date-time) | no | Only fills after this time (ISO 8601, e.g. 2026-10-27T18:00:00Z) | | `until` | query | string (date-time) | no | Only fills at or before this time (ISO 8601, e.g. 2026-10-27T18:00:00Z) | | `limit` | query | integer | no | How many to return (1–1000, default 100) Default 100. | | `cursor` | query | string | no | From a previous page's `nextCursor` | ```bash curl "https://www.vancouverpx.ca/api/v1/fills?marketId=3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11" \ -H "Authorization: Bearer $VPX_API_KEY" ``` Answers `200` with an object: ```json { "fills": [ { "id": "trade:5d1e9c2a-7b3f-4e8d-a6c1-2f9b8e7d6c5a:buy", "kind": "trade", "orderId": "9b2e5c1d-0f47-4d1e-8a55-6c2b7e3f9a10", "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "walletId": "clx8w2k3p0001qz8r5t1y7u4v", "side": "BUY", "outcome": "YES", "price": 53, "quantity": 4, "executedAt": "2026-10-27T17:05:00.000Z", "botId": null } ], "nextCursor": null } ``` ### List your settlements `GET /api/v1/settlements` · API key · [docs](https://www.vancouverpx.ca/docs/api/get-settlements) What resolved markets paid you, newest first. Each resolved market you held shares of when it resolved: the winning outcome, your YES and NO shares, and what VPX paid for them (a winning share pays 100¢, a losing one nothing). VPX pays out automatically at resolution; there is nothing to claim. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `since` | query | string (date-time) | no | Only markets resolved after this time (ISO 8601, e.g. 2026-10-27T18:00:00Z) | | `limit` | query | integer | no | How many to return (1–1000, default 100) Default 100. | | `cursor` | query | string | no | From a previous page's `nextCursor` | ```bash curl "https://www.vancouverpx.ca/api/v1/settlements" \ -H "Authorization: Bearer $VPX_API_KEY" ``` Answers `200` with an object: ```json { "settlements": [ { "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "marketQuestion": "Will the Bank of Canada cut rates on October 28?", "walletId": "clx8w2k3p0001qz8r5t1y7u4v", "outcome": "YES", "resolvedAt": "2026-10-28T14:05:00.000Z", "yesQuantity": 40, "noQuantity": 0, "yesPayout": 100, "noPayout": 0, "payout": 4000 } ], "nextCursor": null } ``` ### Get your account history `GET /api/v1/account/history` · API key · [docs](https://www.vancouverpx.ca/docs/api/get-account-history) Your main wallet's value, day by day. One snapshot a day of your main wallet: cash, open positions at their last traded price, and the total. It is what your profile's chart shows. For exact accounting, rebuild from GET /fills and GET /settlements. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `since` | query | string (date-time) | no | From this day (ISO 8601, e.g. 2026-10-27T18:00:00Z) | | `until` | query | string (date-time) | no | Up to this day (ISO 8601, e.g. 2026-10-27T18:00:00Z) | ```bash curl "https://www.vancouverpx.ca/api/v1/account/history" \ -H "Authorization: Bearer $VPX_API_KEY" ``` Answers `200` with an object: ```json { "snapshots": [ { "date": "2026-10-25", "cash": 1012000, "holdingsValue": 8150, "totalValue": 1020150 }, { "date": "2026-10-26", "cash": 1015400, "holdingsValue": 9020, "totalValue": 1024420 } ] } ``` ## Trading ### Place an order `POST /api/v1/orders` · API key · [docs](https://www.vancouverpx.ca/docs/api/place-order) Buy or sell YES or NO shares. A LIMIT order buys or sells at `price` or better, matches at once against the book, and leaves what doesn't fill resting until you cancel it. A MARKET order takes what the book offers now and cancels the rest. The answer is the order after matching, with its fills. Buying locks `price × quantity` cents of available cash (a MARKET buy needs 99¢ × quantity available while it fills, and gets back what it doesn't spend); selling needs that many unlocked shares. To bet against YES, buy NO: there is no shorting. Buying NO at p is the same as selling YES at 100 − p, and it matches the same book. If a request times out, check GET /orders before you send it again, or you may place the order twice. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `marketId` | body | string | yes | The market's id (or its slug) | | `side` | body | "BUY" \| "SELL" | yes | | | `outcome` | body | "YES" \| "NO" | yes | | | `quantity` | body | integer | yes | Shares | | `type` | body | OrderType | no | LIMIT (default) or MARKET Default "LIMIT". | | `price` | body | integer | no | LIMIT only: cents, 1–99, in `outcome`'s terms | ```bash curl -X POST "https://www.vancouverpx.ca/api/v1/orders" \ -H "Authorization: Bearer $VPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"marketId":"3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11","side":"BUY","outcome":"YES","quantity":10,"price":53}' ``` Answers `201` with an object: ```json { "id": "9b2e5c1d-0f47-4d1e-8a55-6c2b7e3f9a10", "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "walletId": "clx8w2k3p0001qz8r5t1y7u4v", "side": "BUY", "outcome": "YES", "type": "LIMIT", "price": 53, "quantity": 10, "filledQuantity": 4, "remainingQuantity": 6, "status": "PARTIALLY_FILLED", "createdAt": "2026-10-27T17:05:00.000Z", "updatedAt": "2026-10-27T17:05:00.000Z", "canceledAt": null, "botId": null, "clientOrderId": null, "fills": [ { "id": "trade:5d1e9c2a-7b3f-4e8d-a6c1-2f9b8e7d6c5a:buy", "kind": "trade", "orderId": "9b2e5c1d-0f47-4d1e-8a55-6c2b7e3f9a10", "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "walletId": "clx8w2k3p0001qz8r5t1y7u4v", "side": "BUY", "outcome": "YES", "price": 53, "quantity": 4, "executedAt": "2026-10-27T17:05:00.000Z", "botId": null } ] } ``` Errors: `MARKET_NOT_FOUND`, `MARKET_CLOSED`, `INSUFFICIENT_FUNDS`, `INSUFFICIENT_SHARES`, `BAD_PRICE`, `POSITION_LIMIT`. ### Cancel an order `DELETE /api/v1/orders/{orderId}` · API key · [docs](https://www.vancouverpx.ca/docs/api/cancel-order) Take one of your orders off the book. Cancels an open or partly filled order and releases the cash or shares it held. The answer is the order afterwards: CANCELLED, or PARTIALLY_FILLED_CANCELLED if some of it had filled. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `orderId` | path | string | yes | | ```bash curl -X DELETE "https://www.vancouverpx.ca/api/v1/orders/9b2e5c1d-0f47-4d1e-8a55-6c2b7e3f9a10" \ -H "Authorization: Bearer $VPX_API_KEY" ``` Answers `200` with an object: ```json { "id": "9b2e5c1d-0f47-4d1e-8a55-6c2b7e3f9a10", "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "walletId": "clx8w2k3p0001qz8r5t1y7u4v", "side": "BUY", "outcome": "YES", "type": "LIMIT", "price": 53, "quantity": 10, "filledQuantity": 4, "remainingQuantity": 0, "status": "PARTIALLY_FILLED_CANCELLED", "createdAt": "2026-10-27T17:05:00.000Z", "updatedAt": "2026-10-27T17:12:40.000Z", "canceledAt": "2026-10-27T17:12:40.000Z", "botId": null, "clientOrderId": null } ``` Errors: `ORDER_NOT_FOUND`, `ORDER_NOT_OPEN`. ### Cancel orders `DELETE /api/v1/orders` · API key · [docs](https://www.vancouverpx.ca/docs/api/cancel-all-orders) Cancel the orders you name, a market's, or all of them. Say which in the body: `{"ids": [...]}` cancels those orders, `{"marketId": "..."}` every open order you have in that market, and `{"all": true}` every open order you have. A body that says none of these is refused, so a request that loses its body on the way never cancels everything. The answer lists what was cancelled. A market's orders, or all of them, include the ones your VPX bots placed in your account, so a script that should only clean up after itself names its ids. A VPX bot only ever cancels its own. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `ids` | body | string[] | no | These orders (at most 5,000; an empty list cancels nothing) | | `marketId` | body | string | no | Every open order you have in this market (its id or slug) | | `all` | body | true | no | Every open order you have | ```bash curl -X DELETE "https://www.vancouverpx.ca/api/v1/orders" \ -H "Authorization: Bearer $VPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"ids":["9b2e5c1d-0f47-4d1e-8a55-6c2b7e3f9a10"]}' ``` Answers `200` with an object: ```json { "cancelled": [ "9b2e5c1d-0f47-4d1e-8a55-6c2b7e3f9a10" ] } ``` Errors: `MARKET_NOT_FOUND`. ### Split cash into shares `POST /api/v1/markets/{marketId}/split` · API key · [docs](https://www.vancouverpx.ca/docs/api/split-shares) Pay 100¢ for one YES and one NO share. Turns cash into pairs: each pair costs 100¢ and gives you one YES and one NO share, which together always pay 100¢. Market makers use it to sell both sides without buying first. Splits don't appear in your fills. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `marketId` | path | string | yes | The market's id, or its slug | | `quantity` | body | integer | yes | How many YES+NO pairs | ```bash curl -X POST "https://www.vancouverpx.ca/api/v1/markets/3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11/split" \ -H "Authorization: Bearer $VPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"quantity":10}' ``` Answers `200` with an object: ```json { "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "walletId": "clx8w2k3p0001qz8r5t1y7u4v", "quantity": 10, "cost": 1000 } ``` Errors: `MARKET_NOT_FOUND`, `MARKET_CLOSED`, `INSUFFICIENT_FUNDS`. ### Redeem shares for cash `POST /api/v1/markets/{marketId}/redeem` · API key · [docs](https://www.vancouverpx.ca/docs/api/redeem-shares) Hand back YES+NO pairs for 100¢ each. The reverse of a split: gives back one YES and one NO share per pair, from your unlocked shares, for 100¢ each, before the market resolves. Redeems don't appear in your fills. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `marketId` | path | string | yes | The market's id, or its slug | | `quantity` | body | integer | yes | How many YES+NO pairs | ```bash curl -X POST "https://www.vancouverpx.ca/api/v1/markets/3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11/redeem" \ -H "Authorization: Bearer $VPX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"quantity":10}' ``` Answers `200` with an object: ```json { "marketId": "3f1c0f2e-6a55-4a8e-9b53-2a1f0c9d7e11", "walletId": "clx8w2k3p0001qz8r5t1y7u4v", "quantity": 10, "credit": 1000 } ``` Errors: `MARKET_NOT_FOUND`, `MARKET_CLOSED`, `INSUFFICIENT_SHARES`. ## API keys ### Ask for an API key `POST /api/v1/keys/request` · public, no key needed · [docs](https://www.vancouverpx.ca/docs/api/request-key) How an agent gets a key: its person approves it on the website. No key needed. Start a request, show your person `url` (or open it for them), and poll POST /keys/claim with `token` every `interval` seconds. They sign in, check the code matches, and press Approve; your next claim gets the key. Requests expire after 10 minutes. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `name` | body | string | no | Who is asking, e.g. "Claude Code": shown on the approval page, and the new key's name | ```bash curl -X POST "https://www.vancouverpx.ca/api/v1/keys/request" \ -H "Content-Type: application/json" \ -d '{"name":"Claude Code"}' ``` Answers `201` with an object: ```json { "code": "K7QM-2XRP", "url": "https://www.vancouverpx.ca/developer/approve?code=K7QM-2XRP", "token": "K7QM2XRP.Zq3v9yJb0cX1aW2eR5tY8uI4oP6sD7fG", "expiresAt": "2026-10-27T17:30:00.000Z", "interval": 3, "next": "Ask your person to open the url, sign in to VPX, check the code reads K7QM-2XRP and press Approve. Meanwhile POST /api/v1/keys/claim with {\"token\": \"\"} every 3 seconds until status is approved." } ``` Errors: `RATE_LIMITED`. ### Collect a requested key `POST /api/v1/keys/claim` · public, no key needed · [docs](https://www.vancouverpx.ca/docs/api/claim-key) Poll until your person approves; then you get the key, once. `pending` until your person answers. Once they approve, the answer is `approved` with the key, a single time: save it (for example as VPX_API_KEY in your .env) before anything else. `denied` if they turned it down. | Parameter | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `token` | body | string | yes | From POST /keys/request | ```bash curl -X POST "https://www.vancouverpx.ca/api/v1/keys/claim" \ -H "Content-Type: application/json" \ -d '{"token":"K7QM2XRP.Zq3v9yJb0cX1aW2eR5tY8uI4oP6sD7fG"}' ``` Answers `200` with an object: ```json { "status": "approved", "key": "vpx_live_3f9a0c1e7b2d4a6c8e0f1a3b5c7d9e1f2a4b6c8d0e2f4a6b" } ``` Errors: `REQUEST_EXPIRED`, `TOO_MANY_KEYS`. ### Revoke your API key `DELETE /api/v1/keys/current` · API key · [docs](https://www.vancouverpx.ca/docs/api/revoke-key) Stop the key you're calling with working, at once. For an agent or script that is done. A key can only revoke itself and can't make keys, so a key that leaks is cut off by revoking it on your Developer page: new keys come only from there, or from a request you approve. ```bash curl -X DELETE "https://www.vancouverpx.ca/api/v1/keys/current" \ -H "Authorization: Bearer $VPX_API_KEY" ``` Answers `200` with an object: ```json { "id": "clz3m1q8b0001ab12cd34ef56", "revoked": true } ``` ## Errors Every error answers `{ "error": "", "code": "" }`, plus `details` (which fields, and why) when the request itself was wrong. Branch on `code`, never on the wording of `error`. | Status | Codes | | --- | --- | | 400 | `BAD_REQUEST` (see details), `BAD_PRICE`, `BAD_CURSOR`, `INSUFFICIENT_FUNDS`, `INSUFFICIENT_SHARES`, `MARKET_CLOSED`, `POSITION_LIMIT` | | 401 | `UNAUTHORIZED` (no key), `INVALID_KEY` (wrong or revoked) | | 403 | `FORBIDDEN` (e.g. a VPX bot calling a key endpoint) | | 404 | `NOT_FOUND`, `MARKET_NOT_FOUND` (also a private market you haven't joined), `GROUP_NOT_FOUND`, `ORDER_NOT_FOUND`, `REQUEST_EXPIRED` | | 405 | `METHOD_NOT_ALLOWED` | | 409 | `ORDER_NOT_OPEN`, `TOO_MANY_KEYS`, `REQUEST_ANSWERED` | | 413 | `BODY_TOO_LARGE` (over 1 MB) | | 429 | `RATE_LIMITED`: wait, then try again | | 500 | `INTERNAL`: try again after a short backoff | ## Objects ### MarketStatus `"OPEN" | "CLOSED" | "RESOLVED" | "CANCELED"` ### Category `"SPORTS" | "FINANCE" | "POLITICS" | "CULTURE" | "OTHER"` ### Outcome `"YES" | "NO"` ### Side `"BUY" | "SELL"` ### OrderType `"LIMIT" | "MARKET"` ### OrderStatus `"OPEN" | "PARTIALLY_FILLED" | "FILLED" | "CANCELLED" | "PARTIALLY_FILLED_CANCELLED" | "EXPIRED"` ### ExecutionKind trade: a buyer and a seller of the same outcome. marriage: a YES buyer and a NO buyer, whose prices add up to 100, create a new pair of shares. divorce: a YES seller and a NO seller hand a pair back for its 100. `"trade" | "marriage" | "divorce"` ### Level | Field | Type | Description | | --- | --- | --- | | `price` | integer | YES price, in cents | | `quantity` | integer | Shares resting at this price | ### Book One book for both outcomes, in YES terms: buying NO at p is offering YES at 100 − p, and selling NO at p is bidding for YES at 100 − p. | Field | Type | Description | | --- | --- | --- | | `bids` | Level[] | Bids for YES, best (highest) first | | `asks` | Level[] | Offers of YES, best (lowest) first | ### Future A private market that settles at a number rather than YES or NO. A YES at price p is a long at lower + p / multiplier points. | Field | Type | Description | | --- | --- | --- | | `lower` | number | The value, in points, that price 0 stands for | | `multiplier` | integer | Cents per point | | `tickSize` | number | Price increment, in points | | `total` | integer | What a YES and a NO pay together at settlement | | `min` | integer | Lowest price an order may have | | `max` | integer | Highest price an order may have | | `step` | integer | Price increment | ### Resolution | Field | Type | Description | | --- | --- | --- | | `outcome` | Outcome | | | `resolvedAt` | string (date-time) | When the market was resolved | | `settlementValue` | number \| null | FUTURE only: the settlement value, in points | | `yesPayout` | integer | What each YES share paid | | `noPayout` | integer | What each NO share paid | ### GroupRef | Field | Type | Description | | --- | --- | --- | | `id` | string | The group's id | | `question` | string | The group's question, e.g. "Who will win the most seats?" | | `itemTitle` | string \| null | This market's answer within the group, e.g. "BC NDP" | | `size` | integer | How many of the group's public markets are open | ### VenueLinks The same question on Polymarket and Kalshi, as matched by VPX. VPX bots use these as fair-price sources. | Field | Type | Description | | --- | --- | --- | | `polymarketSlug` | string \| null | | | `kalshiTicker` | string \| null | | ### Market | Field | Type | Description | | --- | --- | --- | | `id` | string | The market's id (a UUID) | | `slug` | string \| null | Its name in addresses, as in vancouverpx.ca/market/; works wherever an id does | | `link` | string | The market's page on the website | | `question` | string | | | `description` (optional) | string \| null | Details and resolution rules. GET /markets leaves it out unless include=description | | `category` | Category | | | `status` | MarketStatus | | | `closesAt` | string (date-time) \| null | | | `resolvesAt` | string (date-time) \| null | | | `resolution` | Resolution \| null | Once resolved: the winner and what each share paid | | `yesLabel` | string | What the website calls YES (usually "Yes") | | `noLabel` | string | What the website calls NO (usually "No") | | `imageUrl` | string \| null | | | `listed` | boolean | On the website's lists. Unlisted markets trade like any other | | `private` | boolean | A private market: only its members see and trade it | | `negRisk` | boolean | One of its group's mutually exclusive outcomes. Their books share liquidity: an order here can also fill against the rest of the group (see `implied` on the order book). | | `group` | GroupRef \| null | | | `venues` | VenueLinks \| null | | | `future` (optional) | Future | Private futures only: how its prices map to points | | `bestBid` | integer \| null | | | `bestAsk` | integer \| null | | | `lastPrice` | integer \| null | | | `volume` | integer | Total traded, in cents: price × shares over every execution | | `createdAt` | string (date-time) | When the market was created | | `updatedAt` | string (date-time) | When the market last changed | | `book` (optional) | Book | Its book of resting orders, with include=book (implied neg-risk liquidity is on GET /markets/{marketId}/book) | ### OrderBook | Field | Type | Description | | --- | --- | --- | | `marketId` | string | | | `bids` | Level[] | Bids for YES, best (highest) first | | `asks` | Level[] | Offers of YES, best (lowest) first | | `implied` | Book \| null | Neg-risk markets only: what the rest of the group's books offer here. An order can fill against it too. Null on other markets. | | `lastPrice` | integer \| null | | | `time` | string (date-time) | When the book was read | ### Trade One execution on a market, in YES terms. | Field | Type | Description | | --- | --- | --- | | `id` | string | "trade:", "marriage:" or "divorce:" | | `kind` | ExecutionKind | | | `marketId` | string | | | `yesPrice` | integer | The execution's price in YES terms | | `quantity` | integer | | | `executedAt` | string (date-time) | When it executed | ### PricePoint | Field | Type | Description | | --- | --- | --- | | `time` | string (date-time) | Start of the interval | | `price` | integer | The YES price the website showed | | `bid` | integer \| null | | | `ask` | integer \| null | | ### GroupMarket | Field | Type | Description | | --- | --- | --- | | `id` | string | | | `itemTitle` | string \| null | | | `question` | string | | | `status` | MarketStatus | | | `bestBid` | integer \| null | | | `bestAsk` | integer \| null | | | `lastPrice` | integer \| null | | ### Group A question with several answers, one yes/no market per answer. | Field | Type | Description | | --- | --- | --- | | `id` | string | | | `slug` | string \| null | | | `link` | string | | | `question` | string | | | `description` | string \| null | | | `category` | Category | | | `status` | MarketStatus | | | `closesAt` | string (date-time) | When trading stops | | `resolvesAt` | string (date-time) \| null | | | `listed` | boolean | On the website's lists | | `negRisk` | boolean | Every market in the group is neg-risk: exactly one of them resolves YES | | `markets` | GroupMarket[] | | ### Wallet | Field | Type | Description | | --- | --- | --- | | `id` | string | | | `kind` | "main" \| "private" | main: your VPX balance. private: the play money of one private market you joined | | `marketId` | string \| null | The private market this wallet trades | | `balance` | integer | Cash, in cents, including what open orders hold | | `locked` | integer | Cash your open buy orders hold | | `available` | integer | Cash you can spend now: balance − locked | | `funded` | integer | Play money VPX has credited to this wallet: the starting balance plus any adjustments | ### Account | Field | Type | Description | | --- | --- | --- | | `userId` | string | | | `username` | string \| null | | | `balance` | integer | Main wallet cash, in cents | | `locked` | integer | Main wallet cash held by open buy orders | | `available` | integer | Main wallet cash you can spend now | | `wallets` | Wallet[] | | | `via` | object | The API key (or VPX bot) this request came from | ### Fill One of your orders trading. Cash moves by price × quantity: out on a BUY, in on a SELL. VPX charges no fees. | Field | Type | Description | | --- | --- | --- | | `id` | string | Unique per fill: "trade::buy", "trade::sell", "marriage::yes", "divorce::no", … | | `kind` | ExecutionKind | | | `orderId` | string | | | `marketId` | string | | | `walletId` | string | | | `side` | Side | | | `outcome` | Outcome | | | `price` | integer | What each share traded at, in this outcome's cents | | `quantity` | integer | | | `executedAt` | string (date-time) | When it executed | | `botId` | string \| null | The VPX bot whose order this was, if any | ### Order | Field | Type | Description | | --- | --- | --- | | `id` | string | | | `marketId` | string | | | `walletId` | string | | | `side` | Side | | | `outcome` | Outcome | | | `type` | OrderType | | | `price` | integer | Limit price, in this outcome's cents (market orders: 99 to buy, 1 to sell) | | `quantity` | integer | | | `filledQuantity` | integer | | | `remainingQuantity` | integer | Shares still on the book (0 once filled or cancelled) | | `status` | OrderStatus | | | `createdAt` | string (date-time) | When it was placed | | `updatedAt` | string (date-time) | When it last changed | | `canceledAt` | string (date-time) \| null | | | `botId` | string \| null | The VPX bot that placed it, if any | | `clientOrderId` | string \| null | The bot's own id for the order (VPX bots only) | ### OrderWithFills | Field | Type | Description | | --- | --- | --- | | `id` | string | | | `marketId` | string | | | `walletId` | string | | | `side` | Side | | | `outcome` | Outcome | | | `type` | OrderType | | | `price` | integer | Limit price, in this outcome's cents (market orders: 99 to buy, 1 to sell) | | `quantity` | integer | | | `filledQuantity` | integer | | | `remainingQuantity` | integer | Shares still on the book (0 once filled or cancelled) | | `status` | OrderStatus | | | `createdAt` | string (date-time) | When it was placed | | `updatedAt` | string (date-time) | When it last changed | | `canceledAt` | string (date-time) \| null | | | `botId` | string \| null | The VPX bot that placed it, if any | | `clientOrderId` | string \| null | The bot's own id for the order (VPX bots only) | | `fills` | Fill[] | Its fills, oldest first | ### Position | Field | Type | Description | | --- | --- | --- | | `walletId` | string | | | `marketId` | string | | | `marketQuestion` | string | | | `marketStatus` | MarketStatus | | | `private` | boolean | | | `outcome` | Outcome | | | `quantity` | integer | Shares held, including those your open sell orders hold | | `lockedQuantity` | integer | Shares your open sell orders hold | | `bid` | integer \| null | | | `ask` | integer \| null | | | `lastPrice` | integer \| null | | | `payout` | integer \| null | | | `updatedAt` | string (date-time) | When the position last changed | ### Settlement A resolved market you held shares in, and what it paid. VPX pays winning shares automatically. | Field | Type | Description | | --- | --- | --- | | `marketId` | string | | | `marketQuestion` | string | | | `walletId` | string | | | `outcome` | Outcome | The winning outcome | | `resolvedAt` | string (date-time) | When the market resolved | | `yesQuantity` | integer | YES shares you held | | `noQuantity` | integer | NO shares you held | | `yesPayout` | integer | What each YES share paid | | `noPayout` | integer | What each NO share paid | | `payout` | integer | What VPX paid you: yesQuantity × yesPayout + noQuantity × noPayout | ### Snapshot | Field | Type | Description | | --- | --- | --- | | `date` | string | The day (UTC), YYYY-MM-DD | | `cash` | integer | Main wallet cash | | `holdingsValue` | integer | Open positions at their last traded price | | `totalValue` | integer | cash + holdingsValue |