# 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": "<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=<a few seconds before the previous answer's now>` 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
