What Is an In-App Purchase?
An in-app purchase (IAP) is any digital product or service a user buys inside a mobile application. Both Apple and Google require that digital goods sold within apps go through their respective billing systems. Physical goods, real-world services, and person-to-person payments are exempt from this requirement.
IAP revenue accounts for the majority of mobile app income worldwide. In 2025, global consumer spending on in-app purchases exceeded $170 billion across both platforms. Understanding IAP types, integration patterns, and validation flows is essential for any developer building a monetized app.
IAP Types
Consumable
Consumable purchases are items that get used up and can be bought multiple times. Examples include virtual currency packs, extra lives in games, or AI generation credits. Once consumed, the item is gone and the user can purchase it again.
Key characteristics:
- Not automatically restored on new devices
- Must be "finished" or "consumed" via API after delivery
- No receipt-based entitlement tracking needed long-term
Non-Consumable
Non-consumable purchases are permanent one-time purchases. Examples include removing ads, unlocking a pro feature, or purchasing a filter pack. Once bought, the user owns the item forever.
Key characteristics:
- Automatically restored on new devices via the store
- Must be available for restore at all times (Apple requires this)
- Good for lifetime unlock business models
Auto-Renewable Subscriptions
Subscriptions charge users on a recurring basis (weekly, monthly, quarterly, or yearly). They are the dominant monetization model for productivity, fitness, media, and SaaS apps.
Key characteristics:
- Managed entirely by the store's billing infrastructure
- Support free trials, introductory pricing, and promotional offers
- Require handling of expiration, renewal, and cancellation states
Non-Renewing Subscriptions
These provide access for a fixed period but do not automatically renew. The user must repurchase manually when the period ends. This type is less common and requires the developer to track expiration.
Integration Overview
Apple (StoreKit 2)
StoreKit 2, introduced in iOS 15 and refined through iOS 18, uses a modern Swift async/await API. Products are configured in App Store Connect and referenced by product IDs.
Basic flow:
- Fetch products using
Product.products(for:) - Call
product.purchase()to initiate the transaction - Verify the transaction using
Transaction.currentEntitlementsor JWS verification - Call
transaction.finish()to acknowledge delivery
StoreKit 2 returns signed JWS (JSON Web Signature) tokens that can be verified server-side without calling Apple's servers, although the App Store Server API provides additional capabilities.
Google (Play Billing Library 7)
Google Play Billing Library 7.x follows a similar pattern using Kotlin or Java APIs.
Basic flow:
- Connect to
BillingClient - Query products with
queryProductDetailsAsync() - Launch purchase flow with
launchBillingFlow() - Handle result in
PurchasesUpdatedListener - Verify and acknowledge with
acknowledgePurchase()orconsumeAsync()
Unacknowledged purchases are automatically refunded after 3 days.
Server-Side Validation
Client-side purchase verification alone is not secure. Users can modify device clocks, use jailbroken devices, or forge receipts. Server-side validation is strongly recommended for all IAP types.
Apple Server-Side
- App Store Server API v2: RESTful API with JWT authentication. Use
GET /inApps/v2/history/{transactionId}to look up transactions - App Store Server Notifications v2: Real-time webhooks for subscription events (renewals, cancellations, refunds)
- JWS Verification: StoreKit 2 transactions are signed JWS tokens verifiable with Apple's public certificate chain
Google Server-Side
- Google Play Developer API: Use
purchases.products.getfor one-time purchases andpurchases.subscriptionsv2.getfor subscriptions - Real-Time Developer Notifications (RTDN): Pub/Sub based webhooks for purchase and subscription events
- Voided Purchases API: Detects refunded or revoked transactions
Common Pitfalls
- Not finishing/acknowledging transactions: Leads to automatic refunds (Google) or repeated transaction delivery (Apple)
- Relying solely on client-side validation: Exposes the app to receipt fraud
- Not handling interrupted purchases: Network failures during purchase require proper recovery using pending transaction queues
- Ignoring price locale: Always display prices from the store API, never hardcode values
- Missing restore functionality: Apple rejects apps that lack a restore purchases button for non-consumables and subscriptions
Related Topics
- Auto-Renewable Subscriptions - Deep dive into subscription lifecycle management
- StoreKit 2 and Play Billing Guide - Platform-specific API implementation details
- IAP Sandbox Testing - How to test purchases without real money