# Events Events are immutable log entries attached to entities. They represent things that happened — a player depositing funds, placing a bet, or starting a session. Events are append-only: once recorded, they cannot be modified. ## Record an event ``` POST /operator-data-api/entities/:externalId/events ``` ### Request | Field | Type | Required | Description | |---|---|---|---| | `eventType` | string | Yes | Event type as defined in your template | | `data` | object | Yes | Event payload — must include all required fields for this event type | ### Event types (iGaming template) | Event Type | Description | Required Fields | |---|---|---| | `transaction` | Deposits, withdrawals, adjustments | `type`, `amount`, `currency` | | `game_activity` | Bets, wins, game rounds | `game_id`, `bet_amount` | | `session` | Logins, logouts, session tracking | — | | `bonus` | Bonus awards, wagering, forfeitures | — | | `block` | Self-exclusion, account restrictions | — | | `support` | Support tickets, interactions | — | | `affiliate` | Affiliate tracking, attribution | — | ::: info Event type format Event types are top-level names only: `transaction`, `game_activity`, etc. Do not use dotted formats like `transaction.deposit` — the subtype goes in the `data` payload (e.g. `"type": "deposit"`). ::: ### Idempotency Include an `Idempotency-Key` header to prevent duplicate event recording. If an event with the same idempotency key already exists, the original event ID is returned with `"action": "duplicate"`. Keys are scoped to your operator and expire after 24 hours. ### Example: Record a deposit ```bash curl -X POST https://api.onehazel.com/operator-data-api/entities/player_12345/events \ -H "Authorization: Bearer oh_live_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: deposit-txn-abc123" \ -d '{ "eventType": "transaction", "data": { "type": "deposit", "amount": 100.00, "currency": "GBP", "method": "card", "provider": "stripe", "reference": "txn_abc123", "card_last4": "4242" } }' ``` **Response (201 Created):** ```json { "success": true, "data": { "id": "eev_b2c3d4e5f6789012" } } ``` ### Example: Record a game round ```bash curl -X POST https://api.onehazel.com/operator-data-api/entities/player_12345/events \ -H "Authorization: Bearer oh_live_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "eventType": "game_activity", "data": { "game_id": "european-roulette", "game_name": "European Roulette", "provider": "evolution", "bet_amount": 5.00, "win_amount": 12.50, "currency": "GBP", "round_id": "round_xyz789" } }' ``` **Response (201 Created):** ```json { "success": true, "data": { "id": "eev_c3d4e5f678901234" } } ``` ### Example: Record a session event ```bash curl -X POST https://api.onehazel.com/operator-data-api/entities/player_12345/events \ -H "Authorization: Bearer oh_live_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "eventType": "session", "data": { "action": "login", "ip_address": "203.0.113.42", "country": "GB", "device": "mobile", "browser": "Safari 17" } }' ``` ## List events ``` GET /operator-data-api/entities/:externalId/events ``` Returns events for an entity in reverse chronological order (newest first). ### Query parameters | Parameter | Type | Default | Description | |---|---|---|---| | `type` | string | — | Filter by event type (e.g. `transaction`) | | `limit` | integer | `100` | Number of events to return (max 100) | | `offset` | integer | `0` | Pagination offset | ### Example ```bash curl "https://api.onehazel.com/operator-data-api/entities/player_12345/events?type=transaction&limit=10" \ -H "Authorization: Bearer oh_live_YOUR_API_KEY" ``` **Response:** ```json { "success": true, "data": [ { "id": "eev_b2c3d4e5f6789012", "event_type": "transaction", "data": { "type": "deposit", "amount": 100.00, "currency": "GBP", "method": "card", "provider": "stripe", "reference": "txn_abc123" }, "created_at": "2026-04-06T12:00:00.000Z" } ], "count": 1 } ``` ## Event fan-out When an event is recorded, OneHazel emits an internal event of type `entity_event.` (e.g. `entity_event.transaction`). This can trigger workflows — for example, "when a deposit occurs, call the KYC provider to run a check". ## Error codes | HTTP Status | Error Code | Description | |---|---|---| | `400` | `MISSING_FIELDS` | `eventType` or `data` is missing | | `400` | `VALIDATION_FAILED` | Data does not match template requirements | | `400` | `TEMPLATE_NOT_CONFIGURED` | No template set — call `PUT /settings` first | | `401` | `UNAUTHORIZED` | Missing or invalid API key | | `404` | `ENTITY_NOT_FOUND` | No entity with that `externalId` exists | | `429` | `RATE_LIMITED` | Rate limit exceeded | | `500` | `INTERNAL_ERROR` | Server error |