Webhooks — the events FlipKey.gg sends your backend
Set your webhook URL and grab your webhook secret on the
Webhooks page. Every delivery is a JSON POST signed
with X-FlipKey-Signature = HMAC-SHA256(rawBody, webhook_secret) — verify it
against the raw request body before trusting anything (the SDKs do this for you;
in Express that means express.raw() on the webhook route, not
express.json()).
Delivery & retries
Respond 2xx to acknowledge. Anything else is retried with backoff, so make
your handler idempotent on the event's id field — a duplicate delivery must
not double-grant. Deliveries that keep failing park in a dead-letter state and we alert you
(at most one email an hour). The Webhooks page has a Send test button that
fires a signed test event at your endpoint.
Event: item_ticket.redeem — grant an item
Fires when a player redeems (burns) an item ticket — giveaway rewards, watch-drop rewards, purchased items. This is the moment you grant the item in-game.
{
event: "item_ticket.redeem",
redemption_id, // idempotency key
reward_drop_id, // which item to grant
item_name,
flipkey_account_id, // stable account key — map to your player
wallet_address, // same value
amount, // units (1)
burn_tx_hash, // on-chain burn of the consumed ticket
connected: true // connection is a redeem precondition
}
Ack fulfillment (optional but recommended):
POST /api/item-tickets/handoff/ack with
{ redemption_id, receipt } and your API key — it flips the redemption to
fulfilled in your dashboard. The
Watch-Drop Handoff SDK verifies, parses, and acks in
a few lines.
Key Station Plus test
Freebies, items you sell, creator giveaways and watch-drops need your backend to grant the item, so they unlock
once you pass the Plus test on the Key Station page. It sends an
item_ticket.redeem with test: true and a redemption_id starting
plustest_. Don't grant anything for it: verify the signature and ack that redemption_id
through POST /api/item-tickets/handoff/ack with your API key within 15 minutes. The Watch-Drop SDK
v0.2+ does this for you.
Event: purchase — token mirror
Fires at every license sale mint so your backend can mirror
token_id → drop for redemption lookups. Payload:
{ contract_address, token_id, flipkey_drop_id, platform, region, minted_at }.
The Publisher Starter backend handles this out of the box.
Event: freebie.revoked — take back a free bonus
Fires when a license refund settles after the buyer redeemed and received the campaign freebie: a refund you approved, a chargeback, or a Stripe-side refund of a redeemed purchase. FlipKey burns the freebie token if the player still holds it; this event is your cue to remove the in-game item you granted.
{
event: "freebie.revoked",
order_ref,
license_token_id,
freebie_id, // your catalog entry
freebie_token_id,
wallet, // the player to un-grant
reason, // "publisher_refund" | "chargeback" | "stripe_refund"
burned_on_chain, // false = the player already consumed it in-game, or the burn failed
burn_tx_hash,
revoked_at
}
Event: item.revoked — take back a paid item
Fires when the payment behind a paid item ticket is reversed: a chargeback, or a refund you issued
from your Stripe dashboard. FlipKey burns the item token if the player still holds it, so
gate.check stops granting on its own; this event is your cue to remove anything the game
already handed out for it.
{
event: "item.revoked",
order_ref,
flipkey_drop_id, // the item listing
token_id,
wallet, // the player to un-grant
reason, // "chargeback" | "stripe_refund"
burned_on_chain, // false = the player already consumed it in-game, or the burn failed
burn_tx_hash,
revoked_at
}
Event: creator_statements.issued — creator program run
Fires after every creator-program statement run (scheduler or manual) that issued at least one statement. Use it to refresh the earnings page on your own site, or to kick off payouts on your rail — FlipKey computes the numbers and never moves the money.
{
event: "creator_statements.issued",
period_start, period_end, // YYYY-MM-DD
run_kind, // "auto" (scheduler) | "manual"
statements: [{
public_id, // cs-YYYYMM-… — fetch lines via GET /api/creator-program/statements/:public_id
creator_id, creator_name,
status, // "finalized" (pay it) | "carried" (under your minimum, rolls forward)
payable_cents // may be negative after refunds — carries to the next statement
}]
}
Pull the white-label version for your site with
GET /api/creator-program/export?period=YYYY-MM, and close a statement once paid with
POST /api/creator-program/statements/:public_id/paid { paid_ref }.
Treat your webhook secret like a password — anyone holding it can forge grant events at your endpoint.