external_purchase_token

Learn about the EXTERNAL_PURCHASE_TOKEN App Store Server Notification V2. Used for apps distributed through alternative distribution in the EU.

App Store Server Notifications V2Other
external_purchase_token

The EXTERNAL_PURCHASE_TOKEN notification fires when an external purchase token is created. This notification type is relevant for apps that use the External Purchase API to take payment outside the App Store in the European Union, as required by the Digital Markets Act (DMA).


When does it fire?


This notification triggers for apps that use the External Purchase API to offer alternative payment options in the EU, when a token is created, when Apple reminds you that an active token is still unreported, and when a token expires without being reported. This is part of Apple's compliance with EU regulations that require allowing third-party payment processors.


Payload highlights


The notification includes the external purchase token that can be used to verify the transaction. This token type was introduced as part of Apple's DMA compliance measures.


How Yeethook helps


If your app supports alternative distribution in the EU, Yeethook tracks these token events alongside your standard App Store transactions, giving you a unified view of all purchase activity in one channel.


Common use cases


  • Monitor external purchase activity for EU-distributed apps
  • Track alternative distribution adoption rates
  • Verify external purchase tokens for transaction validation
  • Maintain a unified view of all purchase activity

Example payload

This type has no data object at all: the decoded body carries a top-level externalPurchaseToken instead, which is why integrations that only read payload.data render an empty message for it.

{
  "notificationType": "EXTERNAL_PURCHASE_TOKEN",
  "subtype": "CREATED",
  "notificationUUID": "c2810a6f-5be4-4739-84d1-96e70f2b3c48",
  "version": "2.0",
  "signedDate": 1789205608000,
  "externalPurchaseToken": {
    "externalPurchaseId": "b6f1c40d-92a7-4e83-8c15-70da29e4f1b6",
    "tokenCreationDate": 1789205608000,
    "tokenExpirationDate": 1790581168000,
    "tokenType": "ACQUISITION",
    "appAppleId": 1234567890,
    "bundleId": "com.example.app"
  }
}

What it looks like in Slack

Info

External purchase token created

Token ID
b6f1c40d-92a7-4e83-8c15-70da29e4f1b6
Token type
Acquisition
Expires
2026-09-28T07:39:28.000Z
Bundle ID
com.example.app

The same event arrives with different values depending on what changed. Yeethook rewrites the headline to match:

  • ACTIVE_TOKEN_REMINDER→ External purchase token reminder
  • UNREPORTED→ External purchase token unreported
  • (no subtype)→ External purchase token (EU)

Questions about external_purchase_token

Why is there no data object in this notification?

Because Apple uses four mutually exclusive top-level shapes in V2: data for transaction events, appData for consent withdrawals, summary for batch results and externalPurchaseToken for this type. Yeethook reads all four, so the token fields appear as Token ID, Token type and Bundle ID rows.

Which apps ever receive EXTERNAL_PURCHASE_TOKEN?

Only apps that use an external purchase entitlement in the EU under the Digital Markets Act. Standard StoreKit purchases never generate it, so if you see it on an app you believe is App Store only, check which entitlements the build ships with.

How does Yeethook treat the different subtypes?

CREATED is posted at info level, ACTIVE_TOKEN_REMINDER as a warning and UNREPORTED as critical, since an unreported token is the one state with a compliance consequence. Any other subtype falls back to the generic headline "External purchase token (EU)".

How long does an external purchase token stay valid?

Until tokenExpirationDate, which Yeethook shows as the Expires row. Report the token to Apple before that timestamp passes, because a token that expires unreported is what produces the UNREPORTED subtype later.

Get this event in Slack or Discord

Connect Yeethook to receive external_purchase_token notifications in your team's Slack or Discord channels.

Get Started Free