Implementing In App Purchases With RevenueCat And Server Validation
Summary
Summary

This tutorial explains implementing Flutter In-App Purchases with RevenueCat and server validation. Initialize Purchases in the Flutter app, perform purchases and restores client-side, then use a secure server to call RevenueCat's subscribers endpoint to verify entitlements. Leverage webhooks, cache with short TTL, and keep API keys on the server for security.

This tutorial explains implementing Flutter In-App Purchases with RevenueCat and server validation. Initialize Purchases in the Flutter app, perform purchases and restores client-side, then use a secure server to call RevenueCat's subscribers endpoint to verify entitlements. Leverage webhooks, cache with short TTL, and keep API keys on the server for security.

Key insights:
Key insights:
  • Why Use RevenueCat For Flutter: Centralizes cross-platform subscription logic and reduces platform-specific code.

  • Client-Side Integration: Initialize purchases_flutter, fetch offerings, perform purchases, and send purchase metadata to your backend.

  • Server Validation With RevenueCat API: Validate entitlements server-side using GET /v1/subscribers/{appUserId} with a secret API key.

  • Testing, Webhooks, And Best Practices: Use sandbox testing, implement webhooks for real-time updates, and cache responses safely.

  • Security And Reliability: Keep API keys on the server, authenticate client calls, log and retry failures.

Introduction

This tutorial shows how to implement In-App Purchases (IAP) in a Flutter app using RevenueCat and perform server-side validation of subscriptions. RevenueCat centralizes receipt handling and cross-platform subscription logic; combining it with server validation lets your backend make authoritative entitlement decisions and reduces client-side attack surface. The examples are practical and focused on mobile development concerns: SDK init, purchase flow, server verification, webhooks, and security.

Why Use RevenueCat For Flutter

RevenueCat provides a single API and set of SDKs that abstract App Store and Google Play differences, handle subscription renewals, and expose entitlements. For Flutter apps this means less platform-specific code, faster iteration, and built-in analytics and webhooks. Use RevenueCat when you want reliable cross-platform subscription state with minimal maintenance and the ability to query subscriber state from your server.

Client-Side Integration

Add purchases_flutter to your pubspec and initialize the SDK with your public key (client-side key). Do not embed your RevenueCat secret (API key) in the app. Initialize early in app startup, fetch offerings, present products, and call purchase methods. Restore purchases on sign-in and app installs to recover entitlements.

Example Flutter initialization and purchase flow:

import 'package:purchases_flutter/purchases_flutter.dart';

await Purchases.configure(PurchasesConfiguration('PUBLIC_REVENUECAT_KEY'));
final offerings = await Purchases.getOfferings();
await Purchases.purchasePackage(offerings.current!.availablePackages.first);

After purchase, RevenueCat updates the purchaser info. On success, grant entitlement locally and send the purchase metadata (appUserId, storeReceipt, or purchase token) to your backend for validation and long-term storage.

Server Validation With RevenueCat API

Server validation means your backend queries RevenueCat (not the client) to determine whether a user has an active entitlement. Keep the RevenueCat REST API key (secret) only on your server. Use the Subscribers endpoint to fetch the canonical state for an appUserId. Your server should authenticate client requests (e.g., signed JWT or session cookie), then call RevenueCat and apply your business rules.

A minimal Dart server-side check using the public RevenueCat REST API looks like this:

import 'dart:convert';
import 'package:http/http.dart' as http;

Future<bool> isEntitled(String appUserId, String key, String entitlementId) async {
  final url = Uri.parse('https://api.revenuecat.com/v1/subscribers/$appUserId');
  final r = await http.get(url, headers: {'Authorization': 'Bearer $key'});
  final data = jsonDecode(r.body);
  return data['subscriber']?['entitlements']?[entitlementId]?['is_active'] == true;
}

On each protected API call your server should call this (or a cached variant with short TTL) to decide whether to grant access. Log failures and implement retries for transient errors.

Testing, Webhooks, And Best Practices

  • Test in sandbox environments (Apple Sandbox, Google Play test) and use RevenueCat sandbox mode for consistent results.

  • Use RevenueCat webhooks to receive real-time subscription events (initial purchase, renewal, cancellation, billing issue). Process webhooks on your server to update internal records and notify clients.

  • Cache subscriber responses for a short period (e.g., 30–60 seconds) to reduce latency and API usage, but invalidate cache on webhook events for correctness.

  • Handle edge cases: expired but grace-period subscriptions, billing retry windows, and restored purchases across devices. Always prefer server-state as canonical.

  • Secure the API key: store it in environment variables or a secrets manager. Never expose server API keys or secret tokens in the client.

Security checklist

  • Authenticate and authorize client calls to your backend.

  • Use HTTPS everywhere and validate server responses.

  • Rate-limit endpoints that call RevenueCat to protect against abuse.

Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.

Conclusion

Using RevenueCat with a Flutter client plus server-side validation gives you a robust, centralized approach to subscriptions and entitlements across iOS and Android. Initialize the SDK in the app, perform purchases with the client SDK, then verify and cache subscriber state on your server via RevenueCat's REST API and webhooks. Follow security best practices: keep secret keys on the server, use authenticated requests, and treat server state as the single source of truth for granting access in your mobile development workflow.

Introduction

This tutorial shows how to implement In-App Purchases (IAP) in a Flutter app using RevenueCat and perform server-side validation of subscriptions. RevenueCat centralizes receipt handling and cross-platform subscription logic; combining it with server validation lets your backend make authoritative entitlement decisions and reduces client-side attack surface. The examples are practical and focused on mobile development concerns: SDK init, purchase flow, server verification, webhooks, and security.

Why Use RevenueCat For Flutter

RevenueCat provides a single API and set of SDKs that abstract App Store and Google Play differences, handle subscription renewals, and expose entitlements. For Flutter apps this means less platform-specific code, faster iteration, and built-in analytics and webhooks. Use RevenueCat when you want reliable cross-platform subscription state with minimal maintenance and the ability to query subscriber state from your server.

Client-Side Integration

Add purchases_flutter to your pubspec and initialize the SDK with your public key (client-side key). Do not embed your RevenueCat secret (API key) in the app. Initialize early in app startup, fetch offerings, present products, and call purchase methods. Restore purchases on sign-in and app installs to recover entitlements.

Example Flutter initialization and purchase flow:

import 'package:purchases_flutter/purchases_flutter.dart';

await Purchases.configure(PurchasesConfiguration('PUBLIC_REVENUECAT_KEY'));
final offerings = await Purchases.getOfferings();
await Purchases.purchasePackage(offerings.current!.availablePackages.first);

After purchase, RevenueCat updates the purchaser info. On success, grant entitlement locally and send the purchase metadata (appUserId, storeReceipt, or purchase token) to your backend for validation and long-term storage.

Server Validation With RevenueCat API

Server validation means your backend queries RevenueCat (not the client) to determine whether a user has an active entitlement. Keep the RevenueCat REST API key (secret) only on your server. Use the Subscribers endpoint to fetch the canonical state for an appUserId. Your server should authenticate client requests (e.g., signed JWT or session cookie), then call RevenueCat and apply your business rules.

A minimal Dart server-side check using the public RevenueCat REST API looks like this:

import 'dart:convert';
import 'package:http/http.dart' as http;

Future<bool> isEntitled(String appUserId, String key, String entitlementId) async {
  final url = Uri.parse('https://api.revenuecat.com/v1/subscribers/$appUserId');
  final r = await http.get(url, headers: {'Authorization': 'Bearer $key'});
  final data = jsonDecode(r.body);
  return data['subscriber']?['entitlements']?[entitlementId]?['is_active'] == true;
}

On each protected API call your server should call this (or a cached variant with short TTL) to decide whether to grant access. Log failures and implement retries for transient errors.

Testing, Webhooks, And Best Practices

  • Test in sandbox environments (Apple Sandbox, Google Play test) and use RevenueCat sandbox mode for consistent results.

  • Use RevenueCat webhooks to receive real-time subscription events (initial purchase, renewal, cancellation, billing issue). Process webhooks on your server to update internal records and notify clients.

  • Cache subscriber responses for a short period (e.g., 30–60 seconds) to reduce latency and API usage, but invalidate cache on webhook events for correctness.

  • Handle edge cases: expired but grace-period subscriptions, billing retry windows, and restored purchases across devices. Always prefer server-state as canonical.

  • Secure the API key: store it in environment variables or a secrets manager. Never expose server API keys or secret tokens in the client.

Security checklist

  • Authenticate and authorize client calls to your backend.

  • Use HTTPS everywhere and validate server responses.

  • Rate-limit endpoints that call RevenueCat to protect against abuse.

Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.

Conclusion

Using RevenueCat with a Flutter client plus server-side validation gives you a robust, centralized approach to subscriptions and entitlements across iOS and Android. Initialize the SDK in the app, perform purchases with the client SDK, then verify and cache subscriber state on your server via RevenueCat's REST API and webhooks. Follow security best practices: keep secret keys on the server, use authenticated requests, and treat server state as the single source of truth for granting access in your mobile development workflow.

Build Flutter Apps Faster with Vibe Studio

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Other Insights

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025