Skip to main content

Overview

Flex integrates with RevenueCat to help you manage subscriptions seamlessly across platforms. This guide walks you through connecting your RevenueCat account to Flex, passing a stable customer identifier, saving the integration, and understanding how events map between systems.

Installation Guide

1

Add RevenueCat in Flex

Log in to your Flex Dashboard.Go to Integrations → RevenueCat.Enter your RevenueCat App ID and API Key.
  • You can find these in your RevenueCat project under App Settings. Flex Dashboard → Integrations page with RevenueCat selected
2

Configure in RevenueCat

In your RevenueCat project, open the Apps section.Click + Add and select Other payment provider.Copy your App ID and Secret API Key.Paste these values into the Flex Dashboard RevenueCat fields from Step 1.RevenueCat “Apps” page showing Other Payment Provider selectedRevenueCat “Apps” page showing Other Payment Provider selected
If you don’t see “Other payment provider (External source)” in your RevenueCat Apps page, that option may not be enabled for your project.Please contact RevenueCat Support and ask them to enable the External payment provider integration for your project.Include:
  • Your Project ID / link
  • The App name
  • That you want to connect Flex as the external payment provider
3

Pass a Custom User Identifier to RevenueCat

If you want RevenueCat to reference your own user ID (or a Flex user ID), include it in the checkout session metadata as REVENUE_CAT_CUSTOMER_ID.
4

Save and Sync

Click Save in the Flex Dashboard integration page.Flex will begin sending subscription events to RevenueCat so customer status stays in sync.
Tip: If you have existing subscriptions, run an initial sync (or perform a backfill) so historical subscriptions are recognized in RevenueCat.

How Flex Integrates with RevenueCat

There are two ways subscriptions can flow into RevenueCat:

Native Stripe Integration

Stripe sends webhooks directly to RC. RC processes them and generates events with store: "STRIPE".

Flex External Purchases API

Flex processes payments via Stripe, then syncs subscription state to RC via the External Purchases API (POST /v1/receipts/external). RC generates events with store: "EXTERNAL".
For Flex-managed subscriptions, all events come through the External Purchases API path. The subscription data is accurate and revenue is correctly tracked — but certain webhook fields have different values than a native Stripe integration would produce.
If you’re migrating from a native Stripe → RevenueCat integration, be aware of these key differences:
  • store is "EXTERNAL", not "STRIPE" — update any webhook consumers that filter by store
  • Refund events have price: 0.0, never negative — use the RC Subscriber API or Flex API for refund amounts
  • expiration_reason is always null — use cancel_reason on preceding CANCELLATION events instead
  • Prorated refunds are invisible in webhooks — no CUSTOMER_SUPPORT event is generated; use Flex API to detect partial refunds
  • IDs use Flex format (fprod_, fsub_, fcus_) instead of Stripe format (prod_, si_, cus_) — treat all IDs as opaque strings
These differences are inherent to the RevenueCat External Purchases API and have been confirmed with the RevenueCat team (March 2026). Revenue is always accurately tracked inside RevenueCat — these differences only affect webhook payload fields.

Subscription Lifecycle Events

Flex syncs the following RevenueCat event types. This is the complete list — every event type that Flex sends to RC:
ProductChange (upgrades/downgrades) is not currently supported. All other subscription lifecycle events are fully implemented and synced in real-time.

Stripe Trigger Mapping

Each Flex RC sync event is triggered by a specific Stripe webhook event:

Event Sequences by Scenario

Both events appear as INITIAL_PURCHASE in RC webhooks. The first has price 0 and status trialing; the second has the actual price and status active.
If payment never recovers, the subscription eventually receives an EXPIRATION event when Stripe deletes it.
Subscription remains active until the current period ends. Access continues during this time.
Event #3 is the refund signal. In a native Stripe integration, price would be -179.99.WiththeExternalAPI,thepriceisalways179.99. With the External API, the price is always `0.00`. Revenue IS correctly adjusted inside RC — query the Subscriber API to confirm net revenue.
No CANCELLATION (CUSTOMER_SUPPORT) event is generated for prorated refunds. The refund is invisible in webhooks. Revenue is adjusted internally in RC. Use the Flex API or RC Subscriber API for refund details.
This fires when the billing period ends after a CancelAtPeriodEnd was set.

Field Reference

Every RC webhook event from Flex will have these field values:

Key Differences from Stripe-Native Integration

If your webhook consumer was originally built for a native Stripe → RevenueCat integration, the following differences apply when receiving events from Flex. These are inherent to the RevenueCat External Purchases API and have been confirmed with the RevenueCat team (March 2026).
These differences are not bugs. They are confirmed RevenueCat platform behavior for the External Purchases API. Flex sends all available data correctly; the External API simply exposes different fields than native integrations.

Refund Handling

Refund visibility in RC webhooks depends on the refund type and flow:

How to detect and measure refunds

Recommended: Use Flex webhooks for refund tracking (exact amounts and types) and RC webhooks for subscription lifecycle (active, canceled, expired, billing).

Recommendations for Webhook Consumers

Handling the store field

Accept events where store is either "STRIPE" or "EXTERNAL":

Detecting subscription state changes

Use the event type and cancel_reason to determine subscription state:

Handling refunds

1

Detect refund occurrence

Check for cancel_reason == "CUSTOMER_SUPPORT" on CANCELLATION events.
2

Do NOT rely on negative price

The price will always be 0.0 for External store events.
3

Get refund amounts

Use the Flex API or RC Subscriber API for exact refund amounts.
4

Handle prorated/custom refunds

No RC webhook event is generated for these — use Flex webhooks instead.

Handling expiration events

Accept expiration_reason: null. The External store does not populate this field. To determine why a subscription expired, look at the preceding CANCELLATION event’s cancel_reason.

ID formats

Treat all IDs as opaque strings. Do not parse, validate format, or assume a prefix:

Example Payloads

All payloads below are from real webhook captures in the RevenueCat sandbox.

FAQ

Flex uses RevenueCat’s External Purchases API to sync subscription data. RC automatically sets store to "EXTERNAL" for all events processed through this API. This is expected behavior, not a misconfiguration.
The External Purchases API does not expose payment amounts in the webhook price field. Flex sends the correct negative payment to RC, and revenue IS adjusted correctly inside RC. But the webhook event’s price field is derived from the subscription record, not the payment. This is a confirmed RevenueCat platform limitation (verified March 2026).
Three options:
  1. RC Subscriber API: GET /v1/subscribers/{app_user_id} — check total_revenue_in_usd
  2. Flex Webhooks: Use Flex’s own webhook events, which include exact refund amounts and types
  3. Flex API: Query the Flex API for subscription/refund details
RevenueCat only generates a CANCELLATION (CUSTOMER_SUPPORT) event for full refunds processed through the External API. Prorated and custom refunds adjust revenue internally but do not trigger a distinct webhook event. Use the Flex API or RC Subscriber API to detect partial refunds.
The External Purchases API does not have a mechanism to set the expiration reason. This field is only populated for native integrations (Apple, Google, Stripe). To determine why a subscription expired, check the cancel_reason on the preceding CANCELLATION event.
Yes. Revenue (including refund adjustments) is always accurate in RC. The differences are only in webhook event payloads, not in RC’s internal data. You can always query GET /v1/subscribers/{id} to get accurate revenue figures.
Yes. Flex syncs both TrialPurchase (trial start, $0 invoice) and TrialConversion (first real payment after trial). Both appear as INITIAL_PURCHASE in RC webhooks — differentiate by checking price (0.0 for trial start, positive for conversion).
Yes. When cancel_at_period_end is reversed, Flex sends an UndoCancelAtPeriodEnd event which appears as UNCANCELLATION in RC webhooks.
Yes. BillingIssue is sent when payment fails (status: in_grace_period, gives_access: true). BillingSucceeds is sent when payment recovers (same logic as Renewal).
These are inherent to the RevenueCat External Purchases API as of March 2026. If RC updates the External API to support additional fields, Flex will adopt them. This document will be updated accordingly.