Batch Operations
Batch endpoints let you send large volumes of data in a single request. Use them for initial data loads, migrations, or periodic bulk syncs.
Batch entities
POST /operator-data-api/batch/entitiesUpserts up to 1,000 entities in a single request. Each entity follows the same format as the individual POST /entities endpoint.
Request body
An array of entity objects:
[
{ "entityType": "player", "externalId": "player_001", "data": { ... } },
{ "entityType": "player", "externalId": "player_002", "data": { ... } }
]Example
curl -X POST https://api.onehazel.com/operator-data-api/batch/entities \
-H "Authorization: Bearer oh_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"entityType": "player",
"externalId": "player_001",
"data": {
"first_name": "Alice",
"last_name": "Chen",
"email": "alice@example.com",
"country": "GB",
"currency": "GBP",
"status": "active"
}
},
{
"entityType": "player",
"externalId": "player_002",
"data": {
"first_name": "Bob",
"last_name": "Smith",
"email": "bob@example.com",
"country": "MT",
"currency": "EUR",
"status": "active"
}
}
]'Response
{
"success": true,
"data": {
"jobId": "job_d4e5f6789012abcd",
"succeeded": 2,
"failed": 0,
"errors": []
}
}Partial failures
If some entities fail validation, the response includes details for each failure:
{
"success": true,
"data": {
"jobId": "job_d4e5f6789012abcd",
"succeeded": 1,
"failed": 1,
"errors": [
{
"index": 1,
"externalId": "player_002",
"code": "VALIDATION_FAILED",
"message": "Missing required field: \"email\""
}
]
}
}Batch events
POST /operator-data-api/batch/eventsInserts up to 5,000 events in a single request. Each event must reference an existing entity by externalId.
Request body
An array of event objects:
[
{ "externalId": "player_001", "eventType": "transaction", "data": { ... } },
{ "externalId": "player_001", "eventType": "game_activity", "data": { ... } }
]Example
curl -X POST https://api.onehazel.com/operator-data-api/batch/events \
-H "Authorization: Bearer oh_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"externalId": "player_001",
"eventType": "transaction",
"data": {
"type": "deposit",
"amount": 100.00,
"currency": "GBP",
"method": "bank_transfer"
}
},
{
"externalId": "player_001",
"eventType": "game_activity",
"data": {
"game_id": "european-roulette",
"bet_amount": 10.00,
"win_amount": 25.00,
"currency": "GBP"
}
},
{
"externalId": "player_002",
"eventType": "transaction",
"data": {
"type": "deposit",
"amount": 50.00,
"currency": "EUR",
"method": "card"
}
}
]'Response
{
"success": true,
"data": {
"succeeded": 3,
"failed": 0,
"errors": []
}
}Batch states
POST /operator-data-api/batch/statesUpserts up to 1,000 state snapshots in a single request.
Request body
An array of state objects:
[
{ "externalId": "player_001", "stateKey": "balance", "value": { ... } },
{ "externalId": "player_001", "stateKey": "kyc_status", "value": "verified" }
]Example
curl -X POST https://api.onehazel.com/operator-data-api/batch/states \
-H "Authorization: Bearer oh_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"externalId": "player_001",
"stateKey": "balance",
"value": { "amount": 250.00, "currency": "GBP" }
},
{
"externalId": "player_001",
"stateKey": "kyc_status",
"value": "verified"
},
{
"externalId": "player_002",
"stateKey": "balance",
"value": { "amount": 50.00, "currency": "EUR" }
},
{
"externalId": "player_002",
"stateKey": "loyalty_tier",
"value": "silver"
}
]'Response
{
"success": true,
"data": {
"succeeded": 4,
"failed": 0,
"errors": []
}
}Checking job status
Batch entity operations create a job record that you can poll:
GET /operator-data-api/batch/jobs/:jobIdExample
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": 2,
"failed": 0,
"errors": []
},
"error": null,
"created_at": "2026-04-06T12:00:00.000Z",
"completed_at": "2026-04-06T12:00:01.500Z"
}
}Limits
| Endpoint | Maximum items per request |
|---|---|
POST /batch/entities | 1,000 |
POST /batch/events | 5,000 |
POST /batch/states | 1,000 |
Synchronous vs asynchronous
Batch entity operations create a job queue entry for tracking, but currently process inline (synchronously). The response includes the full result immediately.
For initial data seeding where you need guaranteed ordering (e.g. create entities before recording events against them), use the individual POST /entities endpoint in sequence rather than the batch endpoint.
Error codes
| HTTP Status | Error Code | Description |
|---|---|---|
400 | INVALID_INPUT | Body is not a non-empty array, or exceeds the maximum batch size |
400 | TEMPLATE_NOT_CONFIGURED | No template set — call PUT /settings first |
401 | UNAUTHORIZED | Missing or invalid API key |
404 | NOT_FOUND | Job ID not found (for status check) |
429 | RATE_LIMITED | Rate limit exceeded for ingest:batch |
500 | INTERNAL_ERROR | Server error |