Validate Apple App Store purchases

This guide shows you how to set up and validate Apple App Store purchases and subscriptions with Nakama.

Before you begin #

Make sure you have:

  • An Apple Developer account with access to App Store Connect
  • An iOS app configured for in-app purchases in App Store Connect
  • Nakama v3.37.0 or later if using StoreKit 2

How Apple validation works #

Nakama sends Apple purchase receipts to Apple for validation. Following Apple’s recommendations, it uses both Production and Sandbox servers to validate receipts.

Apple receipts can contain multiple purchases. Nakama validates all of them and stores them as individual purchase records. Nakama only supports validating iOS 7+ receipts.

StoreKit 1 and StoreKit 2 #

Nakama supports both StoreKit 1 (legacy) and StoreKit 2 receipts through the same validation API. The receipt type your app sends depends on which version of the Apple SDK your client uses.

SettingStoreKit 1 (legacy)StoreKit 2
Validation methodApp-specific shared secretPKI (no shared secret needed)
Receipt formatBase64-encoded receiptJWS-signed transaction
Nakama config requiredYes, set iap.apple.shared_passwordNo

If you set the shared secret in Nakama, it’s used only for StoreKit 1 receipts. StoreKit 2 receipts are validated using PKI regardless of whether the shared secret is set.

Configure Apple App Store credentials #

If you’re using StoreKit 2 exclusively, skip this section as no Nakama configuration is required. If you’re using StoreKit 1 or need to support both receipt formats, configure the shared secret as follows.

  1. From App Store Connect, go to General > App Information and find the App-Specific Shared Secret section:
Apple App Store Connect
  1. Select Manage and in the dialog that appears, select Generate:
Generate Apple App Store Connect Shared Secret
  1. Record your shared secret for use in your Nakama configuration:
New Apple App Store Connect Shared Secret
  1. Set Nakama’s iap.apple.shared_password configuration flag to the shared secret value:
1
2
3
iap:
  apple:
    shared_password: "your-shared-secret-here"

Validate a purchase #

To validate an Apple purchase, send the receipt data in the appropriate format to Nakama’s validation endpoint. Nakama verifies the receipt with Apple’s servers and returns a list of validated purchases. Each purchase includes a “seen before” flag to help you detect and prevent replay attacks.

Refer to the function reference page for the provided runtime purchase validation functions.

Validate a subscription #

Subscription validation works similarly to purchase validation, but returns subscription-specific information like expiry time and active status. Send the same receipt in the appropriate format to the subscription validation endpoint.

Refer to the function reference page for the provided runtime subscription validation functions.

Handle refunds and subscription changes #

The Apple App Store supports Server Notifications to monitor IAP state changes in real time. Configuring server notifications is optional since your receipts and subscriptions validate correctly without it. However, enabling notifications is recommended: it lets Nakama automatically track subscription renewals, expirations, cancellations, and refunds, and allows you to register runtime hooks to trigger custom code when these events occur.

Accepting incoming notifications

Whether Nakama can process an incoming notification depends on which version of StoreKit your client uses.

StoreKit 1: Nakama can only process notifications for purchases that were previously validated through its client APIs. If Apple sends a notification for a purchase Nakama hasn’t seen before, it’s ignored.

StoreKit 2: Nakama can process a notification if either of the following is true:

  • The purchase was previously validated through Nakama’s client APIs, or
  • appAccountToken was set to the Nakama user_id (as a UUID) during the client purchase flow, using StoreKit 2’s appAccountToken(_:) purchase option.

If neither condition is met, the notification is ignored.

Even if you set appAccountToken, validating purchases through Nakama’s client APIs is still recommended. Server notifications are asynchronous, so there’s no guarantee of how quickly Nakama would otherwise become aware of an active subscription that hasn’t been explicitly validated.

Set up notification callbacks #

To activate the callback URL, set the notifications_endpoint_id configuration, which creates the following endpoint path: /v2/console/apple/subscriptions/<notifications_endpoint_id>.

The <notifications_endpoint_id> is an arbitrary string you define. It becomes the path segment Nakama listens on for incoming notifications.

Configure this URL in App Store Connect for both production and sandbox environments. Apple requires App Store Server Notifications v2.

App Store Connect Production Server URL
App Store Connect Production Server URL

Automatic state updates #

Once you’ve configured the callback URL, Nakama automatically updates the state of any purchase or subscription that was previously validated through the validation APIs. This keeps subscription expiry times, active status, and other metadata synchronized with the App Store.

Notification types #

Nakama normalizes Apple’s notifications into five simplified types:

TypeDescription
SUBSCRIBEDInitial subscription purchase or resubscription
RENEWEDSubscription successfully auto-renewed
EXPIREDSubscription expired and won’t renew
CANCELLEDSubscription cancelled by the user or the App Store
REFUNDEDPurchase or subscription refunded

These normalized types make it easier to handle notifications consistently across both Apple and Google platforms.

Implement notification hooks #

Register custom code to respond to notifications for purchases and subscriptions. Hooks fire after Nakama has automatically updated the purchase or subscription state in the database.

Use these hooks to implement your own business logic when IAP states change — like revoking player access when a subscription expires, sending analytics events, or triggering in-game rewards for renewals.

Purchase notifications #

Register a hook to handle purchase refunds. The purchase parameter contains the validated purchase data. See Response contents for available fields.

Subscription notifications #

Register a hook to handle all subscription state changes. The subscription parameter contains the validated subscription data — see Response contents for available fields.

See also #