Trading API
Use the Olympus Trading API to read your pUSD balance, positions, and equity in one call, or to queue buy and sell trades from your selected Olympus wallet, including buys with built-in stop losses and take profits.
Create an API key
Log in to create a wallet-scoped API key. Keys can trade only from the wallet you select.
Authentication
Create an API key while logged in above. Each key is linked to one wallet:
- Olympus Wallet by default — your current Olympus-created EOA/Safe/deposit wallet.
- Imported wallet when you select one before creating the key.
The plaintext key is shown only once. After creation, the UI displays only the first four characters and lets you delete the key.
Send the key as a bearer token:
Authorization: Bearer YOUR_API_KEY
You can also send it with X-API-Key, but Authorization: Bearer is preferred.
Base URL
Use the Olympus production API host:
https://api.olympusx.app
Rate limits
Rate limits are enforced per API key:
| Endpoint | Limit |
|---|---|
GET /v1/portfolio | 30 requests per minute |
GET /v1/trades/:tradeId | 100 requests per minute |
POST /v1/trade | 60 requests per minute |
When you exceed a limit, Olympus returns 429 Too Many Requests with a Retry-After header in seconds.
Find Polymarket market fields
Olympus uses Polymarket market identifiers. You can get them from Polymarket's public APIs before
calling POST /v1/trade.
Useful Polymarket docs:
Fetch a market by slug:
curl "https://gamma-api.polymarket.com/markets?slug=new-rhianna-album-before-gta-vi-926"
Or fetch active order-book markets:
curl "https://gamma-api.polymarket.com/markets?active=true&closed=false&enableOrderBook=true&limit=1"
Example Polymarket market data:
{
"id": "540817",
"question": "New Rihanna Album before GTA VI?",
"conditionId": "0x1fad72fae204143ff1c3035e99e7c0f65ea8d5cd9bd1070987bd1a3316f772be",
"slug": "new-rhianna-album-before-gta-vi-926",
"outcomes": "[\"Yes\", \"No\"]",
"clobTokenIds": "[\"98022490269692409998126496127597032490334070080325855126491859374983463996227\", \"53831553061883006530739877284105938919721408776239639687877978808906551086026\"]",
"enableOrderBook": true,
"acceptingOrders": true
}
Parse outcomes and clobTokenIds before choosing a token:
const [market] = await fetch(
'https://gamma-api.polymarket.com/markets?slug=new-rhianna-album-before-gta-vi-926',
).then((res) => res.json());
const outcomes = JSON.parse(market.outcomes);
const tokenIds = JSON.parse(market.clobTokenIds);
console.log({
conditionId: market.conditionId,
marketId: market.id,
marketSlug: market.slug,
marketTitle: market.question,
yesTokenId: tokenIds[outcomes.indexOf('Yes')],
noTokenId: tokenIds[outcomes.indexOf('No')],
});
Use the matching index in outcomes and clobTokenIds:
| Outcome | outcomeLabel | tokenId |
|---|---|---|
| Yes | Yes | 98022490269692409998126496127597032490334070080325855126491859374983463996227 |
| No | No | 53831553061883006530739877284105938919721408776239639687877978808906551086026 |
For Olympus:
| Olympus field | Polymarket field | Example |
|---|---|---|
tokenId | One value from clobTokenIds | 98022490269692409998126496127597032490334070080325855126491859374983463996227 |
conditionId | conditionId | 0x1fad72fae204143ff1c3035e99e7c0f65ea8d5cd9bd1070987bd1a3316f772be |
marketTitle | question | New Rihanna Album before GTA VI? |
marketId | id | 540817 |
marketSlug | slug | new-rhianna-album-before-gta-vi-926 |
outcomeLabel | Matching value from outcomes | Yes |
Only submit trades for markets where enableOrderBook is true and the market is accepting orders.
GET /v1/portfolio
Returns your linked wallet's pUSD balance, total cash balance, open positions, open-position value, and equity in one response.
curl https://api.olympusx.app/v1/portfolio \
-H "Authorization: Bearer YOUR_API_KEY"
Example response:
{
"walletAddress": "0x...",
"pusdBalance": 125.5,
"totalCashBalanceUsd": 125.5,
"positionsValueUsd": 74.25,
"equityUsd": 199.75,
"positionCount": 2,
"positions": [
{
"asset": "98022490269692409998126496127597032490334070080325855126491859374983463996227",
"conditionId": "0x1fad72fae204143ff1c3035e99e7c0f65ea8d5cd9bd1070987bd1a3316f772be",
"marketId": "540817",
"slug": "new-rhianna-album-before-gta-vi-926",
"title": "Yes",
"size": 128.75,
"avgPrice": 0.56,
"curPrice": 0.58,
"currentValue": 74.25,
"cashPnl": 2.58,
"percentPnl": 3.58,
"redeemable": false
}
],
"calculatedAt": "2026-05-09T00:00:00.000Z"
}
equityUsd is totalCashBalanceUsd + positionsValueUsd.
For sells, use a position's asset as the trade tokenId, and reuse its conditionId,
marketId, slug, and title/outcome metadata when building the sell request.
POST /v1/trade
Queues a trade exactly like a manual trade from the Olympus frontend. The response returns a tradeId; execution happens asynchronously through the same worker queue used by the app.
Buy Yes with stop-loss and take-profit
curl https://api.olympusx.app/v1/trade \
-X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"side": "BUY",
"tokenId": "98022490269692409998126496127597032490334070080325855126491859374983463996227",
"conditionId": "0x1fad72fae204143ff1c3035e99e7c0f65ea8d5cd9bd1070987bd1a3316f772be",
"amountUsd": 25,
"maxPrice": 0.62,
"marketTitle": "New Rihanna Album before GTA VI?",
"marketId": "540817",
"marketSlug": "new-rhianna-album-before-gta-vi-926",
"outcomeLabel": "Yes",
"stopLossPercent": 20,
"takeProfitPercent": 50
}'
Buy fields:
| Field | Required | Notes |
|---|---|---|
side | Yes | Must be BUY. |
tokenId | Yes | Pick the outcome token from Polymarket clobTokenIds. For a Yes buy in the example above, use the first token ID because outcomes[0] is Yes. |
conditionId | Yes | Use the Polymarket market conditionId. |
amountUsd | Yes | USD notional to spend from the linked Olympus wallet. |
maxPrice | No | Maximum acceptable price from 0 to 1; 0.62 means do not buy above 62c. Omit it to use the current market price behavior. |
marketTitle | Yes | Use the Polymarket question. This appears in Olympus logs and notifications. |
marketId | No | Use the Polymarket Gamma id, or null if you do not have it. |
marketSlug | No | Use the Polymarket slug, or null if you do not have it. |
outcomeLabel | Yes | The matching outcome label from Polymarket outcomes, such as Yes or No. |
stopLossPercent | No | Auto-sell when the position loses this percent from entry. 20 means sell after a 20% loss. |
takeProfitPercent | No | Auto-sell when the position gains this percent from entry. 50 means sell after a 50% gain. |
Buy No
To buy the No side of the same market, use the second token ID and set outcomeLabel to No:
{
"side": "BUY",
"tokenId": "53831553061883006530739877284105938919721408776239639687877978808906551086026",
"conditionId": "0x1fad72fae204143ff1c3035e99e7c0f65ea8d5cd9bd1070987bd1a3316f772be",
"amountUsd": 25,
"maxPrice": 0.45,
"marketTitle": "New Rihanna Album before GTA VI?",
"marketId": "540817",
"marketSlug": "new-rhianna-album-before-gta-vi-926",
"outcomeLabel": "No"
}
Sell by percent
curl https://api.olympusx.app/v1/trade \
-X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"side": "SELL",
"tokenId": "98022490269692409998126496127597032490334070080325855126491859374983463996227",
"conditionId": "0x1fad72fae204143ff1c3035e99e7c0f65ea8d5cd9bd1070987bd1a3316f772be",
"sellSpec": { "type": "percent", "sharePercent": 100 },
"minPrice": 0.55,
"marketTitle": "New Rihanna Album before GTA VI?",
"marketId": "540817",
"marketSlug": "new-rhianna-album-before-gta-vi-926"
}'
Sell by shares
{
"side": "SELL",
"tokenId": "98022490269692409998126496127597032490334070080325855126491859374983463996227",
"conditionId": "0x1fad72fae204143ff1c3035e99e7c0f65ea8d5cd9bd1070987bd1a3316f772be",
"sellSpec": { "type": "shares", "sharesNormalized": 25 },
"minPrice": 0.55,
"marketTitle": "New Rihanna Album before GTA VI?",
"marketId": "540817",
"marketSlug": "new-rhianna-album-before-gta-vi-926"
}
Sell fields:
| Field | Required | Notes |
|---|---|---|
side | Yes | Must be SELL. |
tokenId | Yes | Use the token you hold. From GET /v1/portfolio, this is positions[].asset. |
conditionId | Yes | Use the same conditionId from the portfolio position or the Polymarket market. |
sellSpec | Yes | Use { "type": "percent", "sharePercent": 1-100 } to sell a percent of the position, or { "type": "shares", "sharesNormalized": 10 } to sell an exact share amount. |
minPrice | No | Minimum acceptable price from 0 to 1; 0.55 means do not sell below 55c. |
marketTitle | Yes | Use the market question/title. |
marketId | No | Use the Gamma market ID from Polymarket or your portfolio position, or null. |
marketSlug | No | Use the market slug from Polymarket or your portfolio position, or null. |
Example queued response:
{
"success": true,
"tradeId": "tr_1234abcd5678ef90",
"status": "QUEUED"
}
Check trade status
curl https://api.olympusx.app/v1/trades/tr_1234abcd5678ef90 \
-H "Authorization: Bearer YOUR_API_KEY"
The status response moves through QUEUED, PROCESSING, then either SUCCEEDED or FAILED.
Successful fills include orderHash, transactionHash, filled shares, filled price, and USD fill
value when available.
Example successful status response:
{
"tradeId": "tr_1234abcd5678ef90",
"status": "SUCCEEDED",
"side": "BUY",
"tokenId": "98022490269692409998126496127597032490334070080325855126491859374983463996227",
"conditionId": "0x1fad72fae204143ff1c3035e99e7c0f65ea8d5cd9bd1070987bd1a3316f772be",
"marketTitle": "New Rihanna Album before GTA VI?",
"marketId": "540817",
"marketSlug": "new-rhianna-album-before-gta-vi-926",
"outcomeLabel": "Yes",
"requestedAmountUsd": 25,
"requestedSellSpec": null,
"orderHash": "0x...",
"transactionHash": "0x...",
"filledSharesNormalized": 43.1,
"filledPrice": 0.58,
"spentUsd": 25,
"errorCode": null,
"errorMessage": null,
"createdAt": "2026-05-09T00:00:00.000Z",
"updatedAt": "2026-05-09T00:00:01.000Z",
"completedAt": "2026-05-09T00:00:01.000Z"
}
Errors
Errors use this shape:
{
"error": "UNAUTHORIZED",
"message": "Invalid API key."
}
Rate-limit responses include Retry-After:
{
"error": "TOO_MANY_REQUESTS",
"message": "Rate limit exceeded. Try again later."
}
Common status codes:
| Status | Meaning |
|---|---|
400 | Invalid JSON or request body. |
401 | Missing, invalid, or deleted API key. |
403 | Trading is blocked, terms acceptance is required, or region is restricted. |
412 | The linked wallet is currently being upgraded. |
429 | Rate limit exceeded. Wait for the Retry-After duration before retrying. |
500 | Temporary server error. |
Security notes
- Keep API keys secret. Anyone with the key can trade from the linked wallet.
- Delete a key immediately if it is exposed.
- Create separate keys for separate wallets when you want wallet-level isolation.
- Olympus stores only a hash of your key, so the plaintext value cannot be recovered after the one-time display.

