Betting Monitor API v1
A powerful RESTful API for real-time betting event ingestion and fraud detection. Monitor player behavior, detect anomalies, and receive alerts for suspicious activities.
Quick Start
- 1 Log in to the Betting Monitor Dashboard
- 2 Generate your API Key in Settings → API Keys
- 3 Start sending events using POST /events or /events/batch
- 4 Configure webhooks to receive fraud alerts in real-time
Base URL
Staging: https://staging.bettingmonitor.cloudpmt.com/api/v1
Sandbox: https://sandbox.bettingmonitor.cloudpmt.com/api/v1
Secure
X-API-Key authentication
Real-time
Async event ingestion
Batch Support
High throughput ingestion
Alerts
Fraud detection webhooks
Authentication
All API requests require authentication via the X-API-Key header.
Required Headers
| Header | Description | Required |
|---|---|---|
| X-API-Key | Your API key from the dashboard | Yes |
| Content-Type | application/json | Yes |
Example Request
curl -X POST "https://bettingmonitor.cloudpmt.com/api/v1/events" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key-here" \
-d '{"external_event_id":"evt-123","player_id":"player-456","event_type":"DEPOSIT","amount":100000,"currency":"XOF","event_timestamp":"2026-01-31T12:00:00Z"}'
Rate Limiting
API requests are rate limited per company based on your plan. Rate limit information is included in response headers.
Response Headers
| Header | Description | Example |
|---|---|---|
| X-RateLimit-Limit | Maximum requests allowed per minute | 1000 |
| X-RateLimit-Remaining | Remaining requests in current window | 950 |
| X-RateLimit-Reset | Unix timestamp when the rate limit resets | 1707321600 |
| Retry-After | Seconds to wait before retrying (only on 429) | 45 |
Rate Limit Exceeded (429)
When you exceed your rate limit, the API returns 429 Too Many Requests.
Check the Retry-After header and wait before retrying.
Error Handling
| HTTP Code | Meaning | Action |
|---|---|---|
| 200/201/202 | Success | Request processed successfully |
| 400 | Bad Request | Check request body and parameters |
| 401 | Unauthorized | Check your API key |
| 404 | Not Found | Resource does not exist |
| 429 | Rate Limited | Reduce request frequency |
| 500 | Server Error | Retry with exponential backoff |
/api/v1/lookups
Get lookup tables for event types, game types, and device types. Use these values when ingesting events.
Response 200 OK
{
"event_types": [
{ "id": 1, "code": "DEPOSIT", "name": "Deposit" },
{ "id": 2, "code": "WITHDRAWAL", "name": "Withdrawal" },
{ "id": 3, "code": "BET_PLACED", "name": "Bet Placed" },
{ "id": 4, "code": "BET_WON", "name": "Bet Won" },
{ "id": 5, "code": "BET_LOST", "name": "Bet Lost" },
{ "id": 6, "code": "BONUS_CREDITED", "name": "Bonus Credited" },
{ "id": 7, "code": "BONUS_USED", "name": "Bonus Used" },
{ "id": 8, "code": "REFUND", "name": "Refund" },
{ "id": 9, "code": "CASHOUT", "name": "Cash Out" },
{ "id": 10, "code": "JACKPOT", "name": "Jackpot" }
],
"game_types": [
{ "id": 1, "code": "SPORTS", "name": "Sports Betting" },
{ "id": 2, "code": "CASINO", "name": "Casino" },
{ "id": 3, "code": "VIRTUAL", "name": "Virtual Sports" },
{ "id": 4, "code": "LOTTERY", "name": "Lottery" },
{ "id": 5, "code": "POKER", "name": "Poker" },
{ "id": 6, "code": "ESPORTS", "name": "eSports" },
{ "id": 7, "code": "LIVE_CASINO", "name": "Live Casino" }
],
"device_types": [
{ "id": 1, "code": "DESKTOP", "name": "Desktop" },
{ "id": 2, "code": "MOBILE", "name": "Mobile" },
{ "id": 3, "code": "TABLET", "name": "Tablet" },
{ "id": 4, "code": "API", "name": "API" },
{ "id": 5, "code": "OTHER", "name": "Other" }
],
"operators": [
{ "id": 1, "code": "ORANGE_SN", "name": "Orange Money Senegal", "country": "SEN" },
{ "id": 2, "code": "WAVE_SN", "name": "Wave Senegal", "country": "SEN" },
{ "id": 5, "code": "ORANGE_CI", "name": "Orange Money Côte d'Ivoire", "country": "CIV" },
{ "id": 6, "code": "MTN_CI", "name": "MTN Mobile Money Côte d'Ivoire", "country": "CIV" },
// ... more operators (see full list via GET /api/v1/lookups)
]
}
Event Types Reference
Use these codes in the event.type field
| Code | Description | When to Use |
|---|---|---|
| DEPOSIT | Player adds funds to account | Mobile money, bank transfer, card payment received |
| WITHDRAWAL | Player withdraws funds | Payout to mobile money, bank, or cash |
| BET_PLACED | Player places a bet | Sports bet, casino wager, lottery ticket purchase |
| BET_WON | Player wins a bet | Bet settled as won, winnings credited to balance |
| BET_LOST | Player loses a bet | Bet settled as lost (amount already deducted at BET_PLACED) |
| BONUS_CREDITED | Bonus added to account | Welcome bonus, promo, loyalty reward, free bet granted |
| BONUS_USED | Bonus funds used | Free bet placed, bonus converted to real money |
| REFUND | Bet refunded to player | Voided bet, cancelled match, technical issue |
| CASHOUT | Early bet settlement | Player cashes out before event ends (partial/full) |
| JACKPOT | Jackpot win | Progressive jackpot, slot jackpot, lottery big win |
Game Types Reference
Use these codes in the game.type field (optional)
| Code | Description | Examples |
|---|---|---|
| SPORTS | Sports betting | Football, Basketball, Tennis, Boxing |
| CASINO | Casino games | Slots, Roulette, Blackjack, Baccarat |
| VIRTUAL | Virtual sports | Virtual football, Virtual racing, Virtual tennis |
| LOTTERY | Lottery games | Lotto, Keno, Scratch cards |
| POKER | Poker games | Texas Hold'em, Omaha, Tournaments |
| ESPORTS | eSports betting | CS:GO, Dota 2, League of Legends |
| LIVE_CASINO | Live dealer games | Live Roulette, Live Blackjack, Game shows |
Device Types Reference
Use these codes in the metadata.device_type field (optional)
| Code | Description | When to Use |
|---|---|---|
| DESKTOP | Desktop computer | Windows, macOS, Linux browsers |
| MOBILE | Mobile phone | iOS/Android app or mobile browser |
| TABLET | Tablet device | iPad, Android tablet |
| API | Server-to-server | USSD, SMS betting, backend integration |
| OTHER | Other device | Smart TV, kiosk, unknown device |
Payment Operators Reference
Use these codes in the metadata.operator field for deposit/withdrawal events
| Code | Operator | Country |
|---|---|---|
| Senegal (SEN) | ||
| ORANGE_SN | Orange Money | SEN |
| WAVE_SN | Wave | SEN |
| FREE_SN | Free Money | SEN |
| Côte d'Ivoire (CIV) | ||
| ORANGE_CI | Orange Money | CIV |
| MTN_CI | MTN Mobile Money | CIV |
| WAVE_CI | Wave | CIV |
| MOOV_CI | Moov Money | CIV |
| Mali (MLI) | ||
| ORANGE_ML | Orange Money | MLI |
| WAVE_ML | Wave | MLI |
| Ghana (GHA) | ||
| MTN_GH | MTN Mobile Money | GHA |
| VODAFONE_GH | Vodafone Cash | GHA |
| Nigeria (NGA) | ||
| MTN_NG | MTN MoMo | NGA |
| OPAY_NG | OPay | NGA |
| Other | ||
| BANK_TRANSFER | Bank Transfer | - |
| CARD | Card Payment | - |
See full list via GET /api/v1/lookups endpoint
/api/v1/events
Ingest a single betting event asynchronously. Returns 202 Accepted immediately - the event will be processed in the background.
Grouped Request Structure
Fields are organized into logical groups: player, event, game, and metadata.
Request Body (Grouped Structure)
{
"event_id": "evt_20250203_143245_abc123",
// Player information (required)
"player": {
"id": "pl_12345abc",
"phone": "+221771234567",
"country": "SEN",
"kyc_level": 2
},
// Event details (required)
"event": {
"type": "BET_PLACED",
"timestamp": "2026-02-03T14:32:45Z",
"amount": 5000,
"currency": "XOF",
"balance_before": 15000,
"balance_after": 10000
},
// Game context (optional - for betting events)
"game": {
"type": "SPORTS",
"id": "game_789",
"name": "Senegal vs Nigeria",
"sport": "football",
"competition": "CAN 2025",
"odds": 2.5,
"bet_id": "bet_456"
},
// Tracking metadata (optional)
"metadata": {
"device_type": "MOBILE",
"operator": "ORANGE_SN",
"ip_address": "41.138.45.22",
"session_id": "sess_xyz"
}
}
Field Reference
| Field | Type | Required | Description |
|---|---|---|---|
| event_id | string | Yes | Your unique event ID (max 100 chars) |
| player | object | Yes | Player information object |
| event | object | Yes | Event details object |
| game | object | No | Game/betting context (recommended for BET events) |
| metadata | object | No | Tracking and session metadata |
| player.id | string | Yes | Player identifier (max 100 chars) |
| player.phone | string | No | Phone number (max 50 chars) |
| player.country | string | No | ISO 3166-1 alpha-3 (SEN, CIV, MLI...) |
| player.kyc_level | integer | No | KYC verification level (0-5) |
| event.type | string | Yes | BET_PLACED, BET_WON, BET_LOST, DEPOSIT, WITHDRAWAL, BONUS_CREDITED, BONUS_USED, REFUND, CASHOUT, JACKPOT |
| event.timestamp | string | Yes | ISO 8601 (2026-01-31T12:00:00Z) |
| event.amount | integer | Yes | Amount in currency units (5000 = 5,000 XOF) |
| event.currency | string | Yes | ISO 4217 (XOF, EUR, USD...) |
| event.balance_before | integer | No | Player balance before event (in currency units) |
| event.balance_after | integer | No | Player balance after event (in currency units) |
| game.type | string | No | SPORTS, CASINO, VIRTUAL, LOTTERY, POKER, ESPORTS, LIVE_CASINO |
| game.id | string | No | Game identifier (max 100 chars) |
| game.name | string | No | Match/game name (e.g., "Senegal vs Nigeria") |
| game.sport | string | No | Sport type (football, basketball...) |
| game.competition | string | No | Competition name (CAN 2025, Premier League...) |
| game.odds | float | No | Betting odds |
| game.bet_id | string | No | Related bet ID (for WIN/LOSS events) |
| metadata.device_type | string | No | DESKTOP, MOBILE, TABLET, API, OTHER |
| metadata.operator | string | No | Payment operator: ORANGE_SN, WAVE_SN, MTN_CI, etc. |
| metadata.ip_address | string | No | Player's IP address |
| metadata.session_id | string | No | Session identifier (max 100 chars) |
| metadata.user_agent | string | No | Browser/app user agent (max 500 chars) |
Response 202 Accepted
{
"success": true,
"data": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"event_month": 202602,
"external_event_id": "evt_20250203_143245_abc123",
"amount_cents": 10000000,
"amount": 100000,
"currency": "XOF",
"received_at": "2026-02-07T06:19:00.681884Z"
}
}
/api/v1/events/batch
Ingest multiple betting events in a single request. Recommended for high-throughput scenarios. Returns success/failure counts for each event.
Best for high throughput
Send up to 1000 events per request for optimal performance.
Request Body (Grouped Structure)
{
"events": [
{
"event_id": "evt_001",
"player": {
"id": "player_123",
"phone": "+221771234567",
"country": "SEN"
},
"event": {
"type": "DEPOSIT",
"timestamp": "2026-01-31T12:00:00Z",
"amount": 100000,
"currency": "XOF"
},
"metadata": {
"device_type": "MOBILE",
"ip_address": "41.138.45.22"
}
},
{
"event_id": "evt_002",
"player": {
"id": "player_123"
},
"event": {
"type": "BET_PLACED",
"timestamp": "2026-01-31T12:05:00Z",
"amount": 50000,
"currency": "XOF"
},
"game": {
"type": "SPORTS",
"name": "Senegal vs Mali",
"sport": "football",
"odds": 2.5
}
}
]
}
Response 200 OK
{
"success": true,
"data": {
"success_count": 2,
"failed_count": 1,
"events": [
{
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"external_event_id": "evt_001"
},
{
"uuid": "550e8400-e29b-41d4-a716-446655440001",
"external_event_id": "evt_002"
},
{
"uuid": null,
"external_event_id": "evt_003",
"error": "event_type invalide: INVALID"
}
]
}
}
/api/v1/events/:uuid/status
Check the processing status of an event by its UUID.
Response 200 OK
{
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"status": "PROCESSED",
"processed_at": "2026-01-31T12:00:05Z"
}
API Playground
Test the API directly from your browser.
Credentials
Request
Response
Response will appear here after sending the request