Use this skill when your backend needs to read or update RevenueCat state on Android. Covers the RevenueCat REST API (v1 subscribers endpoint, grant/revoke entitlements, attributes), secret vs public SDK API key usage, and why you do not build a receipt verification backend with RevenueCat.
72
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
You do not build a receipt verification server with RevenueCat. Your backend still has a role, but that role is consuming RevenueCat state, not validating Google Play purchase tokens.
RevenueCat's backend is the receipt verification server. When the Android SDK posts a purchase token, RevenueCat's backend:
purchases.subscriptionsv2.get or purchases.products.get against the Google Play Developer API.CustomerInfo to the SDK.Your Android app never calls the Google Play Developer API. Your server does not call it either.
Before writing any backend code, confirm these facts about your deployment:
app_user_id your SDK uses (the same identifier your auth system uses).If your app only gates features inside the client, you may not need a backend component at all. RevenueCat verifies CustomerInfo server side before it reaches the SDK, and EntitlementVerificationMode.INFORMATIONAL or .ENFORCED adds signature verification on the client. Serve premium content from a server only when you can verify entitlement on the server.
Map each backend responsibility to a RevenueCat mechanism.
| Use case | Mechanism | Notes |
|---|---|---|
| React to purchase, renewal, cancellation | Webhook receiver | RevenueCat posts normalized events; your server updates its own DB. |
| Check current entitlement for a user | GET /v1/subscribers/{app_user_id} | Secret API key in Authorization header. |
| Grant promotional access (support, refunds, comps) | POST /v1/subscribers/{app_user_id}/entitlements/{entitlement_id}/promotional | Server side only. |
| Revoke promotional access | POST /v1/subscribers/{app_user_id}/entitlements/{entitlement_id}/revoke_promotionals | Server side only. |
| Set subscriber attributes from server side data | POST /v1/subscribers/{app_user_id}/attributes | Useful for CRM fields the SDK does not know. |
| Bulk data export | RevenueCat data export | Scheduled exports to your warehouse. |
What your backend still owns:
What your backend does not own:
linkedPurchaseToken chain traversal.GET https://api.revenuecat.com/v1/subscribers/{app_user_id}
Authorization: Bearer sk_...
X-Platform: androidThe response body is the same CustomerInfo structure the Android SDK returns. Use it in a server side endpoint that gates premium API responses.
POST https://api.revenuecat.com/v1/subscribers/{app_user_id}/entitlements/{entitlement_id}/promotional
Authorization: Bearer sk_...
Content-Type: application/json
{"duration": "monthly"}Valid duration values include daily, three_day, weekly, monthly, two_month, three_month, six_month, yearly, lifetime. Use this for support workflows, never from the client.
val response = client.get("https://api.revenuecat.com/v1/subscribers/$appUserId") {
header("Authorization", "Bearer ${System.getenv("RC_SECRET_KEY")}")
header("X-Platform", "android")
}| Key | Where it lives | What it can do |
|---|---|---|
| Android public SDK key | Embedded in the Android app | Post purchases, fetch CustomerInfo for the current user. |
| Secret API key | Server environment variable only | Read any subscriber, grant or revoke promotionals, set attributes, bulk operations. |
Never ship the secret key in the Android APK, in a BuildConfig field, or in any client bundle. Rotate it if it leaks. Treat it like a database password.
post("/revenuecat/webhook") {
val auth = call.request.header("Authorization")
require(auth == "Bearer ${System.getenv("RC_WEBHOOK_SECRET")}")
val event = call.receive<RevenueCatEvent>()
when (event.type) {
"INITIAL_PURCHASE", "RENEWAL" -> grantAccess(event.appUserId, event.entitlements)
"CANCELLATION", "EXPIRATION" -> scheduleRevocation(event.appUserId)
}
call.respond(HttpStatusCode.OK)
}Verify the authorization header you configured in the RevenueCat dashboard. Respond 2xx fast; RevenueCat retries on non 2xx responses.
CustomerInfo.entitlements.active or webhook events instead.ccfc038
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.