Partners
WebhooksEvent reference

prize.won

One of your buyers won — your fulfilment handoff

This is the only handoff you get for a winner. When it arrives, present the buyback offer, and:

  • verity_collected: the prize token is already in the wallet that paid for the winning ticket when this event fires. The winner ships the prize themselves from their browser, by signing with that wallet against the Redemption endpoints below. Link them to your prizes page; GET /users/{externalUserRef}/prizes shows the state of each prize.
  • partner_collected: collect the shipping address yourself. No token is minted, and the Redemption endpoints refuse the prize.

When buyback.available is true, show amount_usd and expires_at, and call POST /raffles/{id}/prizes/{prizeId}/buyback on acceptance. It is false for partner winners today, with amount_usd and expires_at null; see the Buyback endpoint.

Request Body

application/json
  1. body

Every webhook uses this envelope.

Headers: x-verity-event: <event name> and x-verity-signature: <hex>.

The signature is HMAC-SHA256 of the exact raw body bytes with your webhook secret, hex encoded. Verify before parsing:

import { createHmac, timingSafeEqual } from "node:crypto";function verify(rawBody, header, secret) {  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");  const a = Buffer.from(expected), b = Buffer.from(header ?? "");  return a.length === b.length && timingSafeEqual(a, b);}

Respond 2xx to acknowledge. Non-2xx and timeouts are retried with backoff, so your handler must be idempotent. You only ever receive data about your own buyers.

event*string
Value in"payment.updated""raffle.live""raffle.closed""raffle.drawn""prize.won""raffle.cancelled""refund.sent"
data*

Response Body

Acknowledged.

Example Requests
POST/prize.won

Every webhook uses this envelope.

Headers: x-verity-event: <event name> and x-verity-signature: <hex>.

The signature is HMAC-SHA256 of the exact raw body bytes with your webhook secret, hex encoded. Verify before parsing:

import { createHmac, timingSafeEqual } from "node:crypto";function verify(rawBody, header, secret) {  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");  const a = Buffer.from(expected), b = Buffer.from(header ?? "");  return a.length === b.length && timingSafeEqual(a, b);}

Respond 2xx to acknowledge. Non-2xx and timeouts are retried with backoff, so your handler must be idempotent. You only ever receive data about your own buyers.

Request Body
application/json
{  "event": "prize.won",  "data": {    "raffle_id": 77,    "prize_id": 41,    "prize_name": "Rolex Submariner 124060",    "external_user_ref": "usr_8812",    "display_name": "alice",    "buyback": {      "available": false,      "amount_usd": null,      "expires_at": null    }  }}