The [Google Play Developer API](https://developers.google.com/android-publisher) includes additional functionality to report
transactions from billing and link programs. This guide describes how to report
transactions from these billing programs.

There are a few components that might be necessary to handle external
transactions from your backend. To build them, you need to set up your backend
integration as indicated in [Configure the Google Play Developer API](https://developer.android.com/google/play/billing/getting-ready#dev-api). To
build developer backend functionality that is not specific to billing and link
programs, see [Google Play's billing system](https://developer.android.com/google/play/billing).

## Glossary of terms

Term conventions followed by this guide:

- **Billing and link programs** : Programs which facilitate digital content purchases or app downloads outside of Google Play. This includes the [alternative billing](https://support.google.com/googleplay/android-developer/topic/16471708) and [external content](https://support.google.com/googleplay/android-developer/topic/16470499) programs.
- **External transaction APIs**: APIs used to report transactions for eligible billing and link programs.
- **External transaction** : A qualifying transaction that occurs outside of the app as defined by the [alternative billing](https://support.google.com/googleplay/android-developer/topic/16471708) and [external content](https://support.google.com/googleplay/android-developer/topic/16470499) programs.
- **External transaction token**: A token provided through the Play Billing Library for you to use when the user initiates an external transaction. This token is used to notify Google Play of an authorized external transaction.
- **External transaction ID**: A unique identifier generated by you to identify an external transaction.

## Report new external transactions to Google Play

Integrate with the [`externaltransactions`](https://developers.google.com/android-publisher/api-ref/rest/v3/externaltransactions) API to *report
transactions happening outside Google Play's billing system in supported
countries, including $0 transactions* resulting from free trial purchases and
app installs. You should only start and report transactions on billing and link
programs for eligible user countries as permitted under the
[alternative billing](https://support.google.com/googleplay/android-developer/topic/16471708) and [external content](https://support.google.com/googleplay/android-developer/topic/16470499) programs; otherwise, the API
call is rejected. This applies to all transactions, including new purchases,
renewals, top-ups, upgrades, downgrades, and app downloads.

### External transaction reporting

You should call the `externaltransactions` API to report an external transaction
after a payment has been authorized through a billing and link program.
This applies to all transactions, including initial charges, renewals, refunds,
and others. See the guidelines for the respective billing and link program for
reporting requirements.

Each external transaction is reported with an external transaction ID. For
recurring purchases (such as auto-renewable subscriptions), you need to send the
external transaction ID associated with the first transaction in the recurring
purchase as a parameter for any subsequent transactions, including refunds. This
records the series of transactions for that purchase. You should send a new
external transaction ID for purchases when the product changes (such as an
upgrade or a downgrade), or if the recurring transaction is canceled or expired
and the same product is bought again later. You must not include any personally
identifiable information, proprietary, or confidential information as part of
this external transaction ID.

### Report an initial transaction

Every time a new purchase or app download is authorized in billing and link
programs, you must call the [`externaltransactions`](https://developers.google.com/android-publisher/api-ref/rest/v3/externaltransactions) API.

The `externalTransactionToken` received by the app through the Google Play
Billing Library is required as part of the request body for app downloads,
one-time purchases, and first-time transactions in a recurring purchase (such as
a subscription). This is called an *initial transaction* . After the initial
transaction, report subsequent transactions (such as subscription renewals) by
providing a new unique `externalTransactionId`. For more information, see
[Report subsequent transactions for a purchase](https://developer.android.com/google/play/billing/outside-gpb-backend#report-subsequent).

**Example**:

1. A developer configures and enables alternative billing in their app.
2. User 1 is in South Korea, a supported country, and is attempting to buy `product1`, for 12634.10KRW per month, with a one month free trial offer.
3. The app launches the purchase flow with the `ProductDetails` for `product1` and the offer that the user selected.
4. User 1 selects the developer's alternative billing system.
5. The `UserChoiceBillingListener` receives the value `my_token` as the `externalTransactionToken`.
6. The developer then sends the pertinent information to their backend (`externalTransactionToken` value and products being purchased). Then, they launch the purchase flow for `product1` in the alternative billing system. This transaction is assigned a unique transaction ID on the developer side that is used to report it to Google Play: *123-456-789*. The transaction ID is required, even though the user is receiving a free trial.
7. After the transaction for the purchase occurs in the alternative billing system, the developer reports the transaction to Google Play with the following request. It is reported as a zero-dollar transaction initially because the user gets a free month.

    POST /androidpublisher/v3/applications/com.myapp.android/externalTransactions?externalTransactionId=123-456-789

    Body
     {
    "originalPreTaxAmount" : {
       "priceMicros" : "0",
       "currency" : "KRW"
     },
     "originalTaxAmount" : {
       "priceMicros" : "0",
       "currency" : "KRW"
     },
    "transactionTime" : "2022-02-22T12:45:00Z",
     "recurringTransaction" : {
       "externalTransactionToken" : "my_token",
       "externalSubscription" : {
         "subscriptionType" : "RECURRING"
       }
     },
     "userTaxAddress" : {
       "regionCode" : "KR"
     }
    }

When reporting an initial transaction, be aware of the following:

- `subscriptionType` can be `RECURRING` (for auto-renewing subscriptions) or `PREPAID` (for prepaid subscriptions).
- `OtherRecurringProduct` must be used to represent one-time purchases that require multiple payments or a delayed payment. For example, a pre-order might have an initial $0 transaction followed by a second transaction at a later date for the price of the SKU when the pre-order is fulfilled. See [Report subsequent
  transactions for a purchase](https://developer.android.com/google/play/billing/outside-gpb-backend#report-subsequent) for more details on reporting subsequent transactions.
- You must provide [`ExternalOfferDetails`](https://developer.android.com/google/play/billing/outside-gpb-backend#external-offer-details) when reporting initial external offer transactions. This is not required for [subsequent transactions](https://developer.android.com/google/play/billing/outside-gpb-backend#report-subsequent).

If you're transacting with a user in India where the tax depends on their
administrative area (such as a state or province), include that area under
[`userTaxAddress`](https://developers.google.com/android-publisher/api-ref/rest/v3/externaltransactions#ExternalTransactionAddress). Refer to the predefined list of
strings in the API reference guide for applicable administrative areas.

    POST /androidpublisher/v3/applications/com.myapp.android/externalTransactions?externalTransactionId=123-456-789

    Body
     {
    "originalPreTaxAmount" : {
       "priceMicros" : "0",
       "currency" : "INR"
     },
     "originalTaxAmount" : {
       "priceMicros" : "0",
       "currency" : "INR"
     },
    "transactionTime" : "2023-11-01T12:45:00Z",
     "recurringTransaction" : {
       "externalTransactionToken" : "my_token",
       "externalSubscription" : {
         "subscriptionType" : "RECURRING"
       }
     },
     "userTaxAddress" : {
       # Tax varies in India based on state, so include that information in
       # administrativeArea
       "regionCode" : "IN",
       "administrativeArea" : "KERALA"
     }
    }

#### External offers

If the transaction being reported is under the external offers program, you
must set the `externalOfferDetails` field if the transaction is a one-time
transaction or the first transaction of a recurring series:

- When reporting app download transactions, set `linkType` to `LINK_TO_APP_DOWNLOAD` and provide the appropriate values for `installedAppPackage` and `installedAppCategory`. See [Report an app download](https://developer.android.com/google/play/billing/outside-gpb-backend#report-app-download) for details.
- When reporting digital content offer transactions, set `linkType` to `LINK_TO_DIGITAL_CONTENT_OFFER`.
- After an external app is installed through the external offers program, you must report transactions made in the external app. When reporting these transactions, link these transactions to the original app download event:
  - Provide the `externalTransactionToken` from the app download event.
  - In the `externalOfferDetails` field, set `appDownloadEventExternalTransactionId` to the `externalTransactionId` of the app download event. Other fields in `externalOfferDetails` are not required.

**Example request for transaction in an external app downloaded through external
offers:**

    POST /androidpublisher/v3/applications/com.myapp.android/externalTransactions?externalTransactionId=ABC-DEF-GHI

    Body
     {
    "originalPreTaxAmount" : {
       "priceMicros" : "990000", # 0.99 EUR
       "currency" : "EUR"
     },
     "originalTaxAmount" : {
       "priceMicros" : "90000", # 0.09 EUR
       "currency" : "EUR"
     },
    "transactionTime" : "2025-11-22T12:45:00Z",
     "oneTimeTransaction" : {
       "externalTransactionToken" : "my_external_transaction_token_for_link_to_download_event"
     },
     "userTaxAddress" : {
       "regionCode" : "DE"
     },
     "externalOfferDetails" : {
       "appDownloadEventExternalTransactionId" : "my_external_transaction_id_for_link_to_download_event"
     }
    }

The updated Play service fee details for different transaction types can be
found in [Changes to the external offers program](https://support.google.com/googleplay/android-developer/answer/16505463) for users in the European
Economic Area (EEA).

### Report subsequent transactions for a purchase

In some cases, there is more than one user payment associated with the same
external purchase, for example subscription renewals or prepaid plan top-ups.
You can report these subsequent transactions by using the same API in
`Externaltransactions`. As described in [Report a new purchase](https://developer.android.com/google/play/billing/outside-gpb-backend#report-new), the
`externalTransactionToken` isn't necessary for subsequent transactions. Instead,
a new unique `externalTransactionId` is sent as the query parameter for each
renewal or top-up transaction, with the ID of the initial transaction included
in the `initialExternalTransactionId` field.

**Following the previous example**:

1. User 1's first renewal occurs on the alternative billing system. The initial transaction ID was *123-456-789*.
2. The developer reports the transaction recurrence in the URL query parameter as the external transaction ID for this new transaction, while referencing the external transaction ID of the initial transaction in the `initialExternalTransactionId` field.

**Example request**:

    POST /androidpublisher/v3/applications/com.myapp.android/externalTransactions?externalTransactionId=abc-def-ghi

    Body
     {
    "originalPreTaxAmount" : {
       "priceMicros" : "12634000000", # 12634 KRW
       "currency" : "KRW"
     },
     "originalTaxAmount" : {
       "priceMicros" : "1263000000", # 1263 KRW
       "currency" : "KRW"
     },
    "transactionTime" : "2022-02-22T12:45:00Z",
     "recurringTransaction" : {
       "initialExternalTransactionId" : "123-456-789",

       "externalSubscription" : {
         "subscriptionType" : "RECURRING"
       }
     },
     "userTaxAddress" : {
       "regionCode" : "KR"
     }
    }

### Report an upgrade or downgrade

To report an upgrade or a downgrade when the user owns a subscription in the
alternative billing system you use the same endpoint and function in the
`Externaltransactions` API, sending the `externalTransactionToken` that was
provided to the app for the upgrade or downgrade transaction. This works
similarly to [reporting a new purchase](https://developer.android.com/google/play/billing/outside-gpb-backend#report-new).

### Report an app download

To report an app install in the external offers billing system, you must
call `Externaltransactions.createexternaltransaction`, sending the
`externalTransactionToken` that was provided to the app. Report this as a
zero-cost, one-time transaction; this process is similar to reporting an
[initial transaction](https://developer.android.com/google/play/billing/outside-gpb-backend#report-new). Be sure to include [`ExternalOfferDetails`](https://developer.android.com/google/play/billing/outside-gpb-backend#external-offer-details) in
the request body.

**Example request**:

    POST /androidpublisher/v3/applications/com.myapp.android/externalTransactions?externalTransactionId=123-456-789

    Body
     {
    "originalPreTaxAmount" : {
       "priceMicros" : "0",
       "currency" : "USD"
     },
     "originalTaxAmount" : {
       "priceMicros" : "0",
       "currency" : "USD"
     },
    "transactionTime" : "2025-12-22T12:45:00Z",
     "oneTimeTransaction" : {
       "externalTransactionToken" : "my_token",
     },
     "userTaxAddress" : {
       "regionCode" : "US"
     },
     "externalOfferDetails" : {
       "linkType" : "LINK_TO_APP_DOWNLOAD",
       "installedAppPackage" : "my.external.app",
       "installedAppCategory" : "APP"
     }
    }

### Migrate from manual reporting of alternative billing transactions

> [!NOTE]
> **Note:** Manual reporting of alternative billing only and user choice billing is being discontinued. For more details about migration deadlines, see [Understanding user choice billing on Google Play](https://support.google.com/googleplay/android-developer/answer/13821247). Be sure to migrate all active subscriptions that started while you were offering alternative billing without automated reporting through the `externaltransactions` API before manual reporting is disabled.

To migrate active subscriptions that started while you were offering alternative
billing without automated reporting, create a new zero-cost transaction using
the `migratedTransactionProgram` field instead of specifying an
`initialExternalTransactionId` or `externalTransactionToken`. Set the
`transactionTime` to the time when the user initially signed up for each active
subscription. Afterwards, report each subsequent transaction for these
subscriptions as normal through the APIs, providing the
`initialExternalTransactionId` used earlier to create the renewal transactions.
Once the subscription is migrated, you will no longer need to manually report
the subsequent transactions for the subscription, provided they are being
reported through the automated methods described in this page.

While migrating subscriptions, be mindful of the [quota limits](https://developer.android.com/google/play/billing/alternative/backend#api-quotas) in place to
verify the migration does not cause a quota outage. If many subscriptions need
to be migrated, spread them out across multiple days or [request for an increase
in quota](https://support.google.com/googleplay/android-developer/contact/apiqr).

> [!NOTE]
> **Note:** Only developers who have offered alternative billing without automated reporting will be able to set the `migratedTransactionProgram` field. If you previously offered alternative billing without automation and are getting an error when attempting to make a request to migrate the subscription, you can [contact our support team](https://support.google.com/googleplay/android-developer/contact/additional_billing_system_q) for help.

The `migratedTransactionProgram` field can only be used when migrating from
manual reporting. It will be deprecated when manual reporting is no longer
supported.

**Example request**:

    # Note that the externalTransactionId specified here will used to report
    # subsequent transactions.

    POST /androidpublisher/v3/applications/com.myapp.android/externalTransactions?externalTransactionId=abc-def-ghi

    Body
     {
     # Be sure to set the price to 0 for this transaction since it does not reflect
     # an actual subscription renewal.
     "originalPreTaxAmount" : {
       "priceMicros" : "0",
       "currency" : "KRW"
     },
     "originalTaxAmount" : {
       "priceMicros" : "0",
       "currency" : "KRW"
     },

     # The transaction time should be set to when the user signed up for this
     # subscription.
     "transactionTime" : "2022-02-22T12:45:00Z",
      "recurringTransaction" : {
        "migratedTransactionProgram" : "USER_CHOICE_BILLING",

        "externalSubscription" : {
          "subscriptionType" : "RECURRING"
        }
      },
     "userTaxAddress" : {
       "regionCode" : "KR"
     }
    }

### Requirements for Play partner programs

Developers participating in partner programs such as the [Play Media Experience
Program](https://google.play/business/programs/mediaprogram/) must provide the
[`transaction_program_code`](https://developers.google.com/android-publisher/api-ref/rest/v3/externaltransactions) when reporting external
transactions. If you are an eligible developer, contact your Business
Development Manager for more information on how to set this field.

## Report purchase refunds to Google Play

Integrate with the `externaltransactions` API to report transactions refunded to
users outside Google Play's billing system. For Play to correctly identify which
transaction has been refunded, you should include the corresponding
`externalTransactionId` for the previously reported transaction as part of the
URL parameters.

When reporting refunds of subscription purchases, reference the
`externalTransactionId` of the specific recurrence of the subscription that is
being refunded.

**Example**:
Suppose a subscription has the following transactions:

- An initial transaction with external transaction ID *ABC.1234-5678-9012-34567*

- The first recurring transaction with external transaction ID
  *ABC.1234-5678-9012-34567..0*

- The second recurring transaction with external transaction ID
  *ABC.1234-5678-9012-34567..1*

To report a refund of all transactions for the subscription, you need to make
three separate refund requests: one for the initial transaction and two for the
subsequent transactions.

This method accepts both [full refunds](https://developers.google.com/android-publisher/api-ref/rest/v3/externaltransactions/refundexternaltransaction#fullrefund) (where the amount is the
same amount that the user paid in the original external transaction) and
[partial refunds](https://developers.google.com/android-publisher/api-ref/rest/v3/externaltransactions/refundexternaltransaction#partialrefund) (where the amount is smaller than what the
user paid in the original external transaction). For partial refunds, you need
to specify the pre-tax amount that was refunded.

## API quotas

The `Externaltransactions` API is subject to [API quotas](https://developers.google.com/android-publisher/quotas) for
all calls, just like any other endpoint in the Google Play Developer API.

Additionally, the `Externaltransactions` API has a 1,200 Queries Per Minute
(QPM) limit on calls to `Externaltransactions.createexternaltransaction` or
`Externaltransactions.refundexternaltransaction`. Calls to
`Externaltransactions.getexternaltransaction` don't count toward this 1,200 QPM
limit.