How RTDN works

Real-time developer notifications (RTDN) are Google Play's server-to-server purchase events. Play publishes each event to a Cloud Pub/Sub topic, and your code receives it through a Pub/Sub subscription. Every message carries one base64-encoded data field that decodes to a DeveloperNotification: packageName, eventTimeMillis, and one of subscriptionNotification, oneTimeProductNotification, voidedPurchaseNotification, pendingRefundReviewNotification (a chargeback request for which you can suggest a resolution) or testNotification.

The sentence to remember from Google's reference:

“These notifications tell you only that the purchase state changed. They do not give you complete information about the purchase.”

— Android Developers, Real-time developer notifications reference guide

You get a purchaseToken (plus an orderId for voided purchases). The amount comes from a follow-up call to the Google Play Developer API — step 5.

The notification types that matter for sales:

NotificationTypeMeaning
subscriptionNotification(4) SUBSCRIPTION_PURCHASEDA new subscription was purchased
(2) SUBSCRIPTION_RENEWEDAn active subscription was renewed
(1) SUBSCRIPTION_RECOVEREDRecovered from account hold or resumed from pause
(3) SUBSCRIPTION_CANCELED · (13) SUBSCRIPTION_EXPIRED · (12) SUBSCRIPTION_REVOKEDCancelled, expired, or revoked before the expiration time
oneTimeProductNotification(1) ONE_TIME_PRODUCT_PURCHASEDA one-time product was purchased
(2) ONE_TIME_PRODUCT_CANCELEDA pending one-time purchase was cancelled by the user
voidedPurchaseNotificationproductType, refundTypeA purchase was voided (refund, chargeback); carries the orderId

The full list — grace period, account hold, pauses, price changes — is in the reference guide linked below.

Step 1: create a Pub/Sub topic

In the Google Cloud console, open Pub/Sub and create a topic in any project you control. Note its full name; it looks like projects/your-project-id/topics/play-rtdn.

Step 2: let Google Play publish to it

  1. In the Cloud console, open Pub/Sub and find your topic.
  2. Open its permissions.
  3. Add the service account google-play-developer-notifications@system.gserviceaccount.com with the role Pub/Sub Publisher.
  4. Click Save.

If your organization restricts sharing to its own domain, Google notes that you must add an exception for this Google Play service account, or the permission can't be granted.

Step 3: connect the topic in Play Console

  1. Open Google Play Console and select your app.
  2. Go to Monetize › Monetization setup.
  3. In the Real-time developer notifications section at the top, check Enable real-time notifications.
  4. In Topic name, enter the full topic name: projects/{project_id}/topics/{topic_name}.
  5. Choose what to receive. “Get notifications for subscriptions and all voided purchases” leaves out one-time product purchases; for sale alerts on one-time products, choose “Get all notifications for subscriptions and one-time products”.
  6. Click Save changes, then Send test message.

If the test publish fails, Google says to check that the topic name is exact and that the service account has Pub/Sub Publisher access. RTDN is set per app, so repeat this for each app — every app can point at the same topic.

Step 4: receive the messages

Attach a subscription to the topic. Google's Pub/Sub documentation describes the two kinds: pull subscriptions “use a subscriber client to request messages from the Pub/Sub server”, and push subscriptions “use the Pub/Sub server to initiate requests to your subscriber application to deliver messages”. With push, a successful HTTP response from your endpoint acknowledges the message; with pull, acknowledge each message you've handled, or Pub/Sub delivers it again.

Pub/Sub “offers at-least-once delivery with no ordering guarantees”, so expect the occasional duplicate. Google's RTDN guide recommends checking messageId uniqueness to avoid processing duplicates and wasting Developer API quota.

// Push endpoint: Pub/Sub POSTs {"message": {"data": "<base64>", "messageId": "…"}, "subscription": "…"}
export async function onPush(request) {
  const { message } = await request.json();
  if (await alreadySeen(message.messageId)) return new Response(null, { status: 204 });
  const note = JSON.parse(atob(message.data)); // DeveloperNotification
  if (note.testNotification) return new Response(null, { status: 204 });
  await enqueueLookup(note.packageName, note.subscriptionNotification ?? note.oneTimeProductNotification ?? note.voidedPurchaseNotification);
  return new Response(null, { status: 204 }); // 2xx acknowledges the message
}

For a public push endpoint, also turn on authentication for the push subscription so your endpoint can reject requests that didn't come from Pub/Sub.

Step 5: look up the purchase

Call the Google Play Developer API with credentials that can access the app — a service account added in Play Console, or an OAuth token with the androidpublisher scope:

With the amount in hand, send the alert wherever you like — Slack, a push notification, or a menu-bar app.

If you'd rather not run a Cloud project

RevBell runs the topic and the receiver for you. In Play Console you paste one RevBell topic, projects/reviewbell-play-production/topics/reviewbell-rtdn, instead of creating your own:

FAQ

Do notifications include the price?

No. They carry a purchase token; the amount comes from the Developer API (step 5).

Can several apps share one topic?

Yes. Each notification includes its packageName, so one topic and one receiver can serve all your apps.

Do I get one-time product purchases?

Only if you choose “Get all notifications for subscriptions and one-time products” in step 3.

How fast is it?

Google doesn't publish a delivery time for RTDN. Through RevBell's topic to a Mac, sale alerts usually arrive within 1–2 minutes.