← All posts

How to Configure App Store Server Notifications V2 in App Store Connect

How to Configure App Store Server Notifications V2 in App Store Connect
Summarize this with AI
Open this article in your favorite AI assistant and get a quick summary in seconds.

This guide provides a step-by-step setup for App Store Server Notifications V2, covering endpoint registration in App Store Connect, JWS payload decryption, and executing test notifications without needing external SaaS.

These notifications are essential because they give your server real-time information about subscription status changes, refunds, and other purchase events. Without them, you'd have to poll Apple's API regularly, which is less efficient and prone to missing critical, time-sensitive updates.

Registering Your Server Endpoint in App Store Connect

The first step to receiving App Store Server Notifications V2 is to tell Apple where to send them. You'll need a publicly accessible HTTPS endpoint for this. This must be a URL that Apple can reach, typically on port 443, and it needs a valid TLS certificate from a trusted root authority. Apple will not send notifications to endpoints using self-signed certificates.

  1. Log into App Store Connect.
  2. Navigate to Users and Access from the main menu.
  3. In the sidebar, under the "Integrations" section, select App Store Server Notifications.
  4. Click the + button or "Add URL" to register a new endpoint.
  5. Enter your Production URL. For example, https://api.your-app.com/apple-notifications.
  6. If you have a separate environment for sandbox testing, also enter a Sandbox URL. This is optional but highly recommended for development.
  7. You can register up to five unique URLs in App Store Connect. If you need more, you might consider a single endpoint that routes to different internal services.

Apple will attempt to validate your URL immediately. Ensure your server is already running and ready to respond to a simple GET request, even if it just returns a 200 OK status. If Apple cannot reach your endpoint or the TLS certificate is invalid, it will show an error.

Understanding the JWS Payload Structure

App Store Server Notifications V2 use JSON Web Signatures (JWS) to ensure the integrity and authenticity of the data. This means the notification you receive isn't plain JSON; it's a compact, URL-safe string divided into three parts by dots: header.payload.signature.

eyJhbGciOiJFUzI1NiIsIng1YyI...

This entire string is the signedPayload. The actual notification data you care about is embedded within the payload section, which is Base64Url encoded. The header contains information about the signing algorithm and the certificate chain used to sign the payload, while the signature confirms the payload hasn't been tampered with.

When you receive a notification, it will be a JSON object containing a top-level key named signedPayload. This is the JWS string you need to parse and verify. For instance, a basic notification will look something like this:

{
  "signedPayload": "eyJhbGciOiJFUzI1NiIsIng1YyI6WyJ...[rest of JWS string]..."
}

It's crucial to understand that directly decoding the signedPayload without verification is risky. Always verify the signature first to ensure the notification genuinely came from Apple and hasn't been altered.

Decrypting and Verifying the JWS Payload

To access the actual notification data, you need to decrypt and verify the JWS payload. This involves several steps:

  1. Extract the Certificate Chain: The JWS header contains an x5c field, which is an array of Base64-encoded X.509 certificates. The first certificate in this chain is Apple's signing certificate.
  2. Download Apple's Root Certificates: For complete trust, you'll also need Apple's root certificates to verify the chain of trust for the signing certificate. You can find these on Apple's Certificate Authority page. The "Apple Root CA - G3" is typically the one you'll need.
  3. Use a JWS Library: Do not try to implement JWS parsing and verification yourself. Use a well-tested library for your programming language.
    • Node.js:
      jose
      or
      node-jose
    • Python:
      python-jose
    • Ruby:
      json-jwt
    • PHP:
      web-token/jwt-framework
    • Java:
      nimbus-jose-jwt

Here's a conceptual outline of the verification process:

// Pseudocode for JWS verification
function verifyAndDecodeJWS(signedPayload) {
    // 1. Parse the JWS string to get header, payload, and signature
    const { header, protectedHeader, payload, signature } = parseJWS(signedPayload);

    // 2. Extract Apple's signing certificate from the x5c header field
    const appleSigningCert = header.x5c[0];

    // 3. Verify the signature using the extracted certificate
    // This step ensures the payload hasn't been tampered with.
    if (!verifySignature(signedPayload, appleSigningCert)) {
        throw new Error("JWS signature verification failed.");
    }

    // 4. Decode the payload (Base64Url decode)
    const decodedPayload = base64UrlDecode(payload);

    // 5. Parse the decoded payload as JSON
    const notificationData = JSON.parse(decodedPayload);

    // 6. Optionally, verify the certificate chain up to Apple's root CA
    // (This adds an extra layer of security, ensuring the signing cert is valid)
    if (!verifyCertificateChain(header.x5c, appleRootCACert)) {
        throw new Error("Certificate chain verification failed.");
    }

    return notificationData;
}

Once successfully verified and decoded, the notificationData will be a JSON object containing details like notificationType (e.g., DID_RENEW, REFUND), subtype, and a data object with specific transaction information.

Executing Test Notifications Without External SaaS

App Store Connect provides a built-in way to send test notifications to your configured endpoints for verifying your server setup and JWS decryption logic without making actual purchases.

Step-by-Step Test Notification Checklist:

  1. Ensure your endpoint is running: Before initiating a test, double-check that your server is live and listening for requests at the URL you registered in App Store Connect.
  2. Log into App Store Connect: Access your developer account.
  3. Navigate to Server Notifications: Go to Users and Access > Integrations > App Store Server Notifications.
  4. Select an endpoint: Choose either your Production URL or Sandbox URL from the list. If you haven't set up a Sandbox URL, the production one will receive sandbox tests.
  5. Send Test Notification: Below your registered URLs, you'll see a section for "Test Notifications." Click the Send Test Notification button.
  6. Monitor your server logs: Immediately after clicking, check your server logs for an incoming request to your endpoint. You should see the JWS payload.
  7. Verify Decryption: Your server should attempt to verify and decrypt the JWS payload. If successful, you'll see the parsed JSON notification. The notificationType for test notifications is typically TEST.
  8. Check Delivery History: Back in App Store Connect, below the "Send Test Notification" button, there's a "Delivery History" section. This shows recent notification attempts, including their status (e.g., "Succeeded," "Failed," with HTTP status codes). If your server returned a non-200 status, it will be reflected here.

Repeat this process whenever you make changes to your notification processing logic. This built-in testing mechanism is a powerful way to ensure your app's backend is always in sync with Apple's purchase events.

Practical Example: Handling Notifications for a Habit Tracker App

Imagine you ship a habit tracker app that offers a premium subscription. You need to know when a user subscribes, renews, or cancels their subscription to manage their premium features correctly on your backend. App Store Server Notifications V2 streamline this.

Your server endpoint (e.g., https://api.myhabitapp.com/apple-webhooks) receives a signedPayload. After successful JWS decryption, you might see a notification like this:

{
  "notificationType": "DID_RENEW",
  "subtype": "AUTO_RENEWED",
  "data": {
    "bundleId": "com.myhabitapp",
    "environment": "Production",
    "appAppleId": 1234567890,
    "signedTransactionInfo": "eyJhbGciOiJFUzI1NiIsImtpZCI6...", // another JWS
    "signedRenewalInfo": "eyJhbGciOiJFUzI1NiIsImtpZCI6..." // another JWS
  },
  "version": "2.0",
  "signedDate": 1678886400000
}

In this example:

  • The notificationType is DID_RENEW, indicating a subscription renewal.
  • The subtype is AUTO_RENEWED, meaning it happened automatically.
  • Inside data, you find signedTransactionInfo and signedRenewalInfo. These are *also* JWS strings that you need to verify and decode separately to get the actual transaction and renewal details (e.g., purchase date, expiration date, product ID).

Your backend logic would then:

  1. Decode signedTransactionInfo to update the user's subscription status in your database, recording the new expiration date.
  2. Decode signedRenewalInfo to track the renewal history and potentially offer proactive support if issues arise.
  3. If the notificationType was GRACE_PERIOD_EXPIRED, you might revoke premium access until the subscription is resolved.
  4. If it was REFUND, you'd immediately revoke premium access and issue any necessary credits on your end.

Using a privacy policy generator or an app privacy label generator can also help ensure you're compliant with data handling related to subscription information.

FAQ

What's the difference between App Store Server Notifications V1 and V2?

V2 notifications provide a more robust and secure system. They use JWS for payload integrity and authenticity, offer more granular notification types and subtypes (like specific refund reasons or billing issues), and include more detailed transaction and renewal information in a structured format, making them easier to process reliably.

Do I need to handle all notification types sent by Apple?

No, you only need to handle the notification types relevant to your app's business logic. For example, if your app doesn't have consumable in-app purchases, you might not need to process notifications related to those. However, you should always be prepared to receive and ignore unknown types gracefully, and definitely process subscription lifecycle events if your app uses subscriptions.

What if my server misses an App Store Server Notification V2?

Apple will retry sending notifications multiple times over a period if your server returns a non-200 HTTP status code. However, it's good practice to also have a fallback mechanism, such as regularly fetching transaction history for your users via the App Store Server API, to reconcile any potential discrepancies and catch missed notifications.

Can I use a self-signed certificate for my endpoint URL?

No, Apple requires that your endpoint URL uses a valid TLS certificate issued by a trusted certificate authority. Self-signed certificates will cause validation errors in App Store Connect and prevent notifications from being sent to your server.

What port should my endpoint listen on for App Store Server Notifications V2?

Your App Store Server Notification V2 endpoint must listen on port 443, the standard port for HTTPS traffic. Apple expects all communications with your endpoint to be secured via HTTPS.

Next Steps: Integrate and Monitor

With your endpoint registered and JWS decryption logic in place, the next step is to integrate the parsed notification data into your app's backend to manage user entitlements and features. Remember to monitor your server logs and the App Store Connect delivery history for any issues. If you're also working on your app's visual presence, LaunchShots' free tools can help you design compelling App Store screenshots and generate other marketing assets.

Was this helpful?
Thanks — that helps me decide what to write next.
Like what you're reading? Add LaunchShots as a preferred source on Google + Follow

Comments (0)

Be the first to comment — share what you'd add, ask a question, or push back on something.
$ add a comment
Be kind. Comments with links are held for review.
Questions or ideas? I read every suggestion — drop yours on the feedback board.
Open feedback board →

Make your App Store screenshots free

LaunchShots is a free, in-browser screenshot maker. No signup, no watermark.

Open the app →