How to Let Users Manage or Cancel a Subscription

Overview

RevenueCat cannot cancel a subscription for the user. Cancellations and plan changes always happen on the store side (the App Store or Google Play). Your job is to send the user to the correct management screen. There are two ways to do this:

  • iOS (native): showManageSubscriptions() presents the App Store manage subscriptions sheet directly inside your app.
  • Cross-platform: customerInfo.managementURL is a URL you open yourself. This is the approach to use on Android and React Native, where there is no native manage screen method.
Prerequisites: The RevenueCat SDK must already be installed and configured with Purchases.configure(...). See the iOS codelab and the Configure the SDK guide for setup. You also need a way to fetch CustomerInfo; see Get CustomerInfo.

iOS: showManageSubscriptions() (Native)

On iOS, RevenueCat exposes a native helper that opens the App Store manage subscriptions sheet without you having to build or open a URL. Call it from a Restore or Manage Subscription button:

swift
import RevenueCat

func openManageSubscriptions() async {
    do {
        // Presents the native App Store manage subscriptions sheet.
        try await Purchases.shared.showManageSubscriptions()
    } catch {
        print("Could not open manage subscriptions: \(error.localizedDescription)")
    }
}

From SwiftUI you can call it from a button action:

swift
Button("Manage Subscription") {
    Task {
        do {
            try await Purchases.shared.showManageSubscriptions()
        } catch {
            print("Manage subscriptions failed: \(error)")
        }
    }
}
iOS only. showManageSubscriptions() presents the App Store sheet and is specific to the iOS SDK. On Android and React Native, use managementURL instead (covered below). The Android SDK does not provide a native manage subscriptions method.

Cross-platform: customerInfo.managementURL

Every CustomerInfo object carries a managementURL property. This URL points to the store's subscription management page: the App Store page for App Store subscriptions, and the Google Play page for Google Play subscriptions. You fetch CustomerInfo with getCustomerInfo() and then open the URL yourself with the platform's standard URL opener.

This is the right approach when:

  • You are on Android, where there is no native manage screen method.
  • You are on React Native, where you open the URL with Linking.
  • You want a single code path that works the same way across stores.
managementURL can be null. It is null when there is no active store subscription to manage, or when the active subscription was purchased on a different platform than the current device. Always check for null before opening it. See the When managementURL is null section.

React Native: Open managementURL with Linking

Fetch CustomerInfo with getCustomerInfo(), then open managementURL with React Native's Linking API. Guard against a null URL first:

typescript
import { Linking } from 'react-native';
import Purchases from 'react-native-purchases';

async function openManageSubscriptions() {
  try {
    const info = await Purchases.getCustomerInfo();
    if (info.managementURL) {
      await Linking.openURL(info.managementURL);
    } else {
      // No active store subscription to manage on this platform.
      console.log('No management URL available.');
    }
  } catch (e) {
    console.log('Failed to open manage subscriptions', e);
  }
}

In a component, wire it to a button and disable the button when there is nothing to manage:

tsx
import { useEffect, useState } from 'react';
import { Button, Linking } from 'react-native';
import Purchases from 'react-native-purchases';

export function ManageSubscriptionButton() {
  const [managementURL, setManagementURL] = useState<string | null>(null);

  useEffect(() => {
    Purchases.getCustomerInfo().then((info) => {
      setManagementURL(info.managementURL);
    });
  }, []);

  return (
    <Button
      title="Manage Subscription"
      disabled={!managementURL}
      onPress={() => {
        if (managementURL) Linking.openURL(managementURL);
      }}
    />
  );
}

Android: Open managementURL with an Intent

The RevenueCat Android SDK does not have a native showManageSubscriptions method. Instead, read customerInfo.managementURL and open it with a standard ACTION_VIEW intent, which routes to the Google Play subscription management page:

kotlin
import android.content.Intent
import android.net.Uri
import com.revenuecat.purchases.Purchases
import com.revenuecat.purchases.getCustomerInfoWith

fun openManageSubscriptions(context: Context) {
    Purchases.sharedInstance.getCustomerInfoWith(
        onError = { error ->
            Log.e("Purchases", "Could not load CustomerInfo: ${error.message}")
        },
        onSuccess = { customerInfo ->
            val url = customerInfo.managementURL
            if (url != null) {
                val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url.toString()))
                context.startActivity(intent)
            } else {
                // No active subscription to manage on this device.
                Log.d("Purchases", "managementURL is null")
            }
        }
    )
}

With coroutines you can use the suspend variant awaitCustomerInfo() instead:

kotlin
lifecycleScope.launch {
    try {
        val customerInfo = Purchases.sharedInstance.awaitCustomerInfo()
        val url = customerInfo.managementURL
        if (url != null) {
            startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url.toString())))
        } else {
            showMessage("No subscription to manage on this device.")
        }
    } catch (e: PurchasesException) {
        Log.e("Purchases", "Failed to load CustomerInfo: ${e.message}")
    }
}

When the Management URL is null

managementURL is not always present. Handle these cases so your UI never tries to open a missing URL:

Situation managementURL
Active store subscription on the current platform A URL to the store management page
No active store subscription to manage null
Subscription purchased on a different platform null
Cross-platform purchases. If a user subscribed on the App Store but is currently running your Android app (or vice versa), managementURL will be null on the current device because the store on this device cannot manage a subscription bought elsewhere. In that case, tell the user to manage the subscription from the original store, or link to the store's generic subscription settings page.
Hide or disable the button. When managementURL is null and, on iOS, the user has no manageable subscription, hide or disable the manage button rather than showing an error. The URL points to the App Store or Google Play page depending on where the subscription was purchased, so there is nothing to open when it is absent.

FAQ

How do I open the manage subscriptions screen on iOS?
Call try await Purchases.shared.showManageSubscriptions(). It presents the native App Store manage subscriptions sheet where the user can change or cancel their plan.

Does React Native have a showManageSubscriptions method?
No. The native showManageSubscriptions() helper is part of the iOS SDK. On React Native and Android, open customerInfo.managementURL instead. On React Native that means Linking.openURL(info.managementURL).

Can RevenueCat cancel a subscription for me?
No. Cancellations always happen on the store (App Store or Google Play). RevenueCat only sends the user to the correct management page, either through showManageSubscriptions() on iOS or through managementURL elsewhere.

Why is managementURL null?
Because there is no active store subscription to manage, or because the active subscription was bought on a different platform than the current device. Check for null and hide the manage button when it is missing.

Related Guides