Admin (God Mode) API
Complete REST API reference for the Predictu internal administration dashboard - codename God Mode. These endpoints power the predictu-admin.vercel.app dashboard used by the Predictu ops team to onboard operators, monitor global risk, track revenue across every casino, and manage platform-wide settings.
/api/internal/* requires a valid Predictu admin session token passed via the Authorization: Bearer <token> header. Tokens are issued by the /api/auth/admin/login flow and carry the role: "predictu_admin" claim. Requests without a valid admin token receive a 401 Unauthorized response.Authentication
All requests must include the admin JWT in the Authorization header. The token is validated against the Supabase admin_users table and must have the predictu_admin role. Tokens expire after 8 hours. A 403 Forbidden is returned if the token is valid but the user's admin role has been revoked.
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...Standard Error Format
All error responses follow a consistent JSON envelope:
{
"error": {
"code": "UNAUTHORIZED",
"message": "Admin authentication required",
"details": null
}
}| HTTP Status | Code | Meaning |
|---|---|---|
400 | BAD_REQUEST | Invalid parameters or request body |
401 | UNAUTHORIZED | Missing or expired admin token |
403 | FORBIDDEN | Valid token but insufficient permissions |
404 | NOT_FOUND | Resource does not exist |
409 | CONFLICT | Duplicate resource (e.g. operator slug) |
422 | VALIDATION_ERROR | Schema validation failed |
429 | RATE_LIMITED | Too many requests (60 req/min per admin) |
500 | INTERNAL_ERROR | Unexpected server failure |
Dashboard Overview
Returns the global platform summary displayed on the God Mode home screen. Aggregates data across all operators, including total revenue, active user counts, trade volume, exposure, and trend deltas compared to the previous period.
Get Dashboard
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
period | string | "7d" | Time window for trend deltas. One of 1d, 7d, 30d, 90d, all. |
operator | string | null | Optional operator slug to scope the dashboard to a single operator. |
Response - 200 OK
{
"data": {
"operators": {
"total": 12,
"active": 9,
"pending_onboarding": 2
},
"users": {
"total": 48230,
"active_24h": 3841,
"active_7d": 12093,
"new_7d": 1847,
"delta_pct": 12.4
},
"trades": {
"total": 892310,
"volume_usd": 14832000.50,
"count_24h": 18420,
"volume_24h_usd": 312800.75,
"delta_pct": 8.2
},
"revenue": {
"total_usd": 743200.00,
"period_usd": 48920.00,
"delta_pct": 15.7,
"breakdown": {
"spread": 38200.00,
"fees": 10720.00
}
},
"exposure": {
"current_usd": 284000.00,
"max_usd": 500000.00,
"utilization_pct": 56.8
},
"risk": {
"circuit_breakers_active": 0,
"high_exposure_markets": 3,
"sharp_bettors_flagged": 14
},
"settlements": {
"pending_count": 47,
"pending_usd": 18400.00,
"last_settled_at": "2026-03-19T08:12:00Z"
},
"chart_data": [
{ "date": "2026-03-12", "revenue_usd": 6800.00, "trades": 2400, "users": 1820 },
{ "date": "2026-03-13", "revenue_usd": 7120.00, "trades": 2580, "users": 1940 }
]
}
}Operators
Manage casino operators integrated with the Predictu platform. Each operator has a unique slug, branding configuration, S2S callback URL, embed origins, and associated users. Operators progress through onboarding stages: pending → configuring → testing → live.
List Operators
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
status | string | null | Filter by status: pending, configuring, testing, live, suspended. |
search | string | null | Full-text search across operator name and slug. |
sort | string | "created_at" | Sort field. One of created_at, name, revenue, users. |
order | string | "desc" | Sort order: asc or desc. |
Response - 200 OK
{
"data": [
{
"id": "op_abc123",
"slug": "example-casino",
"name": "Example Casino",
"status": "live",
"logo_url": "https://cdn.predictu.com/operators/example-casino/logo.png",
"primary_color": "#00ff88",
"s2s_enabled": true,
"callback_url": "https://api.example-casino.com/predictu/callback",
"embed_origins": ["https://example-casino.com", "https://www.example-casino.com"],
"user_count": 8420,
"trade_count": 214800,
"revenue_total_usd": 128400.00,
"revenue_30d_usd": 18200.00,
"created_at": "2025-11-15T10:00:00Z",
"onboarded_at": "2025-11-22T14:30:00Z"
}
],
"total": 12
}Create Operator
Registers a new casino operator on the platform. The operator starts in pending status and must complete the onboarding flow before going live. An API key pair is generated automatically and returned in the response.
Request Body
{
"name": "Lucky Spins Casino",
"slug": "lucky-spins",
"contact_email": "integrations@luckyspins.com",
"contact_name": "Alex Morgan",
"website_url": "https://luckyspins.com",
"callback_url": "https://api.luckyspins.com/predictu/callback",
"s2s_enabled": true,
"branding": {
"primary_color": "#ff6b00",
"secondary_color": "#1a1a2e",
"logo_url": null,
"favicon_url": null,
"display_name": "Lucky Spins Predictions"
},
"embed_origins": ["https://luckyspins.com"],
"config": {
"max_bet_usd": 500,
"min_bet_usd": 1,
"default_currency": "USD",
"allowed_categories": ["sports", "politics", "entertainment"],
"risk_tier": "standard"
}
}Response - 201 Created
{
"data": {
"id": "op_xyz789",
"slug": "lucky-spins",
"name": "Lucky Spins Casino",
"status": "pending",
"api_key": "pk_live_abc123...",
"api_secret": "sk_live_xyz789...",
"created_at": "2026-03-19T12:00:00Z"
}
}api_secret is only returned at creation time. Store it securely. If lost, a new key pair must be generated via the operator settings.Get Operator Detail
Returns the full operator profile including branding, config, S2S status, and aggregated metrics.
Path Parameters
| Param | Type | Description |
|---|---|---|
slug | string | Operator's unique URL slug (e.g. example-casino). |
Response - 200 OK
{
"data": {
"id": "op_abc123",
"slug": "example-casino",
"name": "Example Casino",
"status": "live",
"contact_email": "tech@example-casino.com",
"contact_name": "Jordan Lee",
"website_url": "https://example-casino.com",
"callback_url": "https://api.example-casino.com/predictu/callback",
"s2s_enabled": true,
"s2s_healthy": true,
"s2s_last_ping": "2026-03-19T11:58:00Z",
"branding": {
"primary_color": "#00ff88",
"secondary_color": "#0a1a0a",
"logo_url": "https://cdn.predictu.com/operators/example-casino/logo.png",
"favicon_url": "https://cdn.predictu.com/operators/example-casino/favicon.png",
"display_name": "Example Casino Predictions"
},
"embed_origins": ["https://example-casino.com", "https://www.example-casino.com"],
"config": {
"max_bet_usd": 1000,
"min_bet_usd": 1,
"default_currency": "USD",
"allowed_categories": ["sports", "politics", "entertainment", "crypto"],
"risk_tier": "premium",
"spread_override": null,
"custom_fees_bps": 150
},
"metrics": {
"user_count": 8420,
"active_users_24h": 642,
"trade_count": 214800,
"trade_volume_usd": 4280000.00,
"revenue_total_usd": 128400.00,
"revenue_30d_usd": 18200.00,
"avg_trade_usd": 19.93,
"exposure_usd": 42000.00
},
"onboarding": {
"stage": "complete",
"completed_steps": ["branding", "s2s_config", "embed_setup", "test_trades", "go_live"],
"onboarded_at": "2025-11-22T14:30:00Z"
},
"created_at": "2025-11-15T10:00:00Z",
"updated_at": "2026-03-18T09:00:00Z"
}
}Operator Revenue
Returns time-series revenue data for a specific operator, broken down by source (spread, fees, settlements).
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
from | string | 30 days ago | ISO 8601 start date. |
to | string | now | ISO 8601 end date. |
granularity | string | "day" | One of hour, day, week, month. |
Response - 200 OK
{
"data": {
"operator_slug": "example-casino",
"period": { "from": "2026-02-17T00:00:00Z", "to": "2026-03-19T23:59:59Z" },
"totals": {
"revenue_usd": 18200.00,
"spread_revenue_usd": 14200.00,
"fee_revenue_usd": 4000.00,
"predictu_share_usd": 5460.00,
"operator_share_usd": 12740.00
},
"series": [
{
"date": "2026-03-18",
"revenue_usd": 620.00,
"spread_usd": 480.00,
"fees_usd": 140.00,
"trade_count": 890,
"volume_usd": 17800.00
}
]
}
}Operator Trades
Returns paginated trade history for an operator. Supports filtering by market, user, side, and date range.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number (1-indexed). |
limit | number | 50 | Results per page. Max 200. |
user_id | string | null | Filter by user ID. |
market_id | string | null | Filter by market ID. |
side | string | null | Filter by side: buy or sell. |
outcome | string | null | Filter by outcome: yes or no. |
from | string | null | ISO 8601 start date. |
to | string | null | ISO 8601 end date. |
sort | string | "created_at" | Sort field: created_at, amount, price. |
order | string | "desc" | Sort order: asc or desc. |
Response - 200 OK
{
"data": [
{
"id": "trd_abc123",
"user_id": "usr_xyz",
"user_name": "player_42",
"operator_slug": "example-casino",
"market_id": "mkt_001",
"market_title": "Will BTC exceed $150k by April 2026?",
"outcome": "yes",
"side": "buy",
"price": 0.62,
"quantity": 50.00,
"cost_usd": 31.00,
"fee_usd": 0.47,
"spread_usd": 0.93,
"pnl_usd": null,
"status": "open",
"created_at": "2026-03-19T10:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 214800,
"total_pages": 4296
}
}Operator Users
Returns paginated list of users registered under a specific operator, with account metrics.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number. |
limit | number | 50 | Results per page. Max 200. |
search | string | null | Search by username, email, or external ID. |
tier | string | null | Filter by risk tier: normal, sharp, restricted, banned. |
status | string | null | Filter by status: active, inactive, suspended. |
sort | string | "created_at" | Sort: created_at, last_active, trade_count, balance, pnl. |
order | string | "desc" | Sort order. |
Response - 200 OK
{
"data": [
{
"id": "usr_xyz",
"external_id": "gbn_player_42",
"username": "player_42",
"email": "player42@email.com",
"operator_slug": "example-casino",
"tier": "normal",
"status": "active",
"balance_usd": 142.50,
"trade_count": 84,
"volume_usd": 2480.00,
"pnl_usd": 38.20,
"win_rate": 0.54,
"score": 42,
"last_active_at": "2026-03-19T10:15:00Z",
"created_at": "2026-01-08T18:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 8420,
"total_pages": 169
}
}Operator Exposure
Returns the current risk exposure for a specific operator, broken down by market and category. Exposure represents the maximum potential payout if all open positions resolve in the worst-case direction.
Response - 200 OK
{
"data": {
"operator_slug": "example-casino",
"total_exposure_usd": 42000.00,
"exposure_limit_usd": 100000.00,
"utilization_pct": 42.0,
"by_category": [
{ "category": "sports", "exposure_usd": 22000.00, "limit_usd": 50000.00, "utilization_pct": 44.0 },
{ "category": "politics", "exposure_usd": 12000.00, "limit_usd": 30000.00, "utilization_pct": 40.0 },
{ "category": "crypto", "exposure_usd": 8000.00, "limit_usd": 20000.00, "utilization_pct": 40.0 }
],
"by_market": [
{
"market_id": "mkt_001",
"title": "Will BTC exceed $150k by April 2026?",
"exposure_usd": 8400.00,
"yes_exposure_usd": 5200.00,
"no_exposure_usd": 3200.00,
"position_count": 142,
"volume_usd": 28400.00
}
],
"top_users": [
{ "user_id": "usr_abc", "username": "highroller_99", "exposure_usd": 4800.00, "tier": "sharp" }
]
}
}Operator Invoices
Returns the billing history for an operator. Invoices are generated monthly and represent Predictu's revenue share from the operator's net player losses.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
status | string | null | Filter: draft, sent, paid, overdue. |
from | string | null | ISO 8601 start date. |
to | string | null | ISO 8601 end date. |
Response - 200 OK
{
"data": [
{
"id": "inv_001",
"operator_slug": "example-casino",
"period": { "from": "2026-02-01", "to": "2026-02-28" },
"status": "paid",
"amount_usd": 5460.00,
"trade_volume_usd": 182000.00,
"trade_count": 8420,
"spread_revenue_usd": 4200.00,
"fee_revenue_usd": 1260.00,
"revenue_share_pct": 30,
"issued_at": "2026-03-01T00:00:00Z",
"paid_at": "2026-03-05T14:20:00Z",
"pdf_url": "/api/internal/invoices/inv_001/pdf"
}
],
"total": 4
}Users
Global user management across all operators. Supports full-text search, risk tier filtering, operator filtering, and detailed user drill-down with ledger history, positions, trades, and scoring data.
List Users
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number (1-indexed). |
limit | number | 50 | Results per page. Max 200. |
search | string | null | Search by username, email, external ID, or user ID. |
operator | string | null | Filter by operator slug. |
tier | string | null | Filter by risk tier: normal, sharp, restricted, banned. |
status | string | null | Filter by account status: active, inactive, suspended. |
min_balance | number | null | Minimum balance in USD. |
max_balance | number | null | Maximum balance in USD. |
sort | string | "created_at" | Sort: created_at, last_active, balance, trade_count, pnl, score. |
order | string | "desc" | Sort order. |
Response - 200 OK
{
"data": [
{
"id": "usr_xyz",
"external_id": "gbn_player_42",
"username": "player_42",
"email": "player42@email.com",
"operator_slug": "example-casino",
"operator_name": "Example Casino",
"tier": "normal",
"status": "active",
"balance_usd": 142.50,
"trade_count": 84,
"volume_usd": 2480.00,
"pnl_usd": 38.20,
"win_rate": 0.54,
"score": 42,
"open_positions": 5,
"last_active_at": "2026-03-19T10:15:00Z",
"created_at": "2026-01-08T18:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 48230,
"total_pages": 965
}
}Get User Detail
Returns the full user profile with account metrics, scoring breakdown, and risk tier assessment.
Path Parameters
| Param | Type | Description |
|---|---|---|
id | string | User ID (e.g. usr_xyz). |
Response - 200 OK
{
"data": {
"id": "usr_xyz",
"external_id": "gbn_player_42",
"username": "player_42",
"email": "player42@email.com",
"operator_slug": "example-casino",
"operator_name": "Example Casino",
"tier": "normal",
"status": "active",
"balance_usd": 142.50,
"metrics": {
"trade_count": 84,
"volume_usd": 2480.00,
"pnl_usd": 38.20,
"win_rate": 0.54,
"avg_trade_usd": 29.52,
"largest_trade_usd": 200.00,
"open_positions": 5,
"total_deposited_usd": 500.00,
"total_withdrawn_usd": 300.00,
"exposure_usd": 280.00
},
"scoring": {
"score": 42,
"tier": "normal",
"components": {
"win_rate_score": 12,
"edge_detection_score": 8,
"timing_score": 6,
"volume_pattern_score": 10,
"correlation_score": 6
},
"flags": [],
"last_evaluated_at": "2026-03-19T08:00:00Z"
},
"restrictions": {
"max_bet_usd": 1000,
"allowed_categories": null,
"blocked_markets": [],
"cooldown_until": null
},
"last_active_at": "2026-03-19T10:15:00Z",
"created_at": "2026-01-08T18:30:00Z",
"updated_at": "2026-03-19T10:15:00Z"
}
}User Ledger
Returns the immutable financial ledger for a user. Every balance-affecting action is recorded here: deposits, withdrawals, trade debits, trade credits, settlement payouts, fee deductions, and admin adjustments. This is the audit trail for any balance dispute.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number. |
limit | number | 50 | Results per page. Max 200. |
type | string | null | Filter: deposit, withdraw, trade_debit, trade_credit, settlement, fee, adjustment. |
from | string | null | ISO 8601 start date. |
to | string | null | ISO 8601 end date. |
Response - 200 OK
{
"data": [
{
"id": "ldg_001",
"user_id": "usr_xyz",
"type": "trade_debit",
"amount_usd": -31.00,
"balance_before_usd": 173.50,
"balance_after_usd": 142.50,
"reference_type": "trade",
"reference_id": "trd_abc123",
"description": "Buy 50 YES @ $0.62 - Will BTC exceed $150k by April 2026?",
"metadata": {
"market_id": "mkt_001",
"outcome": "yes",
"side": "buy",
"price": 0.62,
"quantity": 50.00
},
"idempotency_key": "idk_trd_abc123",
"created_at": "2026-03-19T10:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 412,
"total_pages": 9
}
}User Positions
Returns all positions (open and closed) for a user across all markets.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
status | string | null | Filter: open, closed, settled. |
page | number | 1 | Page number. |
limit | number | 50 | Results per page. |
Response - 200 OK
{
"data": [
{
"id": "pos_001",
"user_id": "usr_xyz",
"market_id": "mkt_001",
"market_title": "Will BTC exceed $150k by April 2026?",
"outcome": "yes",
"quantity": 50.00,
"avg_price": 0.62,
"cost_basis_usd": 31.00,
"current_price": 0.68,
"market_value_usd": 34.00,
"unrealized_pnl_usd": 3.00,
"realized_pnl_usd": 0.00,
"status": "open",
"opened_at": "2026-03-19T10:30:00Z",
"closed_at": null,
"settled_at": null
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 5,
"total_pages": 1
}
}User Trades
Returns all trades executed by a specific user. Same schema as the global trades endpoint, scoped to one user.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number. |
limit | number | 50 | Results per page. |
market_id | string | null | Filter by market. |
side | string | null | Filter: buy or sell. |
from | string | null | ISO 8601 start date. |
to | string | null | ISO 8601 end date. |
Response - 200 OK
{
"data": [
{
"id": "trd_abc123",
"user_id": "usr_xyz",
"market_id": "mkt_001",
"market_title": "Will BTC exceed $150k by April 2026?",
"outcome": "yes",
"side": "buy",
"price": 0.62,
"quantity": 50.00,
"cost_usd": 31.00,
"fee_usd": 0.47,
"spread_usd": 0.93,
"status": "filled",
"created_at": "2026-03-19T10:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 84,
"total_pages": 2
}
}User Score
Returns the detailed scoring breakdown for a user. The scoring system detects sharp bettors using five components: win rate analysis, edge detection (beating closing line), timing patterns, volume patterns, and cross-market correlation. Scores range from 0 (recreational) to 100 (sharp).
Response - 200 OK
{
"data": {
"user_id": "usr_xyz",
"score": 42,
"tier": "normal",
"tier_thresholds": {
"normal": { "min": 0, "max": 59 },
"sharp": { "min": 60, "max": 79 },
"restricted": { "min": 80, "max": 100 }
},
"components": {
"win_rate": {
"score": 12,
"max": 25,
"value": 0.54,
"detail": "Win rate 54% - slightly above baseline (50%)"
},
"edge_detection": {
"score": 8,
"max": 25,
"value": 0.02,
"detail": "Avg CLV edge +2% - minimal"
},
"timing": {
"score": 6,
"max": 20,
"value": 0.15,
"detail": "15% of bets placed within 5min of line movement"
},
"volume_pattern": {
"score": 10,
"max": 15,
"value": 0.8,
"detail": "Consistent sizing, no spike patterns"
},
"correlation": {
"score": 6,
"max": 15,
"value": 0.12,
"detail": "Low cross-market correlation (0.12)"
}
},
"history": [
{ "date": "2026-03-12", "score": 40 },
{ "date": "2026-03-05", "score": 38 },
{ "date": "2026-02-26", "score": 35 }
],
"flags": [],
"recommendations": [],
"last_evaluated_at": "2026-03-19T08:00:00Z"
}
}Trades
Global trade management across all operators. Each trade record represents an atomic execution: a buy or sell of an outcome share at a specific price. Trades are immutable once created.
List Trades
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number. |
limit | number | 50 | Results per page. Max 200. |
operator | string | null | Filter by operator slug. |
user_id | string | null | Filter by user ID. |
market_id | string | null | Filter by market ID. |
side | string | null | Filter: buy or sell. |
outcome | string | null | Filter: yes or no. |
status | string | null | Filter: filled, settled, cancelled. |
min_amount | number | null | Minimum trade amount in USD. |
max_amount | number | null | Maximum trade amount in USD. |
from | string | null | ISO 8601 start date. |
to | string | null | ISO 8601 end date. |
sort | string | "created_at" | Sort: created_at, amount, price. |
order | string | "desc" | Sort order. |
Response - 200 OK
{
"data": [
{
"id": "trd_abc123",
"user_id": "usr_xyz",
"user_name": "player_42",
"operator_slug": "example-casino",
"operator_name": "Example Casino",
"market_id": "mkt_001",
"market_title": "Will BTC exceed $150k by April 2026?",
"category": "crypto",
"outcome": "yes",
"side": "buy",
"price": 0.62,
"quantity": 50.00,
"cost_usd": 31.00,
"fee_usd": 0.47,
"spread_usd": 0.93,
"pnl_usd": null,
"status": "filled",
"s2s_transaction_id": "txn_gbn_abc123",
"idempotency_key": "idk_trd_abc123",
"created_at": "2026-03-19T10:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 892310,
"total_pages": 17847
}
}Markets
Browse and inspect all prediction markets on the platform. Markets are sourced from Polymarket and mapped through the Predictu tradeability filter. Includes pricing data, volume, and resolution status.
List Markets
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number. |
limit | number | 50 | Results per page. Max 200. |
search | string | null | Full-text search on market title and description. |
category | string | null | Filter: sports, politics, entertainment, crypto, science, business. |
status | string | null | Filter: active, paused, resolved, cancelled. |
tradeable | boolean | null | Filter by tradeability flag (passed Predictu selection criteria). |
sort | string | "volume" | Sort: volume, created_at, end_date, exposure, trade_count. |
order | string | "desc" | Sort order. |
Response - 200 OK
{
"data": [
{
"id": "mkt_001",
"polymarket_id": "pm_condition_abc",
"title": "Will BTC exceed $150k by April 2026?",
"description": "Resolves YES if Bitcoin trades above $150,000...",
"category": "crypto",
"status": "active",
"tradeable": true,
"image_url": "https://cdn.predictu.com/markets/mkt_001.png",
"yes_price": 0.62,
"no_price": 0.38,
"spread": 0.04,
"volume_usd": 482000.00,
"trade_count": 12400,
"position_count": 3200,
"exposure_usd": 28400.00,
"liquidity_score": 0.89,
"end_date": "2026-04-30T23:59:59Z",
"resolution": null,
"resolved_at": null,
"created_at": "2026-01-15T00:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 842,
"total_pages": 17
}
}Get Market Detail
Returns full market detail including pricing history, operator-level breakdown, and risk metrics.
Response - 200 OK
{
"data": {
"id": "mkt_001",
"polymarket_id": "pm_condition_abc",
"title": "Will BTC exceed $150k by April 2026?",
"description": "Resolves YES if Bitcoin price exceeds $150,000 USD on any major exchange before April 30, 2026 23:59 UTC.",
"category": "crypto",
"tags": ["bitcoin", "price", "crypto"],
"status": "active",
"tradeable": true,
"image_url": "https://cdn.predictu.com/markets/mkt_001.png",
"pricing": {
"yes_price": 0.62,
"no_price": 0.38,
"spread": 0.04,
"base_spread": 0.02,
"risk_adjusted_spread": 0.04,
"last_updated": "2026-03-19T11:58:00Z"
},
"volume": {
"total_usd": 482000.00,
"24h_usd": 12400.00,
"7d_usd": 68000.00,
"trade_count": 12400,
"unique_traders": 2840
},
"exposure": {
"total_usd": 28400.00,
"yes_usd": 18200.00,
"no_usd": 10200.00,
"imbalance_ratio": 1.78,
"position_count": 3200
},
"by_operator": [
{
"operator_slug": "example-casino",
"volume_usd": 148000.00,
"trade_count": 3800,
"exposure_usd": 8400.00,
"user_count": 920
}
],
"price_history": [
{ "timestamp": "2026-03-19T11:00:00Z", "yes_price": 0.61, "volume_usd": 480.00 },
{ "timestamp": "2026-03-19T12:00:00Z", "yes_price": 0.62, "volume_usd": 520.00 }
],
"resolution": null,
"resolution_source": null,
"resolved_at": null,
"end_date": "2026-04-30T23:59:59Z",
"created_at": "2026-01-15T00:00:00Z",
"updated_at": "2026-03-19T11:58:00Z"
}
}Global Exposure
Real-time view of platform-wide risk exposure. Exposure is the maximum potential payout if all open positions resolve in the worst-case direction. The 5-wall risk system enforces limits at per-trade, per-market, per-category, per-operator, and global levels.
Get Global Exposure
Response - 200 OK
{
"data": {
"total_exposure_usd": 284000.00,
"global_limit_usd": 500000.00,
"utilization_pct": 56.8,
"by_operator": [
{
"operator_slug": "example-casino",
"exposure_usd": 42000.00,
"limit_usd": 100000.00,
"utilization_pct": 42.0
}
],
"by_category": [
{ "category": "sports", "exposure_usd": 120000.00, "limit_usd": 200000.00, "utilization_pct": 60.0 },
{ "category": "crypto", "exposure_usd": 84000.00, "limit_usd": 150000.00, "utilization_pct": 56.0 },
{ "category": "politics", "exposure_usd": 52000.00, "limit_usd": 100000.00, "utilization_pct": 52.0 },
{ "category": "entertainment", "exposure_usd": 28000.00, "limit_usd": 50000.00, "utilization_pct": 56.0 }
],
"top_markets": [
{
"market_id": "mkt_001",
"title": "Will BTC exceed $150k by April 2026?",
"exposure_usd": 28400.00,
"limit_usd": 50000.00,
"position_count": 3200
}
],
"top_users": [
{
"user_id": "usr_high1",
"username": "whale_trader",
"operator_slug": "example-casino",
"exposure_usd": 12000.00,
"tier": "sharp"
}
],
"alerts": [
{
"level": "warning",
"message": "Category 'sports' approaching 60% utilization",
"category": "sports",
"created_at": "2026-03-19T11:00:00Z"
}
],
"snapshot_at": "2026-03-19T12:00:00Z"
}
}Risk Management
The risk engine provides real-time monitoring, circuit breaker management, risk event logging, and sharp bettor tracking. Circuit breakers can automatically halt trading on specific markets or globally when risk thresholds are exceeded.
Get Risk Overview
Response - 200 OK
{
"data": {
"status": "healthy",
"circuit_breakers": {
"global_active": false,
"market_breakers": 0,
"category_breakers": 0,
"operator_breakers": 0
},
"exposure_summary": {
"total_usd": 284000.00,
"limit_usd": 500000.00,
"utilization_pct": 56.8
},
"sharp_bettors": {
"flagged_count": 14,
"restricted_count": 3,
"banned_count": 1
},
"recent_events_count": 42,
"risk_score": 38,
"risk_level": "moderate",
"walls": {
"wall_1_per_trade": { "status": "green", "violations_24h": 12 },
"wall_2_per_market": { "status": "green", "violations_24h": 3 },
"wall_3_per_category": { "status": "yellow", "violations_24h": 1 },
"wall_4_per_operator": { "status": "green", "violations_24h": 0 },
"wall_5_global": { "status": "green", "violations_24h": 0 }
}
}
}Circuit Breakers
Returns all configured circuit breakers with their current state. Circuit breakers can be scoped to a specific market, category, operator, or applied globally. When tripped, all new trades in the affected scope are rejected until the breaker is manually reset or the cooldown expires.
Response - 200 OK
{
"data": [
{
"id": "cb_001",
"scope": "market",
"scope_id": "mkt_001",
"scope_label": "Will BTC exceed $150k by April 2026?",
"trigger_type": "exposure_pct",
"trigger_threshold": 90,
"current_value": 56.8,
"status": "armed",
"cooldown_minutes": 60,
"auto_reset": true,
"tripped_at": null,
"reset_at": null,
"created_by": "admin_001",
"created_at": "2026-02-01T10:00:00Z"
},
{
"id": "cb_002",
"scope": "global",
"scope_id": null,
"scope_label": "Global",
"trigger_type": "exposure_pct",
"trigger_threshold": 95,
"current_value": 56.8,
"status": "armed",
"cooldown_minutes": 120,
"auto_reset": false,
"tripped_at": null,
"reset_at": null,
"created_by": "admin_001",
"created_at": "2026-01-15T10:00:00Z"
}
],
"total": 8
}Risk Events
Returns a paginated log of risk events. Risk events are generated when wall limits are approached or breached, when circuit breakers trip, when sharp bettor thresholds change, and when unusual trading patterns are detected.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number. |
limit | number | 50 | Results per page. |
severity | string | null | Filter: info, warning, critical. |
type | string | null | Filter: wall_violation, circuit_breaker, sharp_detection, anomaly. |
from | string | null | ISO 8601 start date. |
to | string | null | ISO 8601 end date. |
Response - 200 OK
{
"data": [
{
"id": "evt_001",
"type": "wall_violation",
"severity": "warning",
"wall": 3,
"wall_name": "per_category",
"message": "Category 'sports' exposure hit 60% utilization (120k/200k USD)",
"scope": { "category": "sports" },
"value": 120000.00,
"threshold": 200000.00,
"utilization_pct": 60.0,
"operator_slug": null,
"user_id": null,
"market_id": null,
"auto_resolved": false,
"resolved_at": null,
"created_at": "2026-03-19T11:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 42,
"total_pages": 1
}
}Sharp Bettors
Returns all users whose scoring tier is sharp or above, with detailed scoring breakdown and betting patterns. Used for manual review and tier override decisions.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
tier | string | null | Filter: sharp, restricted, banned. |
operator | string | null | Filter by operator slug. |
sort | string | "score" | Sort: score, pnl, volume, win_rate. |
order | string | "desc" | Sort order. |
Response - 200 OK
{
"data": [
{
"user_id": "usr_sharp1",
"username": "edge_hunter",
"operator_slug": "example-casino",
"tier": "sharp",
"score": 72,
"win_rate": 0.64,
"pnl_usd": 4820.00,
"volume_usd": 38400.00,
"trade_count": 420,
"clv_edge": 0.08,
"timing_score": 16,
"restrictions": {
"max_bet_usd": 100,
"blocked_categories": ["sports"],
"cooldown_until": null
},
"last_evaluated_at": "2026-03-19T08:00:00Z"
}
],
"total": 14
}Settlements
When a market resolves, positions are settled: winning positions receive payouts, losing positions are closed at zero. The settlement engine processes all positions atomically per market and generates ledger entries and S2S callbacks for each affected user.
List Settlements
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number. |
limit | number | 50 | Results per page. |
status | string | null | Filter: pending, processing, completed, failed. |
market_id | string | null | Filter by market. |
operator | string | null | Filter by operator slug. |
Response - 200 OK
{
"data": [
{
"id": "stl_001",
"market_id": "mkt_042",
"market_title": "Will the Fed cut rates in March 2026?",
"resolution": "yes",
"status": "completed",
"positions_settled": 840,
"winners": 520,
"losers": 320,
"total_payout_usd": 14200.00,
"total_loss_usd": 9800.00,
"net_pnl_usd": -4400.00,
"s2s_callbacks_sent": 840,
"s2s_callbacks_confirmed": 838,
"s2s_callbacks_failed": 2,
"processing_time_ms": 3420,
"resolved_at": "2026-03-18T20:00:00Z",
"settled_at": "2026-03-18T20:00:03Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 284,
"total_pages": 6
}
}Pending Settlements
Returns markets that have resolved but whose positions have not yet been fully settled. This includes markets in processing state and those with failed S2S callbacks awaiting retry.
Response - 200 OK
{
"data": [
{
"market_id": "mkt_099",
"market_title": "Will ETH flip BTC in market cap by Q2 2026?",
"resolution": "no",
"resolved_at": "2026-03-19T08:00:00Z",
"status": "processing",
"positions_total": 420,
"positions_settled": 380,
"positions_remaining": 40,
"failed_callbacks": [
{
"user_id": "usr_fail1",
"operator_slug": "lucky-spins",
"error": "S2S callback timeout after 3 retries",
"last_attempt_at": "2026-03-19T08:05:00Z",
"retry_count": 3
}
]
}
],
"total": 2
}Invoices
Monthly billing invoices for operator revenue sharing. Invoices are auto-generated on the 1st of each month for the prior period. Each invoice itemizes player losses by source (spread, fees) and the Predictu revenue share percentage (% of player losses).
List Invoices
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number. |
limit | number | 50 | Results per page. |
operator | string | null | Filter by operator slug. |
status | string | null | Filter: draft, sent, paid, overdue. |
Response - 200 OK
{
"data": [
{
"id": "inv_001",
"operator_slug": "example-casino",
"operator_name": "Example Casino",
"period": { "from": "2026-02-01", "to": "2026-02-28" },
"status": "paid",
"amount_usd": 5460.00,
"line_items": [
{ "description": "Predictu share of spread player losses (30%)", "amount_usd": 4260.00 },
{ "description": "Predictu share of fee player losses (30%)", "amount_usd": 1200.00 }
],
"trade_volume_usd": 182000.00,
"trade_count": 8420,
"revenue_share_pct": 30,
"issued_at": "2026-03-01T00:00:00Z",
"due_at": "2026-03-15T00:00:00Z",
"paid_at": "2026-03-05T14:20:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 36,
"total_pages": 1
}
}Get Invoice Detail
Returns full invoice detail with line items and payment history.
Response - 200 OK
{
"data": {
"id": "inv_001",
"operator_slug": "example-casino",
"operator_name": "Example Casino",
"operator_contact_email": "billing@example-casino.com",
"period": { "from": "2026-02-01", "to": "2026-02-28" },
"status": "paid",
"amount_usd": 5460.00,
"line_items": [
{ "description": "Player losses from spread - 8,420 trades", "gross_usd": 14200.00, "share_pct": 30, "amount_usd": 4260.00 },
{ "description": "Player losses from fees - 8,420 trades", "gross_usd": 4000.00, "share_pct": 30, "amount_usd": 1200.00 }
],
"summary": {
"trade_volume_usd": 182000.00,
"trade_count": 8420,
"unique_traders": 2100,
"gross_revenue_usd": 18200.00,
"predictu_share_usd": 5460.00,
"operator_share_usd": 12740.00,
"revenue_share_pct": 30
},
"payment": {
"method": "wire",
"reference": "WIR-2026-0305-001",
"paid_at": "2026-03-05T14:20:00Z"
},
"issued_at": "2026-03-01T00:00:00Z",
"due_at": "2026-03-15T00:00:00Z",
"created_at": "2026-03-01T00:00:00Z"
}
}Download Invoice PDF
Returns the invoice as a PDF binary download. The response has Content-Type: application/pdf andContent-Disposition: attachment; filename="invoice-inv_001.pdf".
Response - 200 OK
Binary PDF file stream. No JSON body.
Revenue
Platform-wide revenue analytics. Revenue represents net player losses, which come from two sources: the spread (difference between displayed price and Polymarket mid-price) and explicit trading fees. Predictu takes an agreed percentage of player losses from each operator per their revenue_share_pct.
Get Revenue
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
from | string | 30 days ago | ISO 8601 start date. |
to | string | now | ISO 8601 end date. |
granularity | string | "day" | Aggregation: hour, day, week, month. |
operator | string | null | Filter by operator slug. |
Response - 200 OK
{
"data": {
"period": { "from": "2026-02-17T00:00:00Z", "to": "2026-03-19T23:59:59Z" },
"totals": {
"gross_revenue_usd": 148200.00,
"spread_revenue_usd": 112000.00,
"fee_revenue_usd": 36200.00,
"predictu_share_usd": 44460.00,
"operator_share_usd": 103740.00,
"trade_volume_usd": 4940000.00,
"trade_count": 98420,
"unique_traders": 12400,
"revenue_per_trade_usd": 1.51
},
"by_operator": [
{
"operator_slug": "example-casino",
"gross_usd": 48200.00,
"predictu_share_usd": 14460.00,
"trade_count": 32000
}
],
"series": [
{
"date": "2026-03-18",
"gross_usd": 4800.00,
"spread_usd": 3600.00,
"fees_usd": 1200.00,
"predictu_usd": 1440.00,
"trades": 3200,
"volume_usd": 160000.00
}
]
}
}Revenue Forecast
Returns projected revenue for the next 30/60/90 days based on historical trends, operator growth rates, and seasonal patterns. Used for financial planning and capacity forecasting.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
horizon | string | "30d" | Forecast horizon: 30d, 60d, 90d. |
Response - 200 OK
{
"data": {
"horizon": "30d",
"projected_revenue_usd": 162000.00,
"confidence_interval": {
"low_usd": 142000.00,
"high_usd": 184000.00,
"confidence_pct": 80
},
"growth_rate_pct": 9.3,
"drivers": [
{ "factor": "New operator (LuckySpins) onboarding", "impact_usd": 8000.00 },
{ "factor": "March Madness sports volume", "impact_usd": 12000.00 },
{ "factor": "Seasonal baseline", "impact_usd": 142000.00 }
],
"by_operator": [
{ "operator_slug": "example-casino", "projected_usd": 52000.00 },
{ "operator_slug": "lucky-spins", "projected_usd": 8000.00 }
],
"series": [
{ "date": "2026-03-20", "projected_usd": 5200.00 },
{ "date": "2026-03-21", "projected_usd": 5400.00 }
],
"generated_at": "2026-03-19T12:00:00Z"
}
}Activity Feed
Real-time feed of all significant platform events. Used on the God Mode dashboard to provide an at-a-glance view of what is happening across the platform.
Get Activity Feed
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
limit | number | 50 | Number of events to return. Max 200. |
type | string | null | Filter: trade, settlement, user_signup, risk_event, operator_event, config_change. |
operator | string | null | Filter by operator slug. |
cursor | string | null | Cursor for pagination (returned in previous response). |
Response - 200 OK
{
"data": [
{
"id": "act_001",
"type": "trade",
"title": "Large trade executed",
"description": "player_42 bought 200 YES @ $0.62 on 'Will BTC exceed $150k...' ($124.00)",
"operator_slug": "example-casino",
"user_id": "usr_xyz",
"market_id": "mkt_001",
"severity": "info",
"metadata": {
"trade_id": "trd_big1",
"amount_usd": 124.00,
"side": "buy",
"outcome": "yes"
},
"created_at": "2026-03-19T11:58:00Z"
},
{
"id": "act_002",
"type": "risk_event",
"title": "Circuit breaker armed",
"description": "Market 'ETH flip BTC' exposure approaching limit (85%)",
"severity": "warning",
"metadata": {
"market_id": "mkt_099",
"utilization_pct": 85
},
"created_at": "2026-03-19T11:55:00Z"
}
],
"next_cursor": "eyJpZCI6ImFjdF8wNTAifQ=="
}Analytics
Advanced analytics endpoints for cohort analysis, lifetime value calculations, and behavioral pattern detection. These power the God Mode analytics dashboard.
Cohort Analysis
Returns user retention and engagement cohorts grouped by signup week. Each cohort shows the percentage of users still active in subsequent weeks, average trades, and revenue per user.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
from | string | 12 weeks ago | ISO 8601 start date for cohort range. |
to | string | now | ISO 8601 end date. |
operator | string | null | Filter by operator slug. |
granularity | string | "week" | Cohort grouping: week or month. |
Response - 200 OK
{
"data": {
"cohorts": [
{
"cohort": "2026-W10",
"signup_count": 420,
"retention": {
"week_0": 1.0,
"week_1": 0.64,
"week_2": 0.48,
"week_3": 0.38,
"week_4": 0.32
},
"avg_trades_per_user": 8.4,
"avg_revenue_per_user_usd": 3.20,
"avg_volume_per_user_usd": 148.00
},
{
"cohort": "2026-W11",
"signup_count": 380,
"retention": {
"week_0": 1.0,
"week_1": 0.68,
"week_2": 0.52
},
"avg_trades_per_user": 9.1,
"avg_revenue_per_user_usd": 3.80,
"avg_volume_per_user_usd": 162.00
}
],
"summary": {
"avg_week_1_retention": 0.66,
"avg_week_4_retention": 0.32,
"best_cohort": "2026-W11",
"worst_cohort": "2026-W08"
}
}
}Lifetime Value
Returns estimated lifetime value (LTV) segmented by operator, acquisition channel, and user tier. LTV is calculated based on historical revenue per user over their active lifespan.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
segment | string | "operator" | Segmentation: operator, tier, category. |
operator | string | null | Filter by operator slug. |
Response - 200 OK
{
"data": {
"global_ltv_usd": 15.40,
"global_ltv_30d_usd": 4.20,
"segments": [
{
"label": "example-casino",
"user_count": 8420,
"ltv_usd": 15.25,
"ltv_30d_usd": 4.10,
"avg_lifespan_days": 62,
"avg_trades": 25.5,
"avg_volume_usd": 294.50
},
{
"label": "lucky-spins",
"user_count": 2100,
"ltv_usd": 12.80,
"ltv_30d_usd": 3.60,
"avg_lifespan_days": 28,
"avg_trades": 14.2,
"avg_volume_usd": 182.00
}
],
"trend": [
{ "month": "2026-01", "ltv_usd": 14.20 },
{ "month": "2026-02", "ltv_usd": 14.80 },
{ "month": "2026-03", "ltv_usd": 15.40 }
]
}
}Behavioral Patterns
Returns detected behavioral patterns across the user base. Includes peak trading hours, popular categories, average session duration, trade frequency distributions, and device/platform breakdown.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
from | string | 30 days ago | ISO 8601 start date. |
to | string | now | ISO 8601 end date. |
operator | string | null | Filter by operator slug. |
Response - 200 OK
{
"data": {
"peak_hours_utc": [18, 19, 20, 21],
"category_distribution": [
{ "category": "sports", "pct": 42.0 },
{ "category": "crypto", "pct": 28.0 },
{ "category": "politics", "pct": 18.0 },
{ "category": "entertainment", "pct": 12.0 }
],
"avg_session_duration_minutes": 14.2,
"avg_trades_per_session": 3.4,
"trade_frequency_distribution": {
"1_per_week": 0.32,
"2_5_per_week": 0.28,
"6_10_per_week": 0.22,
"11_plus_per_week": 0.18
},
"device_breakdown": {
"mobile": 0.68,
"desktop": 0.28,
"tablet": 0.04
},
"bet_size_distribution": {
"under_5_usd": 0.35,
"5_20_usd": 0.38,
"20_100_usd": 0.20,
"100_plus_usd": 0.07
},
"popular_markets": [
{ "market_id": "mkt_001", "title": "Will BTC exceed $150k...", "trade_count": 12400 }
]
}
}Configuration
Global platform configuration. Controls risk limits, spread parameters, fee structures, feature flags, and system-wide defaults. Changes are audit-logged with the admin user who made them.
Get Configuration
Response - 200 OK
{
"data": {
"risk": {
"global_exposure_limit_usd": 500000,
"category_limits": {
"sports": 200000,
"crypto": 150000,
"politics": 100000,
"entertainment": 50000
},
"per_trade_max_usd": 5000,
"per_market_max_usd": 50000,
"circuit_breaker_threshold_pct": 90,
"sharp_score_threshold": 60,
"restricted_score_threshold": 80
},
"spread": {
"base_spread_bps": 200,
"min_spread_bps": 100,
"max_spread_bps": 800,
"risk_multiplier": 1.5,
"volume_discount_enabled": true,
"volume_discount_threshold_usd": 10000,
"volume_discount_bps": 25
},
"fees": {
"trading_fee_bps": 50,
"settlement_fee_bps": 0,
"withdrawal_fee_usd": 0
},
"features": {
"s2s_enabled": true,
"embed_enabled": true,
"auto_settlement": true,
"sharp_detection": true,
"revenue_forecast": true,
"cohort_analytics": true
},
"defaults": {
"operator_revenue_share_pct": 70,
"user_max_bet_usd": 1000,
"session_timeout_hours": 8,
"s2s_retry_max": 5,
"s2s_retry_backoff_ms": 1000
},
"updated_at": "2026-03-18T09:00:00Z",
"updated_by": "admin_001"
}
}Update Configuration
Updates one or more configuration values. Supports partial updates - only include the keys you want to change. All changes are audit-logged. Some changes (like reducing global exposure limits) may trigger immediate risk re-evaluation.
Request Body
{
"risk": {
"global_exposure_limit_usd": 600000,
"sharp_score_threshold": 55
},
"spread": {
"base_spread_bps": 250
},
"reason": "Increasing global limit for March Madness volume spike"
}Response - 200 OK
{
"data": {
"updated_keys": [
"risk.global_exposure_limit_usd",
"risk.sharp_score_threshold",
"spread.base_spread_bps"
],
"previous_values": {
"risk.global_exposure_limit_usd": 500000,
"risk.sharp_score_threshold": 60,
"spread.base_spread_bps": 200
},
"new_values": {
"risk.global_exposure_limit_usd": 600000,
"risk.sharp_score_threshold": 55,
"spread.base_spread_bps": 250
},
"audit_id": "aud_cfg_001",
"updated_by": "admin_001",
"updated_at": "2026-03-19T12:00:00Z"
}
}Reports
Generate on-demand or scheduled reports in CSV, Excel, or PDF format. Reports can cover trades, revenue, users, risk events, or settlements within a specified date range.
Generate Report
Request Body
{
"type": "trades",
"format": "csv",
"filters": {
"operator": "example-casino",
"from": "2026-03-01T00:00:00Z",
"to": "2026-03-19T23:59:59Z",
"min_amount": 10
},
"columns": ["id", "user_name", "market_title", "outcome", "side", "price", "quantity", "cost_usd", "fee_usd", "created_at"],
"delivery": "download"
}| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Report type: trades, revenue, users, risk_events, settlements, invoices. |
format | string | Yes | Output format: csv, xlsx, pdf. |
filters | object | No | Filter criteria (varies by report type). |
columns | string[] | No | Specific columns to include. Defaults to all available columns. |
delivery | string | No | download (default) or email. |
email | string | No | Required if delivery is email. |
Response - 200 OK (download)
{
"data": {
"report_id": "rpt_001",
"type": "trades",
"format": "csv",
"status": "ready",
"download_url": "/api/internal/reports/rpt_001/download",
"expires_at": "2026-03-19T14:00:00Z",
"row_count": 4280,
"file_size_bytes": 842000,
"generated_at": "2026-03-19T12:00:05Z"
}
}Scheduled Reports
Creates a recurring report schedule. Reports are generated automatically at the specified frequency and delivered via email.
Request Body
{
"name": "Weekly Operator Trade Report",
"type": "trades",
"format": "xlsx",
"frequency": "weekly",
"day_of_week": 1,
"time_utc": "08:00",
"filters": {
"operator": "example-casino"
},
"recipients": ["ops@predictu.com", "reports@example-casino.com"],
"enabled": true
}Response - 201 Created
{
"data": {
"id": "sched_001",
"name": "Weekly Operator Trade Report",
"type": "trades",
"format": "xlsx",
"frequency": "weekly",
"day_of_week": 1,
"time_utc": "08:00",
"next_run_at": "2026-03-24T08:00:00Z",
"recipients": ["ops@predictu.com", "reports@example-casino.com"],
"enabled": true,
"created_by": "admin_001",
"created_at": "2026-03-19T12:00:00Z"
}
}Data Export
Bulk data export for specific entity types. Unlike reports (which are filtered and formatted), exports produce raw data dumps suitable for data warehouse ingestion or external analysis.
Export Data
Path Parameters
| Param | Type | Description |
|---|---|---|
type | string | Export type: users, trades, positions, ledger, settlements, risk_events. |
Request Body
{
"format": "csv",
"from": "2026-01-01T00:00:00Z",
"to": "2026-03-19T23:59:59Z",
"operator": null,
"include_pii": false,
"compression": "gzip"
}| Field | Type | Default | Description |
|---|---|---|---|
format | string | "csv" | Export format: csv, jsonl, parquet. |
from | string | Required | ISO 8601 start date. |
to | string | Required | ISO 8601 end date. |
operator | string | null | Filter by operator slug. |
include_pii | boolean | false | Include PII (emails, names). Requires elevated permissions. |
compression | string | "none" | Compression: none, gzip, zstd. |
Response - 202 Accepted
{
"data": {
"export_id": "exp_001",
"type": "trades",
"format": "csv",
"status": "processing",
"estimated_rows": 892000,
"estimated_size_bytes": 180000000,
"poll_url": "/api/internal/export/exp_001/status",
"created_at": "2026-03-19T12:00:00Z"
}
}poll_url for status updates. When status changes to "ready", a download_url will be included in the response. Download links expire after 1 hour.File Upload
Upload files to the Predictu CDN. Used for operator logos, favicons, market images, and invoice attachments. Returns a CDN URL that can be referenced in subsequent API calls.
Upload File
Send the file as multipart/form-data. The Content-Type must bemultipart/form-data - do not use application/json.
Form Fields
| Field | Type | Required | Description |
|---|---|---|---|
file | File | Yes | The file to upload. Max 5MB. Accepted types: png, jpg, jpeg, svg, webp, pdf. |
category | string | Yes | Upload category: operator_logo, operator_favicon, market_image, invoice_attachment. |
operator_slug | string | No | Associate the file with an operator. Required for operator assets. |
Response - 200 OK
{
"data": {
"id": "file_001",
"url": "https://cdn.predictu.com/operators/example-casino/logo.png",
"category": "operator_logo",
"operator_slug": "example-casino",
"content_type": "image/png",
"size_bytes": 24800,
"width": 512,
"height": 512,
"uploaded_by": "admin_001",
"uploaded_at": "2026-03-19T12:00:00Z"
}
}Operator Onboarding
Advance an operator through the onboarding pipeline. The onboarding flow consists of steps:branding → s2s_config → embed_setup → test_trades → go_live. Each step validates prerequisites before allowing progression.
Advance Onboarding Step
Path Parameters
| Param | Type | Description |
|---|---|---|
operatorId | string | Operator ID (e.g. op_abc123). |
Request Body
{
"action": "advance",
"step": "s2s_config",
"data": {
"callback_url": "https://api.luckyspins.com/predictu/callback",
"signing_key_confirmed": true,
"test_callback_success": true
},
"notes": "S2S callback verified with test transaction"
}| Field | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Action: advance (move to next step), rollback (go back one step), skip (skip optional step). |
step | string | Yes | Current step being completed. |
data | object | No | Step-specific data to validate and persist. |
notes | string | No | Admin notes for the onboarding audit trail. |
Response - 200 OK
{
"data": {
"operator_id": "op_xyz789",
"current_step": "embed_setup",
"previous_step": "s2s_config",
"completed_steps": ["branding", "s2s_config"],
"remaining_steps": ["embed_setup", "test_trades", "go_live"],
"status": "configuring",
"progress_pct": 40,
"notes": "S2S callback verified with test transaction",
"updated_by": "admin_001",
"updated_at": "2026-03-19T12:00:00Z"
}
}go_live step requires all previous steps to be completed and at least one successful test trade to have been executed through the S2S pipeline. Attempting to advance togo_live without meeting prerequisites returns a 422 with a list of unmet requirements.Pagination
All list endpoints use offset-based pagination with a consistent response envelope. The activity feed uses cursor-based pagination for real-time consistency.
Offset Pagination
// Request
GET /api/internal/trades?page=2&limit=50
// Response envelope
{
"data": [...],
"pagination": {
"page": 2,
"limit": 50,
"total": 892310,
"total_pages": 17847
}
}Cursor Pagination
// Request
GET /api/internal/activity?limit=50&cursor=eyJpZCI6ImFjdF8wNTAifQ==
// Response envelope
{
"data": [...],
"next_cursor": "eyJpZCI6ImFjdF8xMDAifQ=="
}X-RateLimit-Remaining and X-RateLimit-Reset headers are included in every response. Exceeding the limit returns 429 Too Many Requests.