Operator Data API Reference
Full reference for the data ingestion API.
Base path: /functions/v1/operator-data-api
Authentication: Authorization: Bearer oh_live_...
List templates {#list-templates}
GET /templatesReturns all available data templates.
curl https://api.onehazel.com/operator-data-api/templates \
-H "Authorization: Bearer oh_live_YOUR_API_KEY"Response:
{
"success": true,
"data": [
{
"id": "tpl_igaming",
"name": "iGaming",
"version": "1.0",
"schema": {
"entity_types": { "player": { "required": [...], "optional": [...] } },
"event_types": { "transaction": { "required": ["type", "amount", "currency"], "optional": [...] } },
"state_keys": ["balance", "kyc_status", "risk_score", "loyalty_tier"],
"pii_fields": { "player": ["first_name", "last_name", "email", "phone", "date_of_birth"] }
},
"created_at": "2026-01-01T00:00:00.000Z"
}
]
}Get settings {#get-settings}
GET /settingsReturns the operator's configured template and data retention settings.
curl https://api.onehazel.com/operator-data-api/settings \
-H "Authorization: Bearer oh_live_YOUR_API_KEY"Response:
{
"success": true,
"data": {
"template": {
"id": "tpl_igaming",
"name": "iGaming",
"version": "1.0"
},
"dataRetentionDays": null,
"retentionPolicy": null
}
}Update settings {#update-settings}
PUT /settingsSet the data template and/or retention policy.
| Field | Type | Description |
|---|---|---|
templateId | string | Template ID (e.g. tpl_igaming) |
dataRetentionDays | number | Global data retention in days |
retentionPolicy | object | Per-type retention configuration |
Retention policy
{
"retentionPolicy": {
"entity_events": { "hot_days": 90, "archive_days": 365 },
"entity_states": { "hot_days": 30, "archive_days": 180 }
}
}Constraints:
entity_events.hot_daysminimum: 30entity_events.archive_daysmaximum: 1825 (5 years)entity_states.hot_daysminimum: 30entity_states.archive_daysmaximum: 1825 (5 years)
curl -X PUT https://api.onehazel.com/operator-data-api/settings \
-H "Authorization: Bearer oh_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "tpl_igaming",
"retentionPolicy": {
"entity_events": { "hot_days": 90, "archive_days": 365 }
}
}'Create or update entity {#create-entity}
POST /entities| Field | Type | Required | Description |
|---|---|---|---|
entityType | string | Yes | Entity type from template |
externalId | string | Yes | Your unique identifier |
data | object | Yes | Entity data payload |
Headers:
| Header | Required | Description |
|---|---|---|
Idempotency-Key | No | Prevents duplicate processing (24h TTL) |
Rate limit: ingest:realtime
curl -X POST https://api.onehazel.com/operator-data-api/entities \
-H "Authorization: Bearer oh_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"entityType": "player",
"externalId": "player_12345",
"data": {
"first_name": "James",
"last_name": "Wilson",
"email": "james@example.com",
"country": "GB",
"currency": "GBP"
}
}'Response (201 / 200):
{
"success": true,
"data": {
"id": "ent_a1b2c3d4e5f67890",
"externalId": "player_12345",
"entityType": "player",
"action": "created"
}
}action is "created" (201) for new entities, "updated" (200) for existing ones.
Get entity {#get-entity}
GET /entities/:externalIdReturns entity with decrypted PII fields.
curl https://api.onehazel.com/operator-data-api/entities/player_12345 \
-H "Authorization: Bearer oh_live_YOUR_API_KEY"Delete entity (GDPR) {#delete-entity}
DELETE /entities/:externalIdSoft-deletes the entity: data is replaced with { "_deleted": true }, related events are redacted to { "_redacted": true }, and all states are removed.
curl -X DELETE https://api.onehazel.com/operator-data-api/entities/player_12345 \
-H "Authorization: Bearer oh_live_YOUR_API_KEY"Record event {#record-event}
POST /entities/:externalId/events| Field | Type | Required | Description |
|---|---|---|---|
eventType | string | Yes | Event type from template |
data | object | Yes | Event data payload |
Headers:
| Header | Required | Description |
|---|---|---|
Idempotency-Key | No | Prevents duplicate events (24h TTL, scoped per operator) |
Rate limit: ingest:realtime
If an event with the same idempotency key already exists, returns the original event ID with "action": "duplicate".
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-abc123" \
-d '{
"eventType": "transaction",
"data": {
"type": "deposit",
"amount": 50.00,
"currency": "GBP",
"method": "card"
}
}'List events {#list-events}
GET /entities/:externalId/events| Parameter | Type | Default | Description |
|---|---|---|---|
type | string | — | Filter by event type |
limit | integer | 100 | Max 100 |
offset | integer | 0 | Pagination offset |
curl "https://api.onehazel.com/operator-data-api/entities/player_12345/events?type=transaction&limit=20" \
-H "Authorization: Bearer oh_live_YOUR_API_KEY"Update state {#update-state}
PUT /entities/:externalId/state/:keyRequest body: { "value": <any JSON value> } or the value directly.
Rate limit: ingest:realtime
curl -X PUT https://api.onehazel.com/operator-data-api/entities/player_12345/state/balance \
-H "Authorization: Bearer oh_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "value": { "amount": 145.50, "currency": "GBP" } }'Get all states {#get-all-states}
GET /entities/:externalId/statecurl https://api.onehazel.com/operator-data-api/entities/player_12345/state \
-H "Authorization: Bearer oh_live_YOUR_API_KEY"Get single state {#get-state}
GET /entities/:externalId/state/:keycurl https://api.onehazel.com/operator-data-api/entities/player_12345/state/kyc_status \
-H "Authorization: Bearer oh_live_YOUR_API_KEY"Batch entities {#batch-entities}
POST /batch/entitiesArray of { entityType, externalId, data } objects. Maximum 1,000 items.
Rate limit: ingest:batch
Batch events {#batch-events}
POST /batch/eventsArray of { externalId, eventType, data } objects. Maximum 5,000 items.
Rate limit: ingest:batch
Batch states {#batch-states}
POST /batch/statesArray of { externalId, stateKey, value } objects. Maximum 1,000 items.
Rate limit: ingest:batch
Job status {#job-status}
GET /batch/jobs/:jobIdReturns the status of a batch job, scoped to the authenticated operator.
curl https://api.onehazel.com/operator-data-api/batch/jobs/job_d4e5f6789012abcd \
-H "Authorization: Bearer oh_live_YOUR_API_KEY"Response:
{
"success": true,
"data": {
"id": "job_d4e5f6789012abcd",
"type": "batch_ingest_entities",
"status": "completed",
"progress": 100,
"output": { "succeeded": 100, "failed": 2, "errors": [...] },
"error": null,
"created_at": "2026-04-06T12:00:00.000Z",
"completed_at": "2026-04-06T12:00:05.000Z"
}
}Error codes
| HTTP Status | Error Code | Description |
|---|---|---|
400 | MISSING_FIELDS | Required fields are missing |
400 | VALIDATION_FAILED | Data fails template validation |
400 | TEMPLATE_NOT_CONFIGURED | No template set — call PUT /settings first |
400 | INVALID_INPUT | Invalid batch input (not an array, empty, or exceeds limit) |
401 | UNAUTHORIZED | Missing or invalid API key |
404 | ENTITY_NOT_FOUND | Entity with given externalId not found |
404 | NOT_FOUND | Resource not found |
429 | RATE_LIMITED | Rate limit exceeded |
500 | INTERNAL_ERROR | Server error |