Skip to content
For LLMsView as Markdown·

Entities ​

Entities are the core records in OneHazel. A player, a game, an operator account: each is represented as an entity with a type, an external ID, and a data payload.

Create or update an entity ​

POST /operator-data-api/entities

Request ​

FieldTypeRequiredDescription
entityTypestringYesEntity type as defined in your template (e.g. player, game)
externalIdstringYesYour unique identifier for this entity
dataobjectYesEntity data, must include all required fields from the template

Upsert semantics ​

If an entity with the same externalId already exists for your operator, the data is updated and the entity type is set to the provided value. If it does not exist, a new entity is created.

PII encryption ​

Fields listed as PII in your template's pii_fields configuration are automatically encrypted before storage using AES-256-GCM with a per-operator derived key. For the iGaming template, PII fields for the player entity type typically include first_name, last_name, email, phone, and date_of_birth.

PII is decrypted only when reading a single entity via GET /entities/:externalId — it remains encrypted in bulk queries.

Idempotency ​

You can include an Idempotency-Key header to prevent duplicate processing. If a request with the same idempotency key has already been processed, the original response is returned. Keys expire after 24 hours.

Example ​

bash
curl -X POST https://api.onehazel.com/operator-data-api/entities \
  -H "Authorization: Bearer oh_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: create-player-12345" \
  -d '{
    "entityType": "player",
    "externalId": "player_12345",
    "data": {
      "first_name": "James",
      "last_name": "Wilson",
      "email": "james.wilson@example.com",
      "country": "GB",
      "currency": "GBP",
      "date_of_birth": "1992-03-15",
      "registration_date": "2026-04-06T10:30:00Z",
      "status": "active",
      "vip_level": "bronze"
    }
  }'

Capturing affiliate attribution

If your players arrive via affiliate or ad-platform links, the tracking params (mid, fluid, gclid, fbclid, utm_*, etc.) must be threaded into the data block on this call. Affiliate platforms reject reports otherwise. See the Affiliate Tag docs for a 30-second <script> install that captures these at landing and exposes them via window.OneHazel.getAttribution(), no URL-parsing code required.

Response (201 Created) ​

json
{
  "success": true,
  "data": {
    "id": "ent_a1b2c3d4e5f67890",
    "externalId": "player_12345",
    "entityType": "player",
    "action": "created"
  }
}

If the entity already exists, the response status is 200 and action is "updated".

Get an entity ​

GET /operator-data-api/entities/:externalId

Retrieves the entity with decrypted PII fields.

Example ​

bash
curl https://api.onehazel.com/operator-data-api/entities/player_12345 \
  -H "Authorization: Bearer oh_live_YOUR_API_KEY"

Response ​

json
{
  "success": true,
  "data": {
    "id": "ent_a1b2c3d4e5f67890",
    "external_id": "player_12345",
    "entity_type": "player",
    "data": {
      "first_name": "James",
      "last_name": "Wilson",
      "email": "james.wilson@example.com",
      "country": "GB",
      "currency": "GBP",
      "date_of_birth": "1992-03-15",
      "registration_date": "2026-04-06T10:30:00Z",
      "status": "active",
      "vip_level": "bronze"
    },
    "created_at": "2026-04-06T10:30:00.000Z",
    "updated_at": "2026-04-06T10:30:00.000Z"
  }
}

Delete an entity (GDPR) ​

DELETE /operator-data-api/entities/:externalId

Performs a soft delete: entity data is replaced with a deletion marker, related events are redacted, and states are removed. This supports GDPR right-to-erasure requests.

Example ​

bash
curl -X DELETE https://api.onehazel.com/operator-data-api/entities/player_12345 \
  -H "Authorization: Bearer oh_live_YOUR_API_KEY"

Response ​

json
{
  "success": true,
  "message": "Entity deleted and data anonymized"
}

Error codes ​

HTTP StatusError CodeDescription
400MISSING_FIELDSentityType, externalId, or data is missing
400VALIDATION_FAILEDData does not match template requirements (details in error.details)
400TEMPLATE_NOT_CONFIGUREDNo template set. Call PUT /settings first
401UNAUTHORIZEDMissing or invalid API key
404ENTITY_NOT_FOUNDNo entity with that externalId exists
429RATE_LIMITEDRate limit exceeded
500INTERNAL_ERRORServer error