API Documentation
Everything you need to integrate Cashmere into your application. Prediction market data from every platform through a single API.
Quick Start
Install the SDK, initialize the client with your API key, and start querying markets.
npm install @cashmere/sdkimport { CashmereClient } from "@cashmere/sdk"
const cashmere = new CashmereClient({
apiKey: "vk_live_..."
})
const { data } = await cashmere.getMarkets({
sort: "volume",
limit: 10,
})Authentication
All endpoints except /v1/health require an API key passed via the x-api-key header.
x-api-keyheaderrequiredYour API key. Recommended method.
api_keyqueryAlternative: pass as query parameter.
curl -H "x-api-key: YOUR_API_KEY" \
https://api.cashmerelabs.xyz/v1/markets/v1/marketsList Markets
List markets across all platforms with filtering, sorting, and pagination.
platformstring"polymarket", "kalshi", "opinion", "predict", "forecastex", "overtime", "myriad". Omit for all.
querystringFull-text search query string.
statusstring"active", "closed", or "resolved".
categorystringFilter by category slug.
sortstring"volume", "liquidity", "newest", or "ending_soon".
limitnumberResults per page (1-100, default 20).
cursorstringPagination cursor from previous response.
curl -X GET "https://api.cashmerelabs.xyz/v1/markets?platform=polymarket&sort=volume&limit=5" \
-H "x-api-key: YOUR_API_KEY"{
"data": [
{
"id": "polymarket:0x1234...",
"platform": "polymarket",
"platformMarketId": "0x1234...",
"platformUrl": "https://polymarket.com/event/...",
"title": "Will X happen by Y?",
"description": "...",
"probability": 0.65,
"outcomes": [
{ "name": "Yes", "probability": 0.65 },
{ "name": "No", "probability": 0.35 }
],
"volume": 1250000,
"volumeCurrency": "USDC",
"liquidity": 85000,
"status": "active",
"createdAt": "2025-01-15T00:00:00Z",
"endDate": "2025-12-31T00:00:00Z",
"lastUpdatedAt": "2025-06-20T12:34:56Z"
}
],
"count": 5,
"nextCursor": "5"
}/v1/markets/:idGet Market
Get a single market by its Cashmere ID. The ID format is {platform}:{platformMarketId}, for example kalshi:BTC-100K-2025.
curl -X GET "https://api.cashmerelabs.xyz/v1/markets/polymarket:0x1234" \
-H "x-api-key: YOUR_API_KEY"{
"data": {
"id": "polymarket:0x1234...",
"platform": "polymarket",
"title": "Will X happen by Y?",
"probability": 0.65,
"volume": 1250000,
"status": "active"
}
}/v1/orderbooks/:marketIdGet Orderbook
Get the unified orderbook for a market. Aggregates depth from Polymarket and Kalshi.
curl -X GET "https://api.cashmerelabs.xyz/v1/orderbooks/polymarket:0x1234" \
-H "x-api-key: YOUR_API_KEY"{
"data": {
"marketId": "polymarket:0x1234",
"platform": "polymarket",
"bids": [
{ "price": 0.62, "size": 500 },
{ "price": 0.61, "size": 1200 }
],
"asks": [
{ "price": 0.64, "size": 800 },
{ "price": 0.65, "size": 300 }
],
"spread": 0.02,
"midpoint": 0.63,
"lastUpdatedAt": "2025-06-20T12:34:56Z"
}
}/v1/candles/:marketIdGet Candles
Get OHLC candlestick data for a market. Useful for charting price history.
intervalstring"1m", "5m", "15m", "1h", "4h", "1d". Default "1h".
startstringISO 8601 start time.
endstringISO 8601 end time.
limitnumberMax candles to return (1-1000, default 100).
curl -X GET "https://api.cashmerelabs.xyz/v1/candles/polymarket:0x1234?interval=1h&limit=24" \
-H "x-api-key: YOUR_API_KEY"{
"data": [
{
"timestamp": "2025-06-20T12:00:00Z",
"open": 0.62,
"high": 0.68,
"low": 0.61,
"close": 0.65,
"volume": 12400
}
],
"count": 24
}/v1/alertsList Alerts
List all alerts configured for the authenticated API key.
curl -X GET "https://api.cashmerelabs.xyz/v1/alerts" \
-H "x-api-key: YOUR_API_KEY"{
"data": [
{
"id": "alert_01",
"marketId": "polymarket:0x1234",
"condition": { "type": "price_above", "threshold": 0.8 },
"delivery": { "type": "webhook", "url": "https://..." },
"status": "active",
"createdAt": "2025-06-20T10:00:00Z"
}
]
}/v1/alertsCreate Alert
Create a new alert with a condition and delivery configuration. Fires when the condition is met.
marketIdstringrequiredThe Cashmere market ID to monitor.
condition.typestringrequired"price_above", "price_below", "price_change", "volume_spike", or "market_resolved".
condition.thresholdnumberThreshold value for price conditions.
condition.percentChangenumberPercentage change for price_change alerts.
condition.windowMsnumberTime window in milliseconds.
delivery.typestringrequired"webhook" or "websocket".
delivery.urlstringWebhook URL (required for webhook delivery).
delivery.headersobjectOptional headers to include in webhook requests.
curl -X POST "https://api.cashmerelabs.xyz/v1/alerts" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"marketId": "polymarket:0x1234",
"condition": { "type": "price_above", "threshold": 0.8 },
"delivery": { "type": "webhook", "url": "https://your-server.com/hook" }
}'{
"data": {
"id": "alert_02",
"marketId": "polymarket:0x1234",
"condition": { "type": "price_above", "threshold": 0.8 },
"delivery": { "type": "webhook", "url": "https://your-server.com/hook" },
"status": "active",
"createdAt": "2025-06-20T12:00:00Z"
}
}/v1/alerts/:idDelete Alert
Delete an alert by its ID. Returns 204 on success.
curl -X DELETE "https://api.cashmerelabs.xyz/v1/alerts/alert_02" \
-H "x-api-key: YOUR_API_KEY"/v1/portfolioGet Portfolio
Get aggregated cross-platform positions. Requires platform API keys configured server-side.
curl -X GET "https://api.cashmerelabs.xyz/v1/portfolio" \
-H "x-api-key: YOUR_API_KEY"{
"data": {
"positions": [...],
"totalValue": 5240.50,
"totalPnl": 340.20,
"byPlatform": {
"polymarket": { "positions": [...], "value": 3200, "pnl": 200 },
"kalshi": { "positions": [...], "value": 2040.50, "pnl": 140.20 }
}
}
}/v1/walletsList Wallets
List connected wallet addresses and their balances across platforms.
curl -X GET "https://api.cashmerelabs.xyz/v1/wallets" \
-H "x-api-key: YOUR_API_KEY"{
"data": [
{
"platform": "polymarket",
"address": "0xabc...",
"balance": 1250.00,
"currency": "USDC"
}
]
}WebSocket
Connect to wss://api.cashmerelabs.xyz/v1/ws and subscribe to real-time channels.
market:updatedchannelFires when market data changes.
market:newchannelFires when a new market is listed.
market:resolvedchannelFires when a market resolves.
orderbook:updatedchannelFires on orderbook depth changes.
price:changedchannelFires on price movement.
*channelSubscribe to all channels.
{"action": "subscribe", "channel": "price:changed"}
{"action": "subscribe", "channel": "orderbook:updated"}{
"type": "event",
"channel": "price:changed",
"data": {
"marketId": "polymarket:0x123",
"platform": "polymarket",
"oldPrice": 0.65,
"newPrice": 0.68
}
}/v1/streamServer-Sent Events
Lightweight alternative to WebSocket. Pass channels as a comma-separated query parameter, or omit for all events.
channelsstringComma-separated channel names to subscribe to.
curl -N -H "x-api-key: vk_live_..." \
"https://api.cashmerelabs.xyz/v1/stream?channels=price:changed,orderbook:updated"TypeScript SDK
The official SDK provides typed methods for every endpoint plus async iterator streaming.
Every REST endpoint has a corresponding SDK method with full TypeScript types.
Streaming uses async iterators — for await over real-time events.
import { CashmereClient } from "@cashmere/sdk"
const cashmere = new CashmereClient({ apiKey: "vk_live_..." })
// Markets
const markets = await cashmere.getMarkets({ sort: "volume" })
// Alerts
await cashmere.createAlert({
marketId: "polymarket:0x1234",
condition: { type: "price_above", threshold: 0.9 },
delivery: { type: "webhook", url: "https://..." },
})
// Streaming (async iterator)
for await (const event of cashmere.stream(["price:changed"])) {
console.log(event.channel, event.data)
}Error Handling
All errors return JSON with an error field and the appropriate HTTP status code.
400Bad RequestInvalid query parameters or request body.
401UnauthorizedMissing API key.
403ForbiddenInvalid API key.
404Not FoundResource not found.
429Too Many RequestsRate limit exceeded. Check Retry-After header.
500Server ErrorInternal server error.
{ "error": "Rate limit exceeded." }import { CashmereRateLimitError } from "@cashmere/sdk"
try {
await cashmere.getMarkets()
} catch (err) {
if (err instanceof CashmereRateLimitError) {
console.log("Retry after", err.retryAfter, "s")
}
}Rate Limits
Rate limits are applied per API key using a sliding window. Headers are included in every response.
| Tier | Rate | Streaming |
|---|---|---|
| Free | 1 req/sec | 1 connection |
| Pro | 100 req/sec | 10 connections |
| Enterprise | Unlimited | Unlimited |
X-RateLimit-LimitX-RateLimit-RemainingRetry-After