Skip to main content

Base URL

https://api.pmx.trade
All endpoints are prefixed with /v2.

Non-Custodial Design

All write endpoints (create, buy, sell, redeem, claim-fees, resolve) return an unsigned Solana transaction as a base64 string. Your application deserializes the transaction, signs it locally with the user’s wallet, and submits it to the Solana network. The API never has access to private keys.

Custom Outcome Names

Markets define their own ticker names for the two outcomes (e.g. UP/DOWN, FLIP/NOFLIP). When calling any endpoint that takes a side parameter, you can pass either:
  • The market’s custom ticker (e.g. UP, DOWN)
  • The canonical YES / NO (where YES = first outcome, NO = second outcome)
The API resolves the ticker to the correct on-chain outcome automatically.
const { data } = await res.json();
const tx = Transaction.from(Buffer.from(data.transaction, "base64"));
tx.sign(wallet);
const sig = await connection.sendRawTransaction(tx.serialize());

Authentication

No API key required. All endpoints are open access with rate limiting.

Rate Limits

The API uses per-route rate limiting:
Request TypeLimit
Read (GET, HEAD)600 requests/minute
Write (POST, PUT, DELETE)300 requests/minute
Read endpoints have a higher limit since they don’t modify state. If you hit the rate limit, you’ll receive a 429 response. Implement exponential backoff and retry.

Idempotent Endpoints

Several endpoints are idempotent — calling them multiple times produces the same result without errors:
EndpointIdempotent behavior
POST /v2/markets/:id/redeemReturns alreadyRedeemed: true if no tokens to redeem
POST /v2/markets/:id/claim-feesReturns noFees: true if no fees to claim
POST /v2/markets/:id/resolveReturns alreadyResolved: true if already resolved
POST /v2/redeem-allReturns empty transactions array with skipped list if nothing to redeem
POST /v2/claim-all-feesReturns empty transactions array with skipped list if nothing to claim
This means you can safely retry these operations without worrying about duplicate errors.

Response format

All responses follow a consistent structure:
{
  "success": true,
  "data": { ... }
}
Error responses:
{
  "success": false,
  "error": "Market not found"
}

Status codes

CodeMeaning
200Success
400Bad request — invalid parameters or constraint violation
403Forbidden — wallet is not authorized for this action (e.g. not the market creator)
404Not found
409Conflict — action not allowed in current state (e.g. trading on a resolved market, selling on a Pool market)
429Rate limited — slow down
500Server error

Endpoints

Markets (read)

MethodEndpointDescription
GET/v2/marketsList markets — broken markets auto-filtered
GET/v2/markets/:idGet market details — includes fees, mint status
GET/v2/markets/:id/quoteGet a price quote

Market Creation (returns unsigned transactions)

MethodEndpointDescription
POST/v2/markets/createCreate a market — validates resolution timestamp
GET/v2/configGet on-chain config (includes marketCounter — the newest market ID)
POST/v2/markets/:id/init-mintsInitialize YES/NO token mints (required after create)
POST/v2/markets/confirmPersist market metadata to backend (makes it visible on the website)
You must call /v2/markets/:id/init-mints after creating a market. Without it, the market’s token mints are uninitialized and all trades will fail. See the Full Market Lifecycle guide.

Trading (returns unsigned transactions)

MethodEndpointDescription
POST/v2/markets/:id/buyBuy outcome tokens
POST/v2/markets/:id/sellSell outcome tokens

Resolution & Redemption (returns unsigned transactions)

MethodEndpointDescription
POST/v2/markets/:id/resolveResolve market — idempotent, auto-syncs Supabase
POST/v2/markets/:id/redeemRedeem winnings — idempotent
POST/v2/markets/:id/claim-feesClaim trade fees — idempotent

Batch Operations (returns multiple unsigned transactions)

MethodEndpointDescription
POST/v2/redeem-allRedeem all winning positions for a wallet
POST/v2/claim-all-feesClaim all accrued fees for a creator
The batch endpoints scan wallet token accounts directly and are much faster than calling individual redemption/claim endpoints in a loop. Use them for cleanup and portfolio management.

Positions (read)

MethodEndpointDescription
GET/v2/positions/:walletGet all positions — enriched with needsRedemption, winningSide
GET/v2/positions/:wallet/:marketIdGet single position

Raw Units

All token and USDC amounts in requests and responses use raw units (6 decimal places, matching USDC/SPL token decimals):
Human AmountRaw Units
$1.00 USDC1,000,000
$100 USDC100,000,000
0.10 USDC100,000
Many endpoints also include *Human fields (e.g. yesBalanceHuman, feesAccruedHuman) for convenience.