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}/prizesshows 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.
application/json- 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"payment.updated""raffle.live""raffle.closed""raffle.drawn""prize.won""raffle.cancelled""refund.sent"data*Acknowledged.
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": "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 } }}