did_renew

Learn about the DID_RENEW App Store Server Notification V2. Fired when an auto-renewable subscription successfully renews for a new billing period.

App Store Server Notifications V2Subscriptions
did_renew

The DID_RENEW notification fires when an auto-renewable subscription successfully renews for a new billing period. This is the heartbeat of your subscription revenue — each renewal means continued revenue from an existing subscriber.


When does it fire?


This notification triggers at the end of each billing period when Apple successfully charges the customer and extends their subscription. It also fires after a billing retry succeeds following a failed renewal attempt.


Payload highlights


The signed transaction info includes the product ID, the new transaction ID, the purchase date, the new expiration date, and a fresh webOrderLineItemId. That last one identifies a single paid period, so counting them tells you how many periods a subscriber has been active.


How Yeethook helps


Renewal events are high-volume for apps with many subscribers. Yeethook filters and formats these events so you can track renewals without noise. Route them to a dedicated #revenue channel to monitor subscription health.


Common use cases


  • Monitor daily renewal rates to detect billing issues early
  • Track subscriber retention by watching renewal counts
  • Alert on renewals after billing retry (recovered revenue)
  • Build dashboards showing MRR trends from real-time renewal data

Example payload

The decoded body of a normal renewal, with no subtype. Apple sends this once per successful billing period, and status 1 confirms the subscription is active for the new period.

{
  "notificationType": "DID_RENEW",
  "notificationUUID": "c17e5a92-84b1-4d6f-a2c3-58e90f1b7d46",
  "version": "2.0",
  "signedDate": 1789284871000,
  "data": {
    "appAppleId": 1234567890,
    "bundleId": "com.example.app",
    "bundleVersion": "142",
    "environment": "Production",
    "signedTransactionInfo": "eyJhbGciOiJFUzI1NiIsIng1YyI6...",
    "signedRenewalInfo": "eyJhbGciOiJFUzI1NiIsIng1YyI6...",
    "status": 1
  }
}

What it looks like in Slack

Success

Subscription renewed

Product
com.example.app.pro.monthly
Price
9.99 USD
Transaction
2000000798765432
Expires
2026-11-12T09:34:13.000Z
Auto-renew
On
Subscription status
Active
Environment
Production

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

  • BILLING_RECOVERY→ Subscription renewed (billing recovery)

Questions about did_renew

How do I deduplicate renewals for the same subscriber?

Each renewal carries a fresh transactionId and a fresh webOrderLineItemId while originalTransactionId stays constant for the life of the subscription. Key your billing records on originalTransactionId and treat webOrderLineItemId as the unique identifier for one paid period.

What does the BILLING_RECOVERY subtype mean?

It means the charge succeeded after an earlier attempt failed, so this subscriber previously produced a DID_FAIL_TO_RENEW. Yeethook changes the headline to "Subscription renewed (billing recovery)" so recovered revenue is distinguishable from ordinary renewals in the same channel.

Is a plan upgrade reported as a renewal?

No. An upgrade arrives as DID_CHANGE_RENEWAL_PREF with subtype UPGRADE, because the customer changed product rather than paying for another period of the same one. DID_RENEW is only sent when the product identified in the transaction bills again.

Why is the Price row sometimes missing from the message?

Yeethook only renders Price when the decoded transaction contains both price and currency, and Apple added those two fields to the transaction payload in 2023. Transactions signed before that, or replayed from older test fixtures, show Product and Transaction but no amount.

Get this event in Slack or Discord

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

Get Started Free