Webhook Event Reference

Overview

When you subscribe to events in the Minigames (formerly Adact) Webhook Integration, our system sends an HTTPS POST request with a JSON payload to your specified endpoint whenever that event occurs. This guide details the available events and the structure of their payloads.

Delivery is asynchronous and does not block the player experience. Every attempt—success or failure—is recorded in the Webhooks history, where you can review the full request body and manually re-send any event.

For step-by-step configuration (endpoint, events, segments, and the embed script), see the How to Set Up Webhook Integration guide.

Available Events

Segment Events

These events fire when you manage segments within the API central settings.

  • segment.created
    Sent when a new segment is created.
  • segment.updated
    Sent when a segment is updated (e.g. its title or connected Campaign ID is changed).
  • segment.deleted
    Sent when a segment is deleted.

Player & Prize Events

These are the core events that fire based on user interaction with your live campaigns.

  • player.created
    Sent the first time a unique player registers in a campaign. The payload contains the registration form field data.
  • player.updated
    Sent when a returning/existing player re-registers, or their data is updated.
  • game.ended
    Sent when a player finishes the actual game (e.g. a quiz, an instant-win round).
  • gameplay.finished
    Sent when a player reaches the final/end screen of a campaign.
  • prize.assigned
    Sent when a prize is awarded to a player and a prize code is issued. The payload contains player and prize details.
ℹ️

Choosing between events

  • game.ended and gameplay.finished are not the same. A campaign typically has a game step (game.ended) followed by an end screen (gameplay.finished). For most integrations one is enough; gameplay.finished is the safer "the experience is complete" signal.
  • player.created fires only the first time a unique player registers for a campaign. Subsequent plays by the same player produce player.updated.
  • prize.assigned fires only when a prize is actually awarded—not when a player loses or an already-won prize is re-shown.
  • For some real-time integrations, gameplay.finished may be suppressed per-play when an equivalent real-time event has already been delivered. If you also rely on the real-time integration, do not expect a gameplay.finished webhook for the same play.

The Request Envelope

Every webhook delivery has the same top-level envelope:

{
  "accountId": 3,
  "campaignId": 5,
  "type": "<event type>",
  "payload": { }
}
  • accountId—your Minigames account id. Useful if a single endpoint serves multiple accounts.
  • campaignId—the campaign that produced the event.
  • type—one of the event wire strings above. Dispatch on this.
  • payload—event-specific body, described below.

Event Payloads

player.created / player.updated

{
  "accountId": 3,
  "campaignId": 5,
  "type": "player.created",
  "payload": {
    "playerId": "627cc032cbff6f5f549e23b5",
    "email": "[email protected]",
    "fullName": "James Smith",
    "termsAccepted": true
  }
}
FieldTypeOptional?Notes
playerIdstringrequiredMinigames' stable unique id for the player. Treat as opaque.
emailstringoptionalOnly present if the campaign collected it and the player provided it.
phoneNumberstringoptionalSame.
fullNamestringoptional
firstNamestringoptional
lastNamestringoptional
codestringoptionalPromo/code value collected by some campaigns.
termsAcceptedbooleanoptional
privacyPolicyAcceptedbooleanoptional
extrastringoptionalJSON-encoded string of any custom fields the campaign collects.
integrationUniqueIdstringoptionalOnly present when the campaign landing page was opened with an integrationUniqueId query parameter (e.g. ?integrationUniqueId=abc123). Minigames uses this value as the player's unique identity for recognising returning players, instead of relying on email/phone/cid matching.
cidstringoptionalOptimove customer id, when present.

Where do these fields come from? Every field except playerId, integrationUniqueId, and cid is collected through the registration form configured for the campaign. The campaign owner decides which fields the form asks for; whatever the player did not provide is simply absent from the payload. The only field guaranteed to be present is playerId.

game.ended / gameplay.finished

{
  "accountId": 3,
  "campaignId": 5,
  "type": "game.ended",
  "payload": {
    "gameDurationInSeconds": 10.123,
    "score": 100,
    "leaderboardName": "James Smith",
    "player": "{\"playerId\":\"627cc032cbff6f5f549e23b5\",\"email\":\"[email protected]\",\"phoneNumber\":\"555\",\"highestScore\":1,\"gameplayCount\":1}"
  }
}
FieldTypeOptional?Notes
gameDurationInSecondsnumberoptionalGame length. Some game types do not report duration.
scorenumberoptionalPlayer's score for this play. Absent for game types without a score.
leaderboardNamestringoptionalThe name the player entered on the leaderboard, if any.
playerstringrequired (see note)A JSON-encoded string describing the player. See The Embedded player Object for its contents.

player is always present, but if the play was anonymous (no registration captured) it may decode to an almost-empty object.

⚠️

player is a JSON-encoded string, not an object. You must JSON.parse(payload.player) to access its fields. This is for backwards-compatibility; new integrations should still parse it.

prize.assigned

Includes everything game.ended includes, plus three prize fields.

{
  "accountId": 3,
  "campaignId": 5,
  "type": "prize.assigned",
  "payload": {
    "gameDurationInSeconds": 10.123,
    "score": 300,
    "leaderboardName": "James Smith",
    "player": "{\"playerId\":\"627cc032cbff6f5f549e23b5\",\"email\":\"[email protected]\"}",
    "prizeId": "627cc032cbff6f5f549e23b5",
    "prizeTitle": "Prize 1",
    "prizeCode": "d7f53b7e-f1e7-4d16-bf8c-310357ff749c"
  }
}
FieldTypeOptional?Notes
prizeIdstringrequiredMinigames' stable id of the prize definition.
prizeTitlestringrequiredHuman-readable prize name.
prizeCodestringrequiredCode/voucher issued to this specific player for this prize.

The Embedded player Object

Inside game.ended, gameplay.finished, and prize.assigned, the player field is a JSON-encoded string. After JSON.parse(payload.player) you get an object. All of its fields are optional except playerId (present whenever the play was associated with a registered player).

FieldTypeNotes
playerIdstringMinigames' stable player id.
emailstring
phoneNumberstring
fullNamestring
firstNamestring
lastNamestring
codestring
termsAcceptedboolean
privacyPolicyAcceptedboolean
highestScorenumberPlayer's best score across the campaign so far.
gameplayCountnumberNumber of plays by this player in the campaign so far.
integrationUniqueIdstringOnly present when the campaign landing page was opened with an integrationUniqueId query parameter. Used as the player's unique identity for recognising returning players, instead of email/phone/cid matching.
cidstringOptimove customer id (when present).

As with the player.created payload, every field except playerId, highestScore, gameplayCount, integrationUniqueId, and cid is provided through the registration form. If your campaign's form doesn't ask for a field, that field won't appear here.

The form can also include custom ("extra") fields—anything your campaign asks for that isn't one of the standard fields above. Those custom fields appear directly on the same player object, at the same level as email, phoneNumber, etc. (not nested under an extra property). For example, if your campaign's form asks for a country field, the decoded player object will look like:

{
  "playerId": "627cc032cbff6f5f549e23b5",
  "email": "[email protected]",
  "country": "Latvia"
}
ℹ️

Empty strings and missing values are stripped—you will never see an email field set to an empty string.

Delivery Semantics

PropertyValue
MethodPOST
Schemehttps://
Content-Typeapplication/json
Timeout2 seconds. Endpoints that have not responded with a status code in 2s are treated as failed (timeout of 2000ms exceeded).
Retry on failureNone automatic. Failures are recorded; you can manually re-send any event from the Webhooks history.
OrderingNot guaranteed.
DuplicationAt-least-once is possible. Your endpoint should be idempotent.
History retention14 days. Older deliveries are removed automatically.

Authentication

There is no signature scheme (no HMAC, no timestamp challenge). The authentication model is a shared secret in a header you choose. When an authorization token is configured, every outbound webhook includes it in the Authorization header by default:

Authorization: <YOUR_TOKEN>

Because there is no signature, the only way to verify a request really came from Minigames is to compare the header against the secret you stored on your side. Treat the token like a password: never log it, and rotate it if you suspect leakage.

For where to set or generate the token (and to request a custom header name), see the How to Set Up Webhook Integration guide.

Designing Your Receiver

  1. Accept fast, process later. Acknowledge with 2xx as soon as the payload is validated and persisted. Do downstream work asynchronously.
  2. Be idempotent. Re-deliveries can happen. Use (type, payload.player.playerId), prizeCode, or your own dedupe key to ignore duplicates.
  3. Verify the auth header. Store the token as a secret and reject requests that do not match.
  4. Tolerate unknown fields. New optional fields may be added over time. Parse leniently.
  5. Always JSON.parse(payload.player) when reading game/prize events—it is a string by design.
  6. Don't trust ordering. Two events for the same play can arrive in either order. If you need a total ordering, persist events and reconcile.
  7. Handle missing optional fields. Most player fields are optional and depend on what the campaign collects.
  8. Pick the right "finished" signal. gameplay.finished is usually the right "experience complete" signal. Use game.ended only if you specifically need the game step. Don't subscribe to both without a reason.

Quick Reference

Event Triggers

EventFires when
segment.createdA new segment is created.
segment.updatedA segment is updated (title or connected Campaign ID changes).
segment.deletedA segment is deleted.
player.createdA unique player registers for the first time in a campaign.
player.updatedAn existing player re-registers, or their profile data changes.
game.endedThe game portion of a campaign completes.
gameplay.finishedThe player reaches the final screen of the campaign.
prize.assignedA prize is awarded to the player and a code is issued.

Limits & Guarantees

PropertyValue
HTTP methodPOST
Required schemehttps://
Body content typeapplication/json
Delivery timeout2 seconds
Automatic retriesNone
Ordering guaranteesNone
Duplicate deliveriesPossible (manual or upstream re-send)
History retention14 days
Signature/HMACNone—shared secret in a custom header

Gating Checklist (if you're not receiving anything)

  1. Is your endpoint URL set?
  2. Is the Enable Webhooks master switch on?
  3. Is the specific event type activated in the events list?
  4. Is the campaign in question selected under "Campaigns that are sending webhooks"?
  5. If you use brand overrides—does the brand override for that campaign's brand have the event activated?
  6. Does your endpoint actually return 2xx within the delivery timeout?

If all six are yes, check the Webhooks history for the most recent attempt's error details.

For an overview of the full API & Webhook feature, see API & Webhooks: An Overview.