Skip to content

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/entities

Upserts 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:

json
[
  { "entityType": "player", "externalId": "player_001", "data": { ... } },
  { "entityType": "player", "externalId": "player_002", "data": { ... } }
]

Example

bash
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

json
{
  "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:

json
{
  "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/events

Inserts 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:

json
[
  { "externalId": "player_001", "eventType": "transaction", "data": { ... } },
  { "externalId": "player_001", "eventType": "game_activity", "data": { ... } }
]

Example

bash
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

json
{
  "success": true,
  "data": {
    "succeeded": 3,
    "failed": 0,
    "errors": []
  }
}

Batch states

POST /operator-data-api/batch/states

Upserts up to 1,000 state snapshots in a single request.

Request body

An array of state objects:

json
[
  { "externalId": "player_001", "stateKey": "balance", "value": { ... } },
  { "externalId": "player_001", "stateKey": "kyc_status", "value": "verified" }
]

Example

bash
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

json
{
  "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/:jobId

Example

bash
curl https://api.onehazel.com/operator-data-api/batch/jobs/job_d4e5f6789012abcd \
  -H "Authorization: Bearer oh_live_YOUR_API_KEY"

Response

json
{
  "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

EndpointMaximum items per request
POST /batch/entities1,000
POST /batch/events5,000
POST /batch/states1,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 StatusError CodeDescription
400INVALID_INPUTBody is not a non-empty array, or exceeds the maximum batch size
400TEMPLATE_NOT_CONFIGUREDNo template set — call PUT /settings first
401UNAUTHORIZEDMissing or invalid API key
404NOT_FOUNDJob ID not found (for status check)
429RATE_LIMITEDRate limit exceeded for ingest:batch
500INTERNAL_ERRORServer error