Events ingestion
Events go to the ingestion host, not the API host:
POST https://ingest.casinocrm.io/v1/events— single eventPOST https://ingest.casinocrm.io/v1/events/batch— up to 100 events
Posting events to api.casinocrm.io returns 404. The api host is only
for identify, admin, and read endpoints.
Auth: API key — Authorization: Bearer ucrm_pk_<env>_<id>_<secret>.
Identity
Every event must carry anonymous_id or player_id — at least one is
required (otherwise 422 IDENTITY_REQUIRED).
anonymous_id— a stable id you control. Server-side platforms send their own permanent player id here. It's the join key betweenidentifyand events.player_id— the casinocrm.io uuid returned byidentify(use it if you store it).external_id— optional, accepted for your own reference. Not a substitute foranonymous_id/player_id.
Single event
{
"event": "deposit_confirmed",
"anonymous_id": "casino_player_001", // REQUIRED (or player_id)
"timestamp": "2026-05-08T10:00:00Z", // ISO-8601 UTC — when it happened
"properties": {
"amount": 5000, // smallest currency unit (cents / sat)
"currency": "EUR",
"transaction_id": "tx_abc",
"payment_method": "card"
}
}
Response 202:
{ "data": { "ingestion_id": "uuid", "accepted": true, "tenant_id": "...", "project_id": "..." } }
202 = accepted into the queue. Stream-processor consumes within ~50ms typical.
Unknown top-level fields are rejected (400 BODY_MALFORMED). Allowed top-level
keys: event, anonymous_id, player_id, external_id, timestamp, properties.
Batch
POST https://ingest.casinocrm.io/v1/events/batch — wrap events in an object
(a bare array is rejected):
{
"events": [
{ "event": "bet_placed", "anonymous_id": "casino_player_001", "timestamp": "...", "properties": { ... } },
{ "event": "bet_settled", "anonymous_id": "casino_player_001", "timestamp": "...", "properties": { ... } }
]
}
Response 202:
{ "data": { "ingestion_id": "uuid", "accepted": 2, "rejected": [] } }
rejected lists per-event failures (index + reason) — a partial batch still
accepts the valid events.
Canonical event names
# Identity / session
signup, login, logout, session_start, session_end, page_view, click
# KYC + responsible gaming
kyc_submitted, kyc_approved, kyc_rejected, kyc_expired, kyc_level_upgraded
self_exclusion_set, self_exclusion_lifted
deposit_limit_set, deposit_limit_reached
loss_limit_set, loss_limit_reached
session_limit_warning, session_limit_exceeded
reality_check, cooldown_entered
# Money in/out
deposit_initiated, deposit_confirmed, deposit_failed
withdrawal_requested, withdrawal_confirmed, withdrawal_failed
# Wagering — casino
bet_placed, bet_won, bet_lost, bet_settled
# Wagering — sportsbook (two-phase)
sport_bet_placed, sport_bet_settled, sport_bet_voided, sport_cashout
# Bonuses
bonus_claimed, bonus_wagered, bonus_completed, bonus_expired
# Outbound messaging delivery feedback
email_sent, email_opened, email_clicked, email_bounced
sms_sent, sms_clicked
push_sent, push_opened
Custom events: prefix with custom_. Accepted, no schema enforced.
Required properties per event
Property shapes are validated by JSON Schema. A missing required field returns
422 PROPERTIES_INVALID — the message names the offending field.
deposit_confirmed / deposit_initiated:
{
"amount": 5000, // required, smallest unit
"currency": "EUR", // required
"transaction_id": "tx_1", // required (idempotency)
"payment_method": "card" // REQUIRED (e.g. card | bank | crypto)
}
withdrawal_confirmed / withdrawal_requested:
{ "amount": 5000, "currency": "EUR", "transaction_id": "wd_1" }
bet_placed:
{ "amount": 200, "currency": "EUR", "bet_id": "b1", "game_id": "starburst",
"game_category": "slots" } // slots | live | table | crash | dice | other
bet_settled:
{ "amount": 200, "payout": 0, "currency": "EUR",
"bet_id": "b1", "game_id": "starburst", "game_category": "slots",
"outcome": "lost" } // won | lost
sport_bet_placed:
{ "amount": 200, "currency": "EUR", "bet_id": "sb1",
"sport": "football", "bet_type": "single", "odds": "1.85", "event_ref": "m123" }
bet_type ∈ single | accumulator | system.
Conventions
| Rule | Detail |
|---|---|
| Money | integer, smallest unit (€50.00 → 5000), always with currency |
| Timestamps | ISO-8601 UTC, when the event happened |
anonymous_id | stable, never reused per player |
transaction_id / bet_id | your unique ids; idempotency, safe to retry |
| Rate limit | ~1000 req/min per key (X-RateLimit-* headers) |
Errors
| Code | Meaning |
|---|---|
202 | accepted |
401 | bad/missing API key |
404 | wrong host — events must go to ingest.casinocrm.io |
422 IDENTITY_REQUIRED | missing anonymous_id/player_id |
422 PROPERTIES_INVALID | properties failed schema (message names the field) |
400 BODY_MALFORMED | unknown field / invalid JSON |
429 | rate limited |