Google Play Real-Time Developer Notifications in 2026: A Step-by-Step Tutorial to Cloud Pub/Sub, Push and Pull Delivery, and Every Notification Type
Real-time developer notifications (RTDN) are how Google Play tells your backend that something happened to a purchase. There is no webhook dashboard and no per-app API key: Play publishes a message into a Cloud Pub/Sub topic inside your own Google Cloud project, and your server either receives it as an HTTPS push or pulls it. If revenue operations still depend on scheduled jobs that poll the Developer API, RTDN is the upgrade — Google’s documentation notes that inefficient use of the Play Developer API “can lead to API quota restrictions.”
This tutorial follows the order you actually do the work: create the topic, grant Play publish rights, choose push or pull, enable notifications in Play Console, then decode the payload and act on it. Every field name, notification type and console step below is taken from Google’s two official pages, cited at the end.
What RTDN is, in one line: a message for every purchase-state change — roughly 1 KB per notification, about 2 KB per publish plus pull — and a standing obligation to call the Google Play Developer API afterwards, because the notification “does not give you complete information about the purchase.”
Step 1 — Create the Pub/Sub topic in your own GCP project
RTDN is configured per Android app, but the messaging layer belongs to you. You need a Google Cloud project with the Cloud Pub/Sub API enabled, and a topic that Play will publish to. You may reuse the project you already use for the Play Developer API or create a separate one: for multiple apps you must use the same Google Cloud project for the Play Developer API, but each individual app can publish to its own project.
Size it before you build. The data portion of a notification is approximately 1 KB per request, and each publish plus pull is a separate request — about 2 KB per notification. Monthly volume depends on your billing cycles and user behaviour, but plan for at least one notification per user per billing cycle, then check Pub/Sub pricing and quotas for that figure.
Step 2 — Give Google Play permission to publish
A brand-new topic silently rejects Play’s publishes until you grant access, and this is the step people miss. In the Google Cloud Console: select the project, open Pub/Sub, find your topic, open its permissions details, then add the service account
google-play-developer-notifications@system.gserviceaccount.com
and grant it the role Pub/Sub Publisher. Save to complete the topic setup. One enterprise wrinkle: if your organization’s domain-restricted sharing configuration blocks the grant, you must add an exception for that Google Play service account before Play can publish anything.
Step 3 — Choose push or pull for the subscription
A topic is not a mailbox you can read; you need a subscription attached to it. A push subscription has Cloud Pub/Sub issue HTTPS requests to your secure backend. A pull subscription requires your backend to initiate requests to Pub/Sub and retrieve messages. Google’s guidance for RTDN: if you are unsure, use push, “as it is generally easier to implement”; pull is commonly used to optimise resource utilisation when a large number of messages are processed.
Two operational rules follow from the choice. For pull, acknowledge every message you have pulled, or Pub/Sub will keep redelivering it. For push, a successful response code from your endpoint serves as the acknowledgement — a slow or failing endpoint means repeated delivery.
Step 4 — Enable RTDN in Play Console and send a test
- Open the Google Play Console, select your app, and go to Monetize → Monetization setup.
- In the Real-time developer notifications section at the top of that page, tick Enable real-time notifications.
- In the Topic name field, enter the full topic name in the format
projects/{project_id}/topics/{topic_name}. - Click Send Test Message. For pull, open the subscription in Cloud Console, click View Messages and pull; then acknowledge. For push, check that the test message reached your endpoint.
- Choose the notification scope. Subscriptions and all voided purchases gives you subscription and voided-purchase events only. All notifications for subscriptions and one-time products also sends one-time product purchase events such as
ONE_TIME_PRODUCT_PURCHASEDandONE_TIME_PRODUCT_CANCELED. - Click Save changes.
When the test publish fails, the console shows an error and there are only two realistic causes: the topic name is wrong, or google-play-developer-notifications@system.gserviceaccount.com does not have Pub/Sub Publisher on the topic. Fix the grant, not the app.
What a message actually contains
Every publish to the topic has the same envelope: an attributes map, a base64-encoded data field, a messageId, and the subscription path. Decode data and you get a DeveloperNotification carrying four facts — version, packageName, eventTimeMillis — plus exactly one payload field. Those payload fields are mutually exclusive: subscriptionNotification, oneTimeProductNotification, voidedPurchaseNotification, or testNotification.
messageId is a unique identifier for the notification, and the reference guide recommends checking that uniqueness so you do not process duplicate notifications and make redundant backend API calls — which wastes exactly the API quota RTDN exists to protect.
Subscription notification types
A subscriptionNotification carries a notificationType integer, a purchaseToken and its own version. The current set:
- 1 — SUBSCRIPTION_RECOVERED: recovered from account hold, or resumed from pause.
- 2 — SUBSCRIPTION_RENEWED: an active subscription renewed.
- 3 — SUBSCRIPTION_CANCELED: cancelled voluntarily or involuntarily; for a voluntary cancellation it is sent when the user cancels.
- 4 — SUBSCRIPTION_PURCHASED: a new subscription was purchased.
- 5 — SUBSCRIPTION_ON_HOLD: entered account hold, if you enabled it.
- 6 — SUBSCRIPTION_IN_GRACE_PERIOD: entered grace period, if you enabled it.
- 7 — SUBSCRIPTION_RESTARTED: user restored a cancelled subscription from Play → Account → Subscriptions before it expired.
- 9 — SUBSCRIPTION_DEFERRED: the recurrence time was extended.
- 10 — SUBSCRIPTION_PAUSED / 11 — SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED: paused, or the pause schedule changed.
- 12 — SUBSCRIPTION_REVOKED: revoked before the expiration time.
- 13 — SUBSCRIPTION_EXPIRED: the subscription expired.
- 17 — SUBSCRIPTION_ITEMS_CHANGED: an item in a subscription bundle changed.
- 18 — SUBSCRIPTION_CANCELLATION_SCHEDULED: cancellation scheduled for the end of an installment commitment period.
- 19 — SUBSCRIPTION_PRICE_CHANGE_UPDATED: a subscription item’s price-change details were updated.
- 20 — SUBSCRIPTION_PENDING_PURCHASE_CANCELED: a pending subscription transaction was cancelled.
- 22 — SUBSCRIPTION_PRICE_STEP_UP_CONSENT_UPDATED: the price step-up consent period began, or the user consented; sent only in regions where price step-up is required.
Type 8 (SUBSCRIPTION_PRICE_CHANGE_CONFIRMED) is marked deprecated in the reference, so do not build new logic on it. Note also that these numbers are not a lifecycle you can infer — the event tells you state changed, never the resulting state.
One-time product notifications
Only sent if you selected the wider scope. A oneTimeProductNotification adds an sku field to the token, with two types: 1 — ONE_TIME_PRODUCT_PURCHASED (a one-time product was successfully purchased) and 2 — ONE_TIME_PRODUCT_CANCELED (a pending one-time purchase was cancelled by the user). Both cases still require a Developer API call, because a purchase notification says nothing about whether you have consumed or acknowledged the product yet.
Voided purchases and the refundType field
A voidedPurchaseNotification is the RTDN most revenue teams care about, and in 2026 it carries more than a token. The payload is purchaseToken, orderId, productType and refundType. productType is 1 for a subscription or 2 for a one-time purchase. refundType is 1 — REFUND_TYPE_FULL_REFUND or 2 — REFUND_TYPE_QUANTITY_BASED_PARTIAL_REFUND, the latter applying only to multi-quantity purchases, which can be partially voided several times; once the remaining total quantity is refunded, the type reports as a full refund.
The reference guide is explicit that for locating the right purchase and order to adjust entitlements, the notification itself is sufficient — and that the Google Play Voided Purchases API is the pull-model complement, returning voided purchase data for a timestamp range. For partial multi-quantity refunds, the refundableQuantity field from purchases.productsv2 tells you how many purchased products remain un-voided. That pairs directly with the chargeback and refund accounting changes we covered in the 2026 Play refund and chargeback guide.
Server rules that keep the pipeline correct
- Treat the notification as a question, not an answer. Call the Developer API after every RTDN to get the complete status before granting, extending or revoking entitlement.
- Deduplicate on
messageId. Pub/Sub delivers at least once; duplicate processing means duplicate API calls and duplicate state transitions. - Always acknowledge, then process. Pull: acknowledge pulled messages. Push: return a success code. If processing takes longer than the acknowledgement, accept redelivery and make the handler idempotent.
- Expect several events per user. One
purchaseTokencan produce purchased, cancelled, then expired notifications for the same subscriber — the handler must be safe to run repeatedly. - Do not poll to compensate. Polling the Developer API alongside RTDN is the failure mode that triggers quota restrictions.
Verifying your configuration
The console’s Send Test Message is the fastest end-to-end proof: if you have a subscription attached, you should receive it. A testNotification body contains only a version field, so it is a safe payload to assert against in your handler’s test suite. With no backend yet, use the gcloud command line to pull the message from the subscription — and remember to acknowledge it. A healthy pipeline shows up as a stream of events whose packageName matches your app and whose eventTimeMillis tracks live subscriber activity.
One scheduling note: server-side RTDN work sits next to the client-side Billing Library deadline. All new apps and updates must use Billing Library version 8 or later, with an extension path running to November 1, 2026 — and the server verification that consumes RTDN should be ready at the same time.
Sources
- Real-time developer notifications reference guide — Android Developers
- Getting ready: Configure Real-time developer notifications — Android Developers
Running developer accounts at scale? We handle the operational side.
We received your message and will reply within 24 hours.
Or email expert@kapps.store← Back to edit