Skip to main content
Version: 3.4 (Current)

Expo IAP

IAPKit - In-App Purchase Solution

Expo IAP is a powerful in-app purchase solution for Expo and React Native applications that conforms to the Open IAP specification. It provides a unified API for handling in-app purchases across iOS and Android platforms with comprehensive error handling and modern TypeScript support.

Built-in Purchase Verification with IAPKit

Expo IAP includes IAPKit integration out of the box — no extra dependencies required. Use verifyPurchaseWithProvider() to verify purchases server-side on both iOS and Android with a single API call. Just add your IAPKit API key to the config plugin and you're ready to go. See the Purchase Verification guide for details.

If you're shipping an app with expo-iap, we’d love to hear about it—please share your product and feedback in Who’s using Expo IAP?. Community stories help us keep improving the ecosystem.

Promotion

kstyled Logo

Compile-time CSS-in-JS for React Native

✨ Experience the next generation of styling with kstyled - a blazing-fast, fully type-safe CSS-in-JS solution with zero runtime overhead.

🚀 Explore kstyled →

Sponsors & Community Support

We're building the OpenIAP ecosystem—defining the spec at openiap.dev, maintaining OpenIAP for the shared type system, and shipping native SDKs such as openiap-apple and openiap-google. These modules power expo-iap, flutter_inapp_purchase, kmp-iap, and react-native-iap. After simplifying fragmented APIs, the next milestone is a streamlined purchase flow: initConnection → fetchProducts → requestPurchase → (server purchase verification) → finishTransaction.

Your sponsorship keeps this work moving—ensuring more developers across platforms, OS, and frameworks can implement IAPs without headaches while we expand to additional plugins and payment systems. Sponsors receive shout-outs in each release and, depending on tier, can request tailored support. If you’re interested—or have rollout feedback to share—you can view sponsorship options at openiap.dev/sponsors.

📚 Guides

🚀 Quick Start

Installation

Install the package using your favorite package manager:

npm install expo-iap

1. Basic Setup

First, import and initialize the IAP hook:

import {useIAP} from 'expo-iap';

function MyStore() {
const {
connected,
products,
fetchProducts,
requestPurchase,
finishTransaction,
} = useIAP({
onPurchaseSuccess: async (purchase) => {
console.log('Purchase successful:', purchase);

// IMPORTANT: Verify receipt on your backend before finishing transaction
const isValid = await verifyReceiptOnServer(purchase);

if (isValid) {
await finishTransaction({purchase, isConsumable: true});
}
},
onPurchaseError: (error) => {
console.error('Purchase failed:', error);
},
});

const productIds = ['your.product.id', 'your.premium.subscription'];
}

2. Fetch Products

Load your products when the store connects:

useEffect(() => {
if (connected) {
// Fetch your products
fetchProducts({skus: productIds, type: 'in-app'});
}
}, [connected]);

3. Display Products

Show available products to users:

return (
<View>
<Text>Store Status: {connected ? 'Connected' : 'Connecting...'}</Text>

{products.map((product) => (
<View key={product.id} style={styles.productItem}>
<Text style={styles.productTitle}>{product.title}</Text>
<Text style={styles.productPrice}>{product.displayPrice}</Text>
<Button title="Buy Now" onPress={() => handlePurchase(product.id)} />
</View>
))}
</View>
);

4. Handle Purchases

Process purchase requests with our new platform-specific API (v2.7.0+):

const handlePurchase = async (productId: string) => {
try {
await requestPurchase({
request: {
apple: {
sku: productId,
},
google: {
skus: [productId],
},
},
});
} catch (error) {
console.error('Purchase failed:', error);
}
};

No more Platform.OS checks! The new API automatically handles platform differences. iOS can only purchase one product at a time, while Android supports purchasing multiple products in a single transaction.

5. Complete Transactions

Finish purchases in the success callback:

const {connected, products, fetchProducts, requestPurchase, finishTransaction} =
useIAP({
onPurchaseSuccess: async (purchase) => {
try {
console.log('Purchase completed:', purchase.id);

// IMPORTANT: Verify receipt on your backend before finishing transaction
const isValid = await verifyReceiptOnServer(purchase);

if (!isValid) {
console.error('Purchase verification failed');
return;
}

// Grant the purchase to user here
await grantPurchaseToUser(purchase);

// Finish the transaction
await finishTransaction({
purchase,
isConsumable: true, // Set based on your product type
});
} catch (error) {
console.error('Failed to complete purchase:', error);
}
},
onPurchaseError: (error) => {
console.error('Purchase failed:', error);
},
});

Complete Example

For a complete working implementation, see example/app/purchase-flow.tsx.

🏗️ Architecture

Expo IAP is built with a modern architecture that emphasizes:

  • Type Safety: Comprehensive TypeScript definitions for all APIs
  • Error Resilience: Centralized error handling with meaningful error codes
  • Platform Abstraction: Unified API that handles platform differences internally
  • Performance: Optimized for minimal bundle size and runtime performance

📱 Platform Support

PlatformSupportNotes
iOSStoreKit 1 & 2 (StoreKit 2 requires iOS 15+)
AndroidGoogle Play Billing v5+
Expo Go⚠️Limited (requires custom development client)
Expo Dev ClientFull support
Bare React NativeFull support

🎯 What's Next?

📦 Setup & Configuration

🔧 Implementation

📚 Guides

🛠️ Advanced Topics

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

📝 License

This project is licensed under the MIT License - see the LICENSE file for details.