What does the Google Play notification SUBSCRIPTION_IN_GRACE_PERIOD mean?

The Google Play notification SUBSCRIPTION_IN_GRACE_PERIOD means a renewal payment failed, but the customer keeps access during the grace period.

Quick facts#

Notification subscriptionNotification.notificationType 6, SUBSCRIPTION_IN_GRACE_PERIOD
Where Google Play real-time developer notifications (Pub/Sub, DeveloperNotification)
Sent by Google Play, as a Cloud Pub/Sub push to your endpoint
What Google says A subscription has entered the grace period, if the grace period is enabled.

What triggers it#

  • A renewal payment failed and the base plan has a grace period. Google enables it by default on auto-renewing base plans.
  • Google waits at least one day before the notification even with a grace period of zero days, to leave time for payment retries.
  • The subscription resource has state SUBSCRIPTION_STATE_IN_GRACE_PERIOD and expiryTime stays in the past until the grace period ends, but entitlement should last.

What your server should do#

  1. Do not trust the message for the state. Google says a notification only tells you the purchase state changed; call the Google Play Developer API (purchases.subscriptionsv2.get) with the purchase token to get the full state.
  2. Keep access while the grace period runs.
  3. Encourage the customer to fix their payment method, with a message in your app.
  4. Expect SUBSCRIPTION_RECOVERED or SUBSCRIPTION_RENEWED on success, or SUBSCRIPTION_ON_HOLD when the grace period ends.
  5. Answer 2xx once you have handled the message, and skip a messageId you have seen: Google recommends checking the uniqueness of message IDs so a redelivery does not make a second API call.

Example#

JavaScript
// A Pub/Sub push body: the notification is base64 JSON in message.data.
const body = { message: { messageId: "136969346945", data: Buffer.from(JSON.stringify({"version":"1.0","packageName":"com.example.app","eventTimeMillis":"1790800914000","subscriptionNotification":{"version":"1.0","notificationType":6,"purchaseToken":"PURCHASE_TOKEN"}})).toString("base64") } };

function decide(body) {
  const n = JSON.parse(Buffer.from(body.message.data, "base64").toString("utf8"));
  if (!(n.subscriptionNotification?.notificationType === 6)) return "ignore";
  return "keep access, show a fix-payment message";
}

console.log(decide(body));

Run-checked: npm run check:snippets runs this snippet with Node and compares its output with keep access (checked 2026-10-03).

How RevenueDot handles it#

RevenueDot answers every handled message with 2xx and every temporary failure with 5xx so Pub/Sub redelivers it. For subscription types it re-reads the subscription from Google with purchases.subscriptionsv2.get and applies that state, and it acknowledges a new purchase if the app has not. A purchase RevenueDot has not seen is applied only when the app's Track new purchases from server-to-server notifications setting is on. RevenueDot stores a billing issue with the grace period end set to the line item's expiry, so access continues. It sends BILLING_ISSUE with grace_period_expiration_at_ms and a CANCELLATION with cancel_reason: BILLING_ERROR. If access later ends, EXPIRATION follows.

Source#

Checked: 2026-10-03

Edit this page on GitHub ↗ View as Markdown Last updated