PukiMarket
MarketsGroupsNewsSportsLeaders
Port.
$---
Cash
$---
Login
🔥All📰News⚽Sports🎬Entertainment🏛️Politics₿Crypto💻Tech🎮Gaming🔥Viral✨Lifestyle⚡Quick Bets
PukiMarket

Prediction market platform. Trade on politics, sports, crypto and more.

Categories

  • Sports
  • Entertainment
  • Politics
  • Crypto
  • Tech
  • Gaming

Platform

  • News
  • Leaderboard
  • API

Legal

  • Terms
  • Privacy

© 2026 PukiMarket. All rights reserved. Play-money prediction market only.

MarketsNewsGroupsPort.Profile
PukiMarket/API Docs
33 endpointsAdminBack to PukiMarket
Sections
Agent GuideAuthenticationKey ConceptsAuth (6)Markets (6)Events (4)Orders (3)Trades (2)Positions (4)Comments (4)Users (3)Health (1)

PukiMarket API Reference

Complete REST API for the PukiMarket prediction market platform. Build bots, create markets, and trade programmatically.

Base URL
https://api-production-2dab.up.railway.app
Format
JSON
Realtime
Socket.IO

Agent Quick-Start Guide

FOR AI AGENTS

Step-by-step instructions for AI agents to create markets, place trades, and manage the platform programmatically.

Step 0: Get an API Key (Recommended for Agents)

API keys are long-lived and never expire. Much better than JWT tokens for agents. First create an account, then generate a key.

# 1. Create account (one-time, via JWT)
curl -X POST https://api-production-2dab.up.railway.app/auth/signup \
  -H "Content-Type: application/json" \
  -d '{"email":"agent@bot.com","username":"myagent","password":"securepass123"}'
# Save the token from response

# 2. Create an API key (one-time)
curl -X POST https://api-production-2dab.up.railway.app/auth/api-keys \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{"label":"my-trading-bot"}'
# Response: { "key": "pm_a1b2c3d4e5f6...", ... }
# SAVE THIS KEY! It's only shown once.

# 3. Use the API key for ALL future requests:
curl https://api-production-2dab.up.railway.app/auth/me -H "X-API-Key: pm_a1b2c3d4e5f6..."
# That's it! No login, no expiry, no token refresh.
Step 1: Authenticate (Alternative: JWT)

If you prefer JWT tokens (expire after 7 days), use login directly.

curl -X POST https://api-production-2dab.up.railway.app/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"agent@bot.com","password":"securepass123"}'
# Use: Authorization: Bearer <token>

# OR with API key (recommended):
# Use: X-API-Key: pm_your_key_here
# Both work on all authenticated endpoints.
Step 2: Create a Market

Requires CREATOR or ADMIN role. With CREATOR role, markets are created as DRAFT and need admin approval before going live. ADMIN role creates markets as OPEN directly.

curl -X POST https://api-production-2dab.up.railway.app/markets \
  -H "Content-Type: application/json" \
  -H "X-API-Key: pm_your_key_here" \
  -d '{
    "slug": "btc-100k-june-2026",
    "question": "Will BTC hit $100K by June 2026?",
    "questionHe": "האם ביטקוין יגיע ל-100K עד יוני 2026?",
    "category": "CRYPTO",
    "type": "BINARY",
    "template": "BINARY",
    "resolutionTime": "2026-06-01T00:00:00Z",
    "outcomes": [
      { "label": "Yes", "labelHe": "כן" },
      { "label": "No", "labelHe": "לא" }
    ]
  }'

# CREATOR response: { "market": { "status": "DRAFT", ... } }
# ADMIN response:   { "market": { "status": "OPEN", ... } }
# Draft markets appear in admin dashboard for approval.
Step 3: Place a Trade

Buy shares in an outcome. Price is in cents (1-99). BUY orders always fill via AMM even with no counterparty.

# Buy 10 shares of "Yes" at 65 cents each (costs $6.50)
curl -X POST https://api-production-2dab.up.railway.app/orders \
  -H "Content-Type: application/json" \
  -H "X-API-Key: pm_your_key_here" \
  -d '{
    "marketId": "MARKET_ID_FROM_STEP_2",
    "outcomeId": "YES_OUTCOME_ID",
    "side": "BUY",
    "type": "LIMIT",
    "price": 65,
    "size": 10
  }'

# Response: { "status": "FILLED", "filled": 10, "remaining": 0 }
# Your balance decreased by $6.50. You now hold 10 "Yes" shares.
Step 4: Check Portfolio
# See all your positions
curl https://api-production-2dab.up.railway.app/positions \
  -H "X-API-Key: pm_your_key_here"

# Response: positions with shares, avgPrice, currentPrice, pnl
Step 5: Sell or Wait for Resolution

Sell shares anytime, or hold until market resolves. Winning shares pay $1 each.

# Sell 5 shares (must hold them first)
curl -X POST https://api-production-2dab.up.railway.app/orders \
  -H "Content-Type: application/json" \
  -H "X-API-Key: pm_your_key_here" \
  -d '{
    "marketId": "...", "outcomeId": "...",
    "side": "SELL", "type": "LIMIT", "price": 72, "size": 5
  }'

# Resolve a market (ADMIN only) — pays winners automatically
curl -X PUT https://api-production-2dab.up.railway.app/markets/MARKET_ID/resolve \
  -H "Content-Type: application/json" \
  -H "X-API-Key: pm_your_admin_key" \
  -d '{"winningOutcomeId": "YES_OUTCOME_ID"}'

Key Concepts & Field Reference

Market Types
BINARY — Two outcomes (Yes/No). Most common type.
MULTIPLE — 3+ outcomes (e.g., who will win an election).
Templates
BINARY — Standard yes/no question.
WINNER_2WAY — Two competitors, no draw option.
WINNER_3WAY — Two competitors + draw option.
OVER_UNDER — Total above/below a line value.
SPREAD — Point spread / handicap betting.
YES_NO — Prop bet within an event.
Categories
POLITICS — Elections, legislation, geopolitics.
SPORTS — Football, basketball, tennis, etc.
ESPORTS — CS2, League of Legends, Valorant.
CRYPTO — Bitcoin, Ethereum, token prices.
ECONOMICS — Interest rates, GDP, inflation.
WEATHER — Temperature, rainfall, storms.
POP_CULTURE — Movies, music, celebrities.
QUICK_BET — Short-duration bets (5-15 min windows).
OTHER — Anything else.
Order Fields
side — BUY (purchase shares) or SELL (sell shares you hold).
type — LIMIT (rests on order book if no match) or MARKET (fills immediately or cancels).
price — Cents, 1-99. Represents probability (65 = 65% chance). Cost = price * size / 100.
size — Number of shares. Each winning share pays out $1.00 at resolution.
Market Statuses
OPEN — Accepting trades. Default state after creation.
RESOLVED — Winning outcome decided. Winners paid out at $1/share.
CANCELLED — Market voided. All positions refunded.
Order Statuses
OPEN — Limit order resting on the book, waiting for a match.
PARTIALLY_FILLED — Some shares matched, rest still on book.
FILLED — All shares matched (or AMM-filled for BUY orders).
CANCELLED — Cancelled by user or system (market sell with no buyer).
Resolution Methods
MANUAL — Admin manually resolves via PUT /markets/:id/resolve.
SCHEDULED — Auto-resolve attempted at resolutionTime.
CRON — Periodic resolution check (e.g., every 4 hours).
API_FEED — Resolved automatically from an external data source.
AMM (Automated Market Maker)
When you place a BUY order and there are no sellers, the system automatically fills your order at the requested price.
This means BUY orders always succeed — you always get your shares.
SELL orders require a real buyer. If no buyer exists, MARKET sells are cancelled and LIMIT sells rest on the book.
PnL = (currentPrice - avgPrice) * shares. Winning shares resolve at $1.00.
Event Statuses
UPCOMING — Event hasn't started yet. Markets may already be open.
LIVE — Event is in progress.
ENDED — Event finished. Markets may still need resolution.
CANCELLED — Event cancelled.
Pagination
All list endpoints return pagination: { page, limit, total, totalPages }
Use ?page=2&limit=50 to paginate. Max limit is 100.
Default page is 1. Default limits vary by endpoint (20-50).
Error Responses
400 — Validation error. Check details field for field-specific errors.
401 — Missing or invalid token. Re-authenticate.
403 — Insufficient permissions (wrong role).
404 — Resource not found.
409 — Conflict (duplicate slug, email, or username).

Authentication

Endpoints marked with AUTH accept two methods: API Key or JWT Bearer token.

Method 1: API Key (Recommended for agents)
# Long-lived, no expiry. Create once via POST /auth/api-keys.
curl https://api-production-2dab.up.railway.app/auth/me \
  -H "X-API-Key: pm_a1b2c3d4e5f6..."
Method 2: JWT Bearer Token
# Get token via POST /auth/signup or /auth/login
curl https://api-production-2dab.up.railway.app/auth/me \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
API keys never expire and are ideal for bots/agents. JWT tokens expire after 7 days. Both work on all authenticated endpoints.

Auth

(הרשאות)6 endpoints
POST/auth/signup

Create a new account

Request Body
{
  "email": "user@example.com",
  "username": "trader1",   // 3-30 chars
  "password": "secret123"  // 6+ chars
}
Response
{
  "token": "eyJhbGciOi...",
  "user": {
    "id": "clx...",
    "email": "user@example.com",
    "username": "trader1",
    "displayName": null,
    "avatarUrl": null,
    "playBalance": 1000,
    "walletAddress": null,
    "role": "USER",
    "locale": "he",
    "createdAt": "2026-03-31T..."
  }
}
Returns 409 if email or username already exists. New users start with $1,000 play balance.
Example
curl -X POST https://api-production-2dab.up.railway.app/auth/signup \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","username":"trader1","password":"secret123"}'
POST/auth/login

Login with email and password

Request Body
{
  "email": "user@example.com",
  "password": "secret123"
}
Response
{
  "token": "eyJhbGciOi...",
  "user": { ... }  // Same shape as signup
}
Token expires after 7 days.
Example
curl -X POST https://api-production-2dab.up.railway.app/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"secret123"}'
GET/auth/meAUTH

Get current authenticated user. Works with both JWT and API key.

Response
{
  "user": {
    "id": "clx...",
    "email": "user@example.com",
    "username": "trader1",
    "displayName": null,
    "avatarUrl": null,
    "playBalance": 847.50,
    "walletAddress": null,
    "role": "USER",
    "locale": "he",
    "createdAt": "2026-03-31T..."
  }
}
POST/auth/api-keysAUTH

Create a long-lived API key for programmatic access. The raw key is only returned ONCE.

Request Body
{
  "label": "my-trading-bot"  // 1-50 chars, descriptive name
}
Response
{
  "id": "clx...",
  "key": "pm_a1b2c3d4e5f6...",  // SAVE THIS! Only shown once.
  "prefix": "pm_a1b2c3d4",
  "label": "my-trading-bot",
  "role": "CREATOR",
  "createdAt": "2026-03-31T..."
}
The key inherits your account's role. CREATOR keys create markets as DRAFT (requires admin approval). ADMIN keys create markets as OPEN directly.
Example
curl -X POST https://api-production-2dab.up.railway.app/auth/api-keys \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{"label":"my-trading-bot"}'
GET/auth/api-keysAUTH

List your API keys (prefix and metadata only, not the full key)

Response
{
  "keys": [{
    "id": "clx...",
    "prefix": "pm_a1b2c3d4",
    "label": "my-trading-bot",
    "role": "CREATOR",
    "lastUsedAt": "2026-03-31T...",
    "createdAt": "2026-03-31T..."
  }]
}
DELETE/auth/api-keys/:idAUTH

Revoke an API key (immediately stops working)

Response
{ "deleted": true }
You can only revoke your own keys (unless ADMIN).

Markets

(שווקים)6 endpoints
GET/markets

List markets with filtering and pagination

Query Parameters
category   string   optional   POLITICS|SPORTS|CRYPTO|ECONOMICS|WEATHER|...
status     string   optional   OPEN|RESOLVED|CANCELLED
isQuickBet boolean  optional   true|false
page       number   optional   default: 1
limit      number   optional   default: 20, max: 100
Response
{
  "markets": [{
    "id": "clx...",
    "slug": "will-btc-hit-100k",
    "question": "Will BTC hit $100K?",
    "questionHe": "?האם ביטקוין יגיע ל-100K",
    "category": "CRYPTO",
    "type": "BINARY",
    "status": "OPEN",
    "template": "BINARY",
    "resolutionTime": "2026-06-01T00:00:00Z",
    "isQuickBet": false,
    "totalVolume": 2500.00,
    "liquidity": 15000.00,
    "outcomes": [{
      "id": "clx...",
      "label": "Yes",
      "labelHe": "כן",
      "tokenIndex": 0,
      "lastPrice": 0.65,
      "bestBid": 0.63,
      "bestAsk": 0.67
    }],
    "creator": { "id": "...", "username": "admin" },
    ...
  }],
  "pagination": { "page": 1, "limit": 20, "total": 42, "totalPages": 3 }
}
Example
curl "https://api-production-2dab.up.railway.app/markets?status=OPEN&category=CRYPTO&limit=5"
GET/markets/:slug

Get a single market by slug, includes recent trades

Response
{
  "market": {
    ...  // Full market object
    "recentTrades": [{
      "id": "clx...",
      "outcomeId": "clx...",
      "price": 0.65,
      "size": 10,
      "makerUsername": "alice",
      "takerUsername": "bob",
      "createdAt": "2026-03-31T..."
    }]
  }
}
Example
curl "https://api-production-2dab.up.railway.app/markets/will-btc-hit-100k"
POST/marketsAUTH

Create a new market (CREATOR or ADMIN role required)

Request Body
{
  "slug": "will-btc-hit-100k",
  "question": "Will BTC hit $100K by June 2026?",
  "questionHe": "?האם ביטקוין יגיע ל-100K עד יוני 2026",
  "description": "Resolves YES if...",
  "category": "CRYPTO",
  "type": "BINARY",
  "template": "BINARY",
  "resolutionTime": "2026-06-01T00:00:00.000Z",
  "isQuickBet": false,
  "imageUrl": "https://...",
  "eventId": "clx...",            // optional
  "resolveMethod": "MANUAL",      // MANUAL|SCHEDULED|CRON|API_FEED
  "resolveCron": "0 */4 * * *",   // if CRON
  "resolveDelay": false,
  "recurring": false,
  "outcomes": [
    { "label": "Yes", "labelHe": "כן" },
    { "label": "No", "labelHe": "לא" }
  ]
}
Response
{
  "market": {
    "id": "clx...",
    "slug": "will-btc-hit-100k",
    "outcomes": [
      { "id": "clx...", "label": "Yes", "labelHe": "כן", "tokenIndex": 0 },
      { "id": "clx...", "label": "No", "labelHe": "לא", "tokenIndex": 1 }
    ],
    ...
  }
}
Slug must be unique. Returns 409 on duplicate. Outcomes get auto-assigned tokenIndex.
Example
curl -X POST https://api-production-2dab.up.railway.app/markets \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "slug": "will-btc-hit-100k",
    "question": "Will BTC hit $100K?",
    "category": "CRYPTO",
    "type": "BINARY",
    "template": "BINARY",
    "resolutionTime": "2026-06-01T00:00:00Z",
    "outcomes": [{"label":"Yes"},{"label":"No"}]
  }'
PUT/markets/:id/resolveAUTH

Resolve a market (ADMIN only). Pays out winners automatically.

Request Body
{
  "winningOutcomeId": "clx..."
}
Response
{
  "market": {
    "id": "clx...",
    "slug": "will-btc-hit-100k",
    "status": "RESOLVED",
    "resolvedAt": "2026-03-31T...",
    "resolvedOutcomeId": "clx..."
  }
}
All positions on the winning outcome pay out at $1/share. Losers get $0. Market status changes to RESOLVED. Broadcasts Socket.IO event.
PUT/markets/:id/approveAUTH

Approve a DRAFT market, making it OPEN and tradeable (ADMIN only)

Response
{
  "market": {
    "id": "clx...",
    "slug": "will-btc-hit-100k",
    "status": "OPEN",
    "question": "Will BTC hit $100K?",
    "questionHe": "..."
  }
}
Only DRAFT markets can be approved. Use this to review agent-created markets before making them live.
Example
curl -X PUT https://api-production-2dab.up.railway.app/markets/MARKET_ID/approve \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"
DELETE/markets/:idAUTH

Delete/reject a DRAFT market (ADMIN only)

Response
{ "deleted": true }
Only DRAFT markets can be deleted. Open markets must be resolved or cancelled instead.

Events

(אירועים)4 endpoints
GET/events

List events with filtering

Query Parameters
category    string   optional
subcategory string   optional
status      string   optional   UPCOMING|LIVE|ENDED|CANCELLED
featured    boolean  optional
page        number   optional   default: 1
limit       number   optional   default: 20, max: 100
Response
{
  "events": [{
    "id": "clx...",
    "slug": "maccabi-vs-hapoel",
    "title": "Maccabi vs Hapoel",
    "titleHe": "מכבי נגד הפועל",
    "category": "SPORTS",
    "participants": [
      { "name": "Maccabi", "nameHe": "מכבי", "iconUrl": "..." }
    ],
    "startTime": "2026-04-01T20:00:00Z",
    "status": "UPCOMING",
    "featured": true,
    "markets": [...],
    "marketCount": 3
  }],
  "pagination": { ... }
}
GET/events/:slug

Get a single event with all its markets

Response
{ "event": { ... } }
POST/eventsAUTH

Create a new event (CREATOR or ADMIN)

Request Body
{
  "slug": "maccabi-vs-hapoel-2026",
  "title": "Maccabi vs Hapoel",
  "titleHe": "מכבי נגד הפועל",
  "category": "SPORTS",
  "participants": [
    { "name": "Maccabi", "nameHe": "מכבי", "iconUrl": "https://..." },
    { "name": "Hapoel", "nameHe": "הפועל" }
  ],
  "startTime": "2026-04-01T20:00:00.000Z",
  "featured": true,
  "imageUrl": "https://...",
  "metadata": { "league": "Premier League" }
}
Response
{ "event": { "id": "clx...", ... } }
Slug must be unique. Participants have optional nameHe and iconUrl.
PUT/events/:id/statusAUTH

Update event status (ADMIN only)

Request Body
{
  "status": "LIVE"  // UPCOMING|LIVE|ENDED|CANCELLED
}
Response
{ "event": { ... } }
Broadcasts Socket.IO 'event:status' event.

Orders

(פקודות)3 endpoints
POST/ordersAUTH

Submit a buy or sell order. AMM auto-fills BUY orders when no counterparty exists.

Request Body
{
  "marketId": "clx...",
  "outcomeId": "clx...",
  "side": "BUY",          // BUY or SELL
  "type": "LIMIT",        // LIMIT or MARKET
  "price": 65,            // 1-99 (cents)
  "size": 10              // number of shares
}
Response
{
  "orderId": "clx...",
  "trades": [{
    "id": "t_...",
    "makerOrderId": "clx...",
    "takerOrderId": "clx...",
    "price": 65,
    "size": 10,
    "timestamp": 1234567890
  }],
  "filled": 10,
  "remaining": 0,
  "status": "FILLED"
}
BUY: deducts price*size/100 from balance upfront. SELL: must hold enough shares. BUY orders always fill via AMM if no counterparty. MARKET SELL orders with no buyer are CANCELLED.
Example
curl -X POST https://api-production-2dab.up.railway.app/orders \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{"marketId":"clx...","outcomeId":"clx...","side":"BUY","type":"LIMIT","price":65,"size":10}'
DELETE/orders/:idAUTH

Cancel an open or partially filled order

Response
{
  "orderId": "clx...",
  "status": "CANCELLED",
  "cancelledFromEngine": true
}
Refunds reserved balance for BUY orders. Can only cancel your own orders (unless ADMIN).
GET/ordersAUTH

List your orders

Query Parameters
marketId  string  optional
status    string  optional   OPEN|PARTIALLY_FILLED|FILLED|CANCELLED
page      number  optional   default: 1
limit     number  optional   default: 50, max: 100
Response
{
  "orders": [{
    "id": "clx...",
    "marketId": "clx...",
    "marketSlug": "will-btc-hit-100k",
    "outcomeId": "clx...",
    "outcomeLabel": "Yes",
    "side": "BUY",
    "type": "LIMIT",
    "price": 0.65,
    "priceCents": 65,
    "size": 10,
    "filled": 10,
    "remaining": 0,
    "status": "FILLED",
    "createdAt": "2026-03-31T..."
  }],
  "pagination": { ... }
}
Default filter: OPEN and PARTIALLY_FILLED orders only.

Trades

(עסקאות)2 endpoints
GET/trades

List trades for a market

Query Parameters
marketId   string  required
outcomeId  string  optional
page       number  optional   default: 1
limit      number  optional   default: 50, max: 100
Response
{
  "trades": [{
    "id": "clx...",
    "marketId": "clx...",
    "outcomeId": "clx...",
    "price": 0.65,
    "size": 10,
    "total": 6.50,
    "makerUsername": "alice",
    "takerUsername": "bob",
    "createdAt": "2026-03-31T..."
  }],
  "pagination": { ... }
}
GET/trades/activity

Get human-readable activity feed for a market

Query Parameters
marketId  string  required
limit     number  optional   default: 20, max: 50
Response
{
  "activity": [{
    "userId": "clx...",
    "username": "trader1",
    "avatarUrl": null,
    "action": "bought",
    "amount": 10,
    "side": "BUY",
    "outcomeLabel": "Yes",
    "outcomeLabelHe": "כן",
    "price": 0.65,
    "total": 6.50,
    "text": "trader1 bought 10 Yes @ 65¢",
    "timestamp": "2026-03-31T..."
  }]
}

Positions

(פוזיציות)4 endpoints
GET/positionsAUTH

Get your portfolio positions with PnL

Query Parameters
page   number  optional   default: 1
limit  number  optional   default: 50, max: 100
Response
{
  "positions": [{
    "id": "clx...",
    "marketId": "clx...",
    "outcomeId": "clx...",
    "shares": 10,
    "avgPrice": 0.65,
    "avgPriceCents": 65,
    "currentPrice": 0.72,
    "currentPriceCents": 72,
    "pnl": 0.70,
    "pnlPercent": 10.77,
    "value": 7.20,
    "marketSlug": "will-btc-hit-100k",
    "marketQuestion": "Will BTC hit $100K?",
    "marketStatus": "OPEN",
    "outcomeLabel": "Yes"
  }],
  "pagination": { ... }
}
GET/positions/:marketIdAUTH

Get your positions in a specific market

Response
{ "positions": [{ ... }] }
GET/positions/:marketId/holders

Public: see who holds positions in a market

Query Parameters
page   number  optional   default: 1
limit  number  optional   default: 20, max: 100
Response
{
  "holders": [{
    "userId": "clx...",
    "username": "trader1",
    "displayName": null,
    "avatarUrl": null,
    "totalShares": 25,
    "outcomes": [{
      "outcomeId": "clx...",
      "label": "Yes",
      "tokenIndex": 0,
      "shares": 25
    }]
  }],
  "pagination": { ... }
}
GET/positions/:marketId/leaderboard

Leaderboard: top traders by PnL in a market

Query Parameters
limit  number  optional   default: 20, max: 100
Response
{
  "leaderboard": [{
    "userId": "clx...",
    "username": "trader1",
    "totalPnl": 125.50,
    "totalValue": 450.00,
    "positionCount": 3
  }]
}

Comments

(תגובות)4 endpoints
GET/comments

List comments for a market (includes replies and position badges)

Query Parameters
marketId  string  required
sort      string  optional   newest|oldest|likes (default: newest)
page      number  optional   default: 1
limit     number  optional   default: 50, max: 100
Response
{
  "comments": [{
    "id": "clx...",
    "content": "Great market!",
    "imageUrl": null,
    "likes": 5,
    "createdAt": "2026-03-31T...",
    "replyCount": 2,
    "user": {
      "id": "clx...",
      "username": "trader1",
      "displayName": null,
      "avatarUrl": null,
      "position": { "label": "Yes", "labelHe": "כן", "shares": 10 }
    },
    "replies": [{ ... }]
  }],
  "pagination": { ... }
}
User's position in the market is included as a badge (null if no position). Top 5 replies included inline.
POST/commentsAUTH

Post a comment or reply

Request Body
{
  "marketId": "clx...",
  "content": "I think Yes is undervalued",  // 1-2000 chars
  "imageUrl": "https://...",                  // optional
  "parentId": "clx..."                        // optional (for replies)
}
Response
{ "comment": { ... } }
parentId must reference an existing comment in the same market.
POST/comments/:id/likeAUTH

Toggle like on a comment

Response
{ "likes": 6 }
Toggles: like if not liked, unlike if already liked.
DELETE/comments/:idAUTH

Delete your own comment (or any if ADMIN)

Response
{ "deleted": true }

Users

(משתמשים)3 endpoints
GET/users/:username

Get public user profile with stats

Response
{
  "user": {
    "id": "clx...",
    "username": "trader1",
    "displayName": null,
    "avatarUrl": null,
    "createdAt": "2026-03-31T...",
    "stats": {
      "positionsValue": 450.00,
      "biggestWin": 125.50,
      "predictions": 12,
      "totalPnl": 87.30,
      "activePositions": 5
    }
  }
}
Example
curl "https://api-production-2dab.up.railway.app/users/trader1"
GET/users/:username/positions

Get user's public positions

Query Parameters
status  string  optional   active|closed|all (default: active)
page    number  optional   default: 1
limit   number  optional   default: 50, max: 100
Response
{ "positions": [{ ... }], "pagination": { ... } }
GET/users/:username/activity

Get user's public trade activity

Query Parameters
filter  string  optional   all|trades|buy|sell (default: all)
page    number  optional   default: 1
limit   number  optional   default: 50, max: 100
Response
{
  "activity": [{
    "id": "clx...",
    "activity": "bought 10 shares",
    "market": { "slug": "...", "question": "...", "questionHe": "..." },
    "outcome": { "label": "Yes", "labelHe": "כן", "tokenIndex": 0 },
    "side": "BUY",
    "priceCents": 65,
    "shares": 10,
    "total": 6.50,
    "createdAt": "2026-03-31T..."
  }],
  "pagination": { ... }
}

Health

(בריאות)1 endpoints
GET/health

Health check endpoint

Response
{
  "status": "ok",
  "timestamp": "2026-03-31T00:00:00.000Z",
  "env": "production"
}
Example
curl "https://api-production-2dab.up.railway.app/health"

Socket.IO Events

Connect via Socket.IO for real-time updates. Events are emitted to specific rooms.

Connection
import { io } from "socket.io-client";
const socket = io("https://api-production-2dab.up.railway.app");

// Join rooms
socket.emit("join", "orderbook:MARKET_ID:OUTCOME_ID");
socket.emit("join", "trades:MARKET_ID");
book:update
Room: orderbook:{marketId}:{outcomeId}
Order book changed (new order, fill, cancel)
trade:new
Room: trades:{marketId}
New trade executed
market:resolved
Room: global
Market resolved with winning outcome
event:status
Room: global
Event status changed
PukiMarket API v1