Instant-Win Integration#

This guide describes how an external partner integrates an instant-win promotion with Evolu through the headless Integrators API.

Model: who decides the win?#

Evolu's instant-prize mechanic can run in two modes:

ModeWho decides the winnerThis guide
WINDOWEvolu draws via time-gated prize windows.
INTEGRATOR_DECLAREDThe integrator decides wins externally and registers them in Evolu via the API.

In INTEGRATOR_DECLARED mode the partner runs the entire instant-win logic on their side. Evolu is a compliance ledger: it records each entry, the declared win, the prize, and the lifecycle webhooks — but it never decides who wins.

Prerequisites#

Before integrating, the campaign operator must, in Evolu Studio:

  1. Set the instant-prize mechanic to integrator-declared mode.
  2. Register the prizes in the campaign's prize pool. Every win you register references a prize by its prize_definition_id — prizes must exist beforehand.
  3. Enable the campaign for the API channel and issue you an API key (live + test).

The happy path#

The integrator creates an entry with the win included in the payload, then waits for Evolu's webhooks as the entry is processed and evaluated.

Step 1 — Create the entry with the win#

POST /v1/entries with the participant enrollment, LGPD consent, the fiscal evidence, and an instant_win block carrying the outcome you decided:

{  "enrollment": { "...": "..." },  "consent": { "...": "..." },  "evidence": { "...": "..." },  "instant_win": { "won": true, "prize_definition_id": "0190559e-cc00-7a00-bc00-1a2b3c4d5e6f" }}

For a participant who did not win, send "instant_win": { "won": false }. Evolu replies 202 Accepted with an entry_id; the entry is PENDING and processed asynchronously. The declared win is held and confirmed later, during evaluation.

To discover valid prize_definition_id values, call GET /v1/prizes — it lists the campaign's pool (scoped to your key's mode) with each prize's remaining current_stock.

Step 2 — React to the webhooks#

Evolu delivers lifecycle webhooks (HMAC-signed) to your configured endpoint:

EventWhenMeaning
entry.receivedImmediately, for accepted entriesThe entry is being processed.
entry.completedAfter the entry phaseThe entry is APPROVED or REJECTED.
entry.evaluatedAfter the evaluation phase (only if approved)Carries the confirmed instant-win outcome.

Outcomes#

What you receive depends on whether the entry survives processing and whether you declared a win.

A win only stands if the entry is approved

If the entry is rejected during processing (e.g. an invalid fiscal key, fraud), the declared win is voided and you only receive entry.completed with status: REJECTED — there is no entry.evaluated.

The entry.evaluated payload#

For an approved entry, entry.evaluated echoes the win back so your system can reconcile:

{  "event_type": "entry.evaluated",  "data": {    "entry_id": "01905a3b-7c8d-7f00-a1b2-c3d4e5f6a7b8",    "enrollment_id": "0190559e-aa00-7a00-bc00-1a2b3c4d5e6f",    "mechanics": [      {        "mechanic_type": "instant_prize",        "status": "APPROVED",        "outcome": {          "won": true,          "prize_definition_id": "0190559e-cc00-7a00-bc00-1a2b3c4d5e6f",          "prize_name": "R$ 50 Voucher",          "award_status": "AWARDED"        }      }    ]  }}

For a declared loss, status is REJECTED and outcome is { "won": false }.

The award lifecycle#

Corrections: revoke & reassign#

Both correction endpoints are synchronous — they return 200 with the new state and do not emit a webhook (you initiated the change, so you already know the result).

Revoke#

POST /v1/entries/{entry_id}/instant-prize/revoke — marks the award revoked and returns its unit to the prize pool. Use it when a win must be cancelled (e.g. fraud found after the fact).

Reassign#

POST /v1/entries/{entry_id}/instant-prize/reassign — atomically revokes a win and re-registers it:

  • Same entry, different prize — omit target_entry_id; only the prize changes.
  • Move to another entry — set target_entry_id. The target entry must belong to the same campaign and have finished processing (be APPROVED).

Endpoint reference#

EndpointPurpose
GET /v1/prizesList the campaign's prize pool + remaining stock.
POST /v1/entriesCreate the entry, with the win in the instant_win block.
POST /v1/entries/{entry_id}/instant-prize/revokeRevoke a win.
POST /v1/entries/{entry_id}/instant-prize/reassignMove a win to another entry / prize.

All endpoints require the Authorization: Bearer <api_key> header. The full request and response schemas are in the Instant Prize and Entries references.

Rules & edge cases#

  • The win is part of the entry. It is declared in the instant_win block of POST /v1/entries — recorded atomically with the entry, so there is no submit-timing race. There is no separate "submit win" endpoint.
  • Prizes are pre-registered. prize_definition_id must reference a prize already in the campaign's pool (see GET /v1/prizes). Unknown prizes are rejected with 422.
  • Test vs live. The API key's mode (test/live) is the entry's mode. A test-mode key can only act on test-mode entries — and sees only test-mode prizes.
  • Prize stock. GET /v1/prizes reports current_stock. A confirmed win decrements it; a revoke or reassign returns the unit. Evolu records the integrator's decision — it does not block a win when the pool is empty, so current_stock may reach zero.
  • Losses are optional but supported. "instant_win": { "won": false } produces an entry.evaluated with instant_prize REJECTED — useful for explicit confirmation of non-winning entries. Omit instant_win entirely and the entry simply has no instant_prize mechanic in entry.evaluated.