Olympus
Documentation

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:

EndpointLimit
GET /v1/portfolio30 requests per minute
GET /v1/trades/:tradeId100 requests per minute
POST /v1/trade60 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:

OutcomeoutcomeLabeltokenId
YesYes98022490269692409998126496127597032490334070080325855126491859374983463996227
NoNo53831553061883006530739877284105938919721408776239639687877978808906551086026

For Olympus:

Olympus fieldPolymarket fieldExample
tokenIdOne value from clobTokenIds98022490269692409998126496127597032490334070080325855126491859374983463996227
conditionIdconditionId0x1fad72fae204143ff1c3035e99e7c0f65ea8d5cd9bd1070987bd1a3316f772be
marketTitlequestionNew Rihanna Album before GTA VI?
marketIdid540817
marketSlugslugnew-rhianna-album-before-gta-vi-926
outcomeLabelMatching value from outcomesYes

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:

FieldRequiredNotes
sideYesMust be BUY.
tokenIdYesPick the outcome token from Polymarket clobTokenIds. For a Yes buy in the example above, use the first token ID because outcomes[0] is Yes.
conditionIdYesUse the Polymarket market conditionId.
amountUsdYesUSD notional to spend from the linked Olympus wallet.
maxPriceNoMaximum acceptable price from 0 to 1; 0.62 means do not buy above 62c. Omit it to use the current market price behavior.
marketTitleYesUse the Polymarket question. This appears in Olympus logs and notifications.
marketIdNoUse the Polymarket Gamma id, or null if you do not have it.
marketSlugNoUse the Polymarket slug, or null if you do not have it.
outcomeLabelYesThe matching outcome label from Polymarket outcomes, such as Yes or No.
stopLossPercentNoAuto-sell when the position loses this percent from entry. 20 means sell after a 20% loss.
takeProfitPercentNoAuto-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:

FieldRequiredNotes
sideYesMust be SELL.
tokenIdYesUse the token you hold. From GET /v1/portfolio, this is positions[].asset.
conditionIdYesUse the same conditionId from the portfolio position or the Polymarket market.
sellSpecYesUse { "type": "percent", "sharePercent": 1-100 } to sell a percent of the position, or { "type": "shares", "sharesNormalized": 10 } to sell an exact share amount.
minPriceNoMinimum acceptable price from 0 to 1; 0.55 means do not sell below 55c.
marketTitleYesUse the market question/title.
marketIdNoUse the Gamma market ID from Polymarket or your portfolio position, or null.
marketSlugNoUse 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:

StatusMeaning
400Invalid JSON or request body.
401Missing, invalid, or deleted API key.
403Trading is blocked, terms acceptance is required, or region is restricted.
412The linked wallet is currently being upgraded.
429Rate limit exceeded. Wait for the Retry-After duration before retrying.
500Temporary 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.