Measure Engine

Apple App Store Server Notifications

Setting up App Store Server Notifications V2 with Appflow

Overview

Apple sends real-time notifications about subscription lifecycle events directly to your server. Appflow processes these notifications to maintain accurate subscription state, revenue tracking, and churn detection across your entire subscriber base.

Appflow supports both V2 notifications (recommended) and V1 (legacy). V2 notifications use signed JWS payloads for enhanced security and include richer data about subscription state changes. We strongly recommend using V2 for all new integrations.

Endpoint
https://api-v2.appflow.ai/v1/webhooks/apple
Method
POST
Format
JWS (JSON Web Signature)

Setup in App Store Connect

Configure App Store Connect to send server notifications to Appflow. Follow these steps to connect your app:

1

Go to App Store Connect and navigate to Your App → App Information

2

Scroll to the App Store Server Notifications section

3

Set the Production Server URL to:

Production URL
https://api-v2.appflow.ai/v1/webhooks/apple
4

Set the Sandbox Server URL to:

Sandbox URL
https://api-v2.appflow.ai/v1/webhooks/apple?env=sandbox
5

Select Version 2 Notifications from the notification version dropdown

Save your changes. Apple will begin sending notifications to Appflow within minutes. Sandbox notifications will use the sandbox URL automatically.

Configure in Appflow

After configuring App Store Connect, provide Appflow with the credentials needed to verify and process notifications. You can do this from the dashboard under Settings → Webhooks or via the API:

cURL
curl -X PUT https://api-v2.appflow.ai/v1/apps/app_xxx/webhooks/apple \
  -H "Authorization: Bearer sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "shared_secret": "your_app_shared_secret",
    "bundle_id": "com.example.myapp",
    "issuer_id": "xxx-xxx-xxx",
    "key_id": "ABC123",
    "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
  }'

Field Reference

FieldDescription
shared_secretYour app-specific shared secret from App Store Connect. Used for V1 receipt validation and as a fallback verification method.
bundle_idThe bundle identifier of your iOS app (e.g., com.example.myapp). Used to route notifications to the correct app.
issuer_idYour issuer ID from App Store Connect → Users and Access → Keys. Required for App Store Server API access.
key_idThe key ID of your App Store Connect API key. Found alongside the private key download.
private_keyThe .p8 private key file contents. Used to authenticate with the App Store Server API for receipt lookups and subscription status queries.
Store your private key securely. Never commit it to version control or share it in plain text. Use environment variables or a secrets manager in production.

Supported Notification Types

Appflow processes all V2 notification types from Apple. Each notification is mapped to a subscription state transition and triggers the corresponding analytics and revenue updates.

NotificationSubtypesWhat Appflow Does
SUBSCRIBEDINITIAL_BUY, RESUBSCRIBECreates or updates subscription record, begins tracking MRR
DID_RENEWUpdates expiry date, confirms active subscription status
DID_CHANGE_RENEWAL_STATUSAUTO_RENEW_ENABLED, AUTO_RENEW_DISABLEDUpdates renewal intent, triggers churn prediction signals
DID_CHANGE_RENEWAL_INFOUpdates pricing and promotional offer information
DID_FAIL_TO_RENEWMarks subscription in billing retry, triggers win-back flows
EXPIREDVOLUNTARY, BILLING_RETRY_PERIOD, PRICE_INCREASEMarks subscription as churned, adjusts MRR downward
GRACE_PERIOD_EXPIREDMarks involuntary churn after billing grace period
OFFER_REDEEMEDINITIAL_BUY, RESUBSCRIBE, UPGRADE, DOWNGRADETracks promotional offer attribution and conversion
REFUNDProcesses refund, adjusts lifetime revenue figures
REVOKEHandles Family Sharing revocation, updates access
CONSUMPTION_REQUESTResponds to Apple consumption information requests
RENEWAL_EXTENDEDExtends subscription period, updates next renewal date

Subscription State Machine

Appflow maintains a deterministic state machine for each subscription. Incoming Apple notifications drive transitions between states. This ensures accurate subscriber counts and revenue metrics at all times.

trial
active
grace_period
billing_retry
cancelled
expired
trialactiveTrial converts
activegrace_periodBilling fails
grace_periodbilling_retryGrace period expires
billing_retryexpiredRetry exhausted
activecancelledAuto-renew disabled
cancelledexpiredPeriod ends
cancelledactiveAuto-renew re-enabled
expiredactiveResubscribe
The state machine handles edge cases like re-subscribing from an expired state, grace period recovery, and billing retry loops. All transitions are idempotent and safe to replay.

Verification

Appflow automatically verifies all incoming V2 notifications by validating the JWS (JSON Web Signature) using Apple's public certificates. This ensures that notifications are authentic and have not been tampered with in transit.

The verification process includes:

Validates the JWS signature against Apple's root certificate chain
Checks the certificate expiration and trust chain
Verifies the bundle ID matches your configured app
Confirms the environment (production vs sandbox) is correct
Rejects replayed notifications using transaction deduplication
For testing, use the sandbox URL https://api-v2.appflow.ai/v1/webhooks/apple?env=sandbox in App Store Connect. Sandbox notifications use a separate verification path and are tagged accordingly in your dashboard.

Troubleshooting

If notifications are not being processed correctly, check the following common issues:

401Unauthorized

Invalid shared secret or JWS verification failed. Verify your shared secret matches the one in App Store Connect. For V2, ensure your issuer_id, key_id, and private_key are correctly configured.

404App Not Found

No app is configured for the bundle_id in the notification. Make sure you have registered your app in Appflow with the matching bundle identifier.

DelayedNotifications Not Arriving

Apple may take a few minutes to begin sending notifications after initial setup. Verify the URL is saved correctly in App Store Connect and that V2 is selected as the notification version.

Check your webhook delivery logs in Settings → Webhooks for detailed request/response logs. Each delivery attempt is recorded with its HTTP status code, processing time, and any error details.

Next Steps