LinkJoltDevelopers

Manage API Keys

← Back to LinkJolt.io

← All guides

Track Apple In-App Purchase conversions

Wire Apple App Store Server Notifications v2 to LinkJolt. Offer-code attribution. No SDK.

Intermediate

15 min read

What you'll get

  • Apple-signed subscription events delivered directly to LinkJolt
  • Attribution via Apple Subscription Offer Codes (no IDFA, no MMP)
  • Automatic recurring commissions on DID_RENEW
  • Refund + family-share revocation handling
  • Sandbox isolation — test conversions tagged is_test=true

Architecture

App Store Server Notifications v2 (ASSN v2) is Apple's server-to-server event stream for subscription lifecycle events. Each notification arrives at your configured URL as a JSON body containing a single signedPayload field — a JWS signed with Apple's certificate chain rooted at Apple Root CA - G3.

LinkJolt runs a dedicated endpoint per merchant. You never implement the verification yourself — paste the URL into App Store Connect and we handle the JWS chain check, event mapping, and conversion insertion.

Step 1 — Configure your app details

Go to Integration Hub → Other Platforms → Apple In-App Purchases and enter:

  • Bundle ID — reverse-domain identifier (e.g. com.example.app). Required. Used to validate bundleId inside Apple's signed payload.
  • App Apple ID — numeric App Store app identifier (e.g. 1234567890). Required for Production notification verification. Optional if you're only testing in Sandbox.

Both values appear in App Store Connect → My Apps → [your app] → App Information.

Step 2 — Paste webhook URLs into App Store Connect

From your LinkJolt Apple IAP setup screen, copy the Production and Sandbox URLs. The shape is:

# Production
https://linkjolt.io/api/webhooks/apple-iap/<your-merchant-user-id>

# Sandbox
https://linkjolt.io/api/webhooks/apple-iap/<your-merchant-user-id>/sandbox

In App Store Connect: General → App Information → scroll to App Store Server Notifications. For each URL field:

  1. Click Set Up URL
  2. Paste the URL from LinkJolt
  3. Select the Version 2 Notifications radio button (Version 1 is deprecated)
  4. Save

Step 3 — Generate Subscription Offer Codes

Offer codes are Apple's officially-supported attribution mechanism for “influencer partnerships with exclusive codes” and “co-marketing partnerships” (Apple's own words).

In App Store Connect:

  1. My Apps → [your app] → Subscriptions → Subscription Offer Codes
  2. Create a new offer — choose Custom Codes (each affiliate gets their own identifier) or One-Time Use (single-redemption codes for limited drops)
  3. Set the discount, duration, and eligibility rules
  4. Copy the Offer Identifier — this is what Apple reports in the notification

Limits: up to 25,000 codes per batch; up to 1,000,000 redemptions per app per quarter.

Step 4 — Register offer identifiers in LinkJolt

For each offer code, register it against a campaign and affiliate via the LinkJolt dashboard or the Developer API:

curl https://linkjolt.io/api/coupons \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "apple",
    "code": "PARTNER_JEN",
    "campaignId": "cmp_...",
    "affiliateId": "aff_..."
  }'

Apple offer identifiers are case-sensitive — register them exactly as you configured them in App Store Connect.

Step 5 — Event mapping

LinkJolt automatically handles all subscription lifecycle events:

  • SUBSCRIBED (INITIAL_BUY / RESUBSCRIBE) — inserts a new conversion, attributes to the affiliate matching offerIdentifier.
  • DID_RENEW — inserts a recurring conversion linked to the parent via originalTransactionId. Requires recurring commissions enabled on the campaign.
  • REFUND / REVOKE — marks the matching conversion as rejected.
  • REFUND_REVERSED — reverts rejection back to pending so you can re-approve.
  • EXPIRED, DID_FAIL_TO_RENEW, PRICE_INCREASE, RENEWAL_EXTENDED, DID_CHANGE_RENEWAL_PREF, DID_CHANGE_RENEWAL_STATUS, GRACE_PERIOD_EXPIRED, OFFER_REDEEMED — logged, no commission side-effects.

Step 6 — Test it

End-to-end sandbox flow:

  1. Build your app for StoreKit testing (TestFlight or a StoreKit configuration file in Xcode)
  2. Redeem one of your uploaded offer codes from a Sandbox Apple ID inside your test build
  3. Apple sends a SUBSCRIBED notification to your Sandbox URL
  4. LinkJolt verifies the JWS, looks up the offer code, inserts a conversion with is_test=true, and shows it in your dashboard under “Test data”

To exercise the webhook without a real purchase, Apple's POST /inApps/v1/notifications/test endpoint fires a signed TEST notification. Requires a signed JWT with your App Store Connect API key — see Apple's Request a Test Notification docs.

Retry behaviour

Apple retries failed deliveries 5 times over 72 hours (at 1h, 12h, 24h, 48h, 72h). LinkJolt always returns HTTP 200 for handled or intentionally-ignored events, and 500 only on transient database errors — Apple retries those legitimately. Idempotency is enforced by a unique index on conversions.order_id (= Apple's transactionId), so duplicate deliveries are safe. Sandbox notifications are not retried.

Attribution boundaries

Offer-code attribution is deterministic and 100% accurate on redemption. It does not attempt ambient click-to-install-to-purchase attribution — that requires an MMP and is probabilistic post-ATT on iOS. For indie subscription apps, offer codes are the more honest and higher-quality signal. If a user buys your subscription without redeeming an affiliate code, that conversion is recorded but unattributed.