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 |
- Map your ad unit names to each network’s ad unit ids. See Ad unit mapping.
- 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. - The network calls Kasskeep. Kasskeep verifies, maps the ad unit and records the reward once.
- Your backend receives
ad.rewardand grants the reward.
The ad.reward event
Section titled “The ad.reward event”{ "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.
Deduplication
Section titled “Deduplication”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 |
In your backend
Section titled “In your backend”- Verify the signature, as for any event.
- Deduplicate by event id.
- Reject
environment: "test"in production. - Apply your own caps and rules. Kasskeep does not limit how many rewards a user gets.
custom_datacomes 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.