Skip to content

Rewarded ads overview

Kasskeep handles one layer of rewarded ads: proving that a user actually watched an ad to the end. It receives the ad network’s server-side reward callback, verifies it, deduplicates it and sends your backend an ad.reward event, signed and delivered exactly like purchase events.

Bidding and fill stay with your mediation platform. Daily caps, what to grant and whether to grant it stay in your backend.

Network Callback Verification
AdMob GET /v1/ads/admob/:app_id/ssv ECDSA signature with Google’s published keys
AppLovin MAX GET /v1/ads/applovin/:app_id/s2s sha1(event_id + Event Key)
Unity LevelPlay GET /v1/ads/levelplay/:app_id/s2s md5(timestamp + eventId + appUserId + rewards + privateKey), timestamp window, optional IP allowlist
  1. Map your ad unit names to each network’s ad unit ids. See Ad unit mapping.
  2. In the app, call Kasskeep.ads.showRewarded({ adUnit: "revive" }). The SDK passes the user id and parameters to your ad SDK so they come back in the server callback.
  3. The network calls Kasskeep. Kasskeep verifies, maps the ad unit and records the reward once.
  4. Your backend receives ad.reward and grants the reward.
{
"id": "evt_...",
"type": "ad.reward",
"created_at": "2026-11-06T08:00:01.000Z",
"app_user_id": "6f1c...",
"platform": "android",
"environment": "production",
"product_id": null,
"transaction_id": "9b3e1c6a-1f2d-4c0e-9a77-5d4f3b2a1c00",
"original_transaction_id": null, "purchased_at": null, "expires_at": null, "price_micros": null, "currency": null, "ownership": null,
"data": {
"app_user_id": "6f1c...",
"network": "applovin",
"ad_unit": "revive",
"network_ad_unit_id": "a1b2c3d4e5f60718",
"reward_type": "gems",
"reward_amount": 5,
"network_transaction_id": "9b3e1c6a-1f2d-4c0e-9a77-5d4f3b2a1c00",
"custom_data": "stage=3",
"environment": "production",
"occurred_at": "2026-11-06T08:00:00.000Z"
}
}

All ten data fields are always present (null when unknown). Top-level platform is ios or android when MAX sends it, null for AdMob and LevelPlay, and test in test mode. Rewards do not appear in the customer’s purchases or subscriptions.

Rewards are unique per app, network and network transaction id (AdMob transaction_id, MAX event_id, LevelPlay eventId). Retries return 200 {"outcome": "duplicate", "event_id": ...} and never create a second event. The event id is derived from the same key, so one view has one id however many callbacks arrive.

Callback responses:

Outcome Meaning
recorded First time, event created
duplicate Already recorded, same event_id
unmapped_ignored The ad unit is not mapped and the app rejects unmapped units
ignored Valid signature but no user id, for example the network’s console test
  1. Verify the signature, as for any event.
  2. Deduplicate by event id.
  3. Reject environment: "test" in production.
  4. Apply your own caps and rules. Kasskeep does not limit how many rewards a user gets.
  5. custom_data comes from the client. Use it to correlate (a level number, for example), never to decide the amount.

Recent rewards for a user are available from GET /v1/customers/:app_user_id/ad-rewards for display and support. Grant rewards from the webhook only.