Setup
RevenueCat dashboard → Project → Integrations → Webhooks → New webhook:
| Field | Value |
|---|---|
| Webhook URL | the app-specific URL shown in the ActivationPal setup checklist |
| Environment | Production |
| Event types | all |
Enable HMAC webhook signing, then paste and save the signing secret in the ActivationPal setup checklist (also available in app settings). The secret is encrypted at rest and is never returned after saving. The checklist shows secret saved until a production event arrives; app tracking and RevenueCat delivery are verified separately. ActivationPal verifies X-RevenueCat-Webhook-Signature against the untouched request body and rejects later cross-app mismatches.
Use one webhook per store application. If a product ships separately on iOS and Android, create two ActivationPal apps and scope the matching RevenueCat webhook to each store app. The client SDK's ap_pk_... key is only for event ingest and must not be used as webhook authentication.
What arrives
Each supported lifecycle event is stored as rc_ + the lowercased RevenueCat type, with its provider fields in props:
rc_initial_purchase, rc_renewal, rc_cancellation, rc_uncancellation, rc_expiration, rc_billing_issue, rc_non_renewing_purchase, rc_product_change, rc_subscription_paused, rc_subscription_extended, rc_refund_reversed, rc_transfer
Dashboard semantics:
- Trial start =
rc_initial_purchasewithperiod_type: "TRIAL"— price 0, counted as a trial, not revenue. - Trial conversion =
rc_renewalwithis_trial_conversion: true— counted as new-subscriber revenue, not a renewal. - Refund =
rc_cancellationwithcancel_reason: "CUSTOMER_SUPPORT". - One-time purchase =
rc_non_renewing_purchase. - Transfer =
rc_transfer—transferred_from/transferred_toarrays, attributed to the receiving user. - Revenue on every surface = sum of positive
priceprops onrc_*events (gross).
Each event is stamped with the last device that reported the same user id (or an alias) via the SDK — that places purchases on user timelines and city-level geo. RevenueCat's event id is stored uniquely: webhook retries never double-count. Net revenue is derived from RevenueCat's tax and commission estimates when available.
Coding-agent responsibilities
Install the SDK, instrument onboarding/paywall events and 5–10 product events, and use the RevenueCat app user ID to join both sources. Verify SDK delivery separately from revenue delivery. The user creates the webhook and saves its signing secret in the setup checklist; SDK delivery alone does not complete revenue setup. Never put the webhook signing secret in app code, logs, or Git. Keep the complete webhook URL unchanged.
Gotchas
- SANDBOX events are stored
env=debug, outside release numbers — set the environment to Production. Test purchases withpaywall_purchasedfrom a DEBUG build instead. - No
userId, no join:rc_*events still arrive and total correctly, but user timelines and funnel-to-revenue joins stay empty. - Rotating the SDK API key (apps.md) does not affect the webhook. Rotate the signing secret in RevenueCat and ActivationPal together.
- ActivationPal returns non-2xx for invalid or transiently failed deliveries so RevenueCat can retry them.
Verify
After a production purchase (or the next real renewal): dashboard live feed, or with an agent API key (agent-api.md):
curl -s "https://activationpal.com/api/v1/get_events?app=myapp&source=revenuecat" \
-H "Authorization: Bearer $AP_KEY"