Skip to main content

Rewards & fulfillment

From winning a prize to delivering it — claim, the transactional outbox, the dispatcher, and the signed n8n callback.

Claim → outbox (on_claim mode)

For instant + in-app channels (voucher_code/none) the task is enqueued (or delivered) at win time instead; the outbox row is always written in the same txn as the reward, so a delivery is never lost or duplicated.

Dispatcher drains the outbox

The dispatcher is multi-replica safe (SKIP LOCKED). Outcomes are also counted as the fulfillment_tasks_total{outcome} metric (delivered/awaiting/retry/dead).

n8n hand-off + signed callback

Admin operations

EndpointPurpose
GET /api/v1/admin/fulfillment/taskslist (filter status / campaign / prize)
POST /api/v1/admin/fulfillment/tasks/{id}/retryre-arm a failed/dead task
POST /api/v1/admin/rewards/{id}/fulfill · /revokemanual lifecycle control

Proven by make e2e-fulfillment (outbox + dispatcher + dead-letter/retry + HMAC callback).