did_fail_to_renew

Learn about the DID_FAIL_TO_RENEW App Store Server Notification V2. Fired when a subscription renewal fails due to a billing issue.

App Store Server Notifications V2Subscriptions
did_fail_to_renew

The DID_FAIL_TO_RENEW notification fires when Apple fails to charge a customer for their subscription renewal. This is typically due to an expired or declined payment method.


When does it fire?


This notification triggers when the billing attempt at the end of a subscription period fails. It may include a subtype indicating whether a grace period is active:


  • Grace period active — the customer still has access while Apple retries billing
  • No grace period — access may be revoked if billing isn't resolved

Apple will retry billing multiple times over the following days before eventually expiring the subscription.


Payload highlights


The signed transaction info shows the last successful transaction, while the signed renewal info indicates the grace period status and the next retry date. This helps you understand the customer's current access state.


How Yeethook helps


Billing failures are involuntary churn — the customer didn't intend to cancel. Yeethook alerts your team immediately so you can take action, such as sending a payment update reminder or adjusting access gracefully.


Common use cases


  • Detect involuntary churn before it becomes permanent
  • Send payment update reminders to affected subscribers
  • Monitor billing failure rates across regions and payment methods
  • Track grace period resolution rates

Example payload

The decoded body of a failed charge where a billing grace period is configured, which is what the GRACE_PERIOD subtype means. status 4 is the important part: the subscriber still has an entitlement while Apple retries.

{
  "notificationType": "DID_FAIL_TO_RENEW",
  "subtype": "GRACE_PERIOD",
  "notificationUUID": "9d1b7ae0-38f4-4c62-95e7-0b6a2f8c1d59",
  "version": "2.0",
  "signedDate": 1789544093000,
  "data": {
    "appAppleId": 1234567890,
    "bundleId": "com.example.app",
    "bundleVersion": "142",
    "environment": "Production",
    "signedTransactionInfo": "eyJhbGciOiJFUzI1NiIsIng1YyI6...",
    "signedRenewalInfo": "eyJhbGciOiJFUzI1NiIsIng1YyI6...",
    "status": 4
  }
}

What it looks like in Slack

Warning

Renewal failed (grace period active)

Product
com.example.app.pro.monthly
Transaction
2000000798765432
Expires
2026-11-12T09:34:13.000Z
Auto-renew
On
Subscription status
Billing grace period
Environment
Production

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

  • (no subtype)→ Renewal failed

Questions about did_fail_to_renew

Is DID_FAIL_TO_RENEW the same as an expired subscription?

No. The subscription record is still open: status is 3 (Billing retry) or 4 (Billing grace period), not 2 (Expired). EXPIRED only arrives once Apple gives up, which can be weeks after this notification.

How long does Apple keep retrying a failed charge?

Up to 60 days from the first failure, and it does not send a notification for each individual attempt. The next event you receive for this subscriber is either DID_RENEW with subtype BILLING_RECOVERY or EXPIRED with subtype BILLING_RETRY.

Should I cut off access when this arrives?

Only if there is no grace period. With subtype GRACE_PERIOD the entitlement runs until gracePeriodExpiresDate in signedRenewalInfo, so keep access on; without the subtype the status is 3 and the paid period has already lapsed.

Does the notification say why the payment failed?

No. Apple never exposes payment method or decline reason data, and the only machine-readable hint is the status code. A cause of sorts only appears if the subscription eventually expires, as expirationIntent 2 (Billing error).

Get this event in Slack or Discord

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

Get Started Free