---
title: "Which webhook events does RevenueDot send?"
description: "Every webhook event type RevenueDot sends, when each fires, its fields and a real example payload, plus the signature header and retry rules."
url: https://revenuedot.app/docs/api/webhook-events
---

# Which webhook events does RevenueDot send?

RevenueDot POSTs one JSON event per request to each matching webhook: `{ "api_version": "1.0", "event": { ... } }`. The payload matches RevenueCat's webhook format field for field, so existing handlers keep working. Set up, verify and test webhooks with the [webhooks guide](https://revenuedot.app/docs/guides/webhooks.md).

- **Headers:** `Content-Type: application/json`, `User-Agent: RevenueDot-Webhooks/1.0`, `X-RevenueCat-Webhook-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256>`, and your `Authorization` header when you set one.
- **Delivery:** only HTTP 200 counts. Anything else, or no answer within 60 seconds, is retried after 5, 10, 20, 40 and 80 minutes, then marked failed. Deliveries can repeat: deduplicate on `event.id`.
- **Examples:** recorded from a RevenueDot server on 2026-09-30 with Test Store purchases. Events that the Test Store cannot produce (pause, product change, extension, refund reversal, uncancellation, price consent) show the same builder's output with App Store or Google Play values.

| Event | When it is sent |
|---|---|
| [`INITIAL_PURCHASE`](#initial_purchase) | The first purchase of a subscription, including a free trial start. |
| [`RENEWAL`](#renewal) | A new paid period: a renewal, a trial converting (`is_trial_conversion: true`), a lapsed customer resubscribing, or a recovered billing issue. |
| [`CANCELLATION`](#cancellation) | Auto-renew was turned off, or the purchase was refunded. Access continues to `expiration_at_ms` unless it was a refund. A refund has `cancel_reason: CUSTOMER_SUPPORT` and a negative price. |
| [`UNCANCELLATION`](#uncancellation) | Auto-renew was turned back on before the subscription expired. |
| [`NON_RENEWING_PURCHASE`](#non_renewing_purchase) | A one-time purchase: consumable, non-consumable or lifetime. |
| [`SUBSCRIPTION_PAUSED`](#subscription_paused) | A Google Play subscription is scheduled to pause. It will not renew at the end of the period. |
| [`EXPIRATION`](#expiration) | Access ended: the period ran out, billing retry gave up or the subscription paused. |
| [`BILLING_ISSUE`](#billing_issue) | A renewal charge failed. The store retries; access may continue in a grace period. |
| [`PRODUCT_CHANGE`](#product_change) | The customer changed product: an upgrade now, or a downgrade or crossgrade scheduled for the next renewal. `product_id` is the old product. |
| [`SUBSCRIPTION_EXTENDED`](#subscription_extended) | The current period got longer without a new payment: an App Store renewal extension or a Google Play deferral. |
| [`REFUND_REVERSED`](#refund_reversed) | A refund was reversed and access is back. |
| [`PRICE_INCREASE_CONSENT_REQUIRED`](#price_increase_consent_required) | The store asks the customer to accept a price increase. |
| [`PRICE_INCREASE_CONSENT_APPROVED`](#price_increase_consent_approved) | The customer accepted the price increase. |
| [`TRANSFER`](#transfer) | A purchase moved to another customer because that customer restored it (transfer behaviour `transfer` or `transfer_if_no_active`). |
| [`TEST`](#test) | Sent by the dashboard's "Send test event" or `POST .../integrations/webhooks/{id}/test`. Shaped like a purchase. |

Accepted in a webhook's `event_types` filter but never sent yet: `TEMPORARY_ENTITLEMENT_GRANT`, `VIRTUAL_CURRENCY_TRANSACTION`, `INVOICE_ISSUANCE`, `EXPERIMENT_ENROLLMENT`, `PURCHASE_REDEEMED`, `SUBSCRIBER_ALIAS`.

## INITIAL_PURCHASE

The first purchase of a subscription, including a free trial start.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `period_type` | `NORMAL`, `TRIAL`, `INTRO`, `PROMOTIONAL`, `PREPAID` |  |
| `purchased_at_ms` | integer | Start of the period. Epoch milliseconds. |
| `expiration_at_ms` | integer or null | End of the period, or null for lifetime. Epoch milliseconds. |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `entitlement_id` | null | Always null (deprecated in RevenueCat's payload). |
| `entitlement_ids` | array of string | Lookup keys of the entitlements the product unlocks, or null. |
| `presented_offering_id` | string or null | Offering the purchase was made from, when the SDK sent it. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `is_family_share` | boolean |  |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `currency` | string or null | ISO 4217. |
| `price` | number or null | USD. Money moved only on INITIAL_PURCHASE, RENEWAL, NON_RENEWING_PURCHASE, REFUND_REVERSED and refunds (negative); 0 on other events. |
| `price_in_purchased_currency` | number or null | Same as price, in `currency`. |
| `subscriber_attributes` | object |  |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `takehome_percentage` | number | 1 minus the estimated store commission. |
| `tax_percentage` | number | Always 0 today. |
| `commission_percentage` | number | Estimated store commission (0.3 for App Store and Google Play, 0 for Test Store). |
| `offer_code` | null |  |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "66339910-3BFF-49F4-B873-D1283D673DE2",
    "type": "INITIAL_PURCHASE",
    "event_timestamp_ms": 1790800914034,
    "app_id": "appvnrm0a5h",
    "app_user_id": "user_1",
    "original_app_user_id": "user_1",
    "aliases": [
      "user_1"
    ],
    "product_id": "pro_monthly",
    "period_type": "NORMAL",
    "purchased_at_ms": 1790800914000,
    "expiration_at_ms": 1793392914000,
    "environment": "SANDBOX",
    "entitlement_id": null,
    "entitlement_ids": [
      "pro"
    ],
    "presented_offering_id": "default",
    "transaction_id": "test_1790800914000_quickstart",
    "original_transaction_id": "test_1790800914000_quickstart",
    "is_family_share": false,
    "country_code": null,
    "currency": "USD",
    "price": 9.99,
    "price_in_purchased_currency": 9.99,
    "subscriber_attributes": {},
    "store": "TEST_STORE",
    "takehome_percentage": 1,
    "tax_percentage": 0,
    "commission_percentage": 0,
    "offer_code": null
  }
}
```

## RENEWAL

A new paid period: a renewal, a trial converting (`is_trial_conversion: true`), a lapsed customer resubscribing, or a recovered billing issue.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `period_type` | `NORMAL`, `TRIAL`, `INTRO`, `PROMOTIONAL`, `PREPAID` |  |
| `purchased_at_ms` | integer | Start of the period. Epoch milliseconds. |
| `expiration_at_ms` | integer or null | End of the period, or null for lifetime. Epoch milliseconds. |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `entitlement_id` | null | Always null (deprecated in RevenueCat's payload). |
| `entitlement_ids` | array of string | Lookup keys of the entitlements the product unlocks, or null. |
| `presented_offering_id` | string or null | Offering the purchase was made from, when the SDK sent it. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `is_family_share` | boolean |  |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `currency` | string or null | ISO 4217. |
| `price` | number or null | USD. Money moved only on INITIAL_PURCHASE, RENEWAL, NON_RENEWING_PURCHASE, REFUND_REVERSED and refunds (negative); 0 on other events. |
| `price_in_purchased_currency` | number or null | Same as price, in `currency`. |
| `subscriber_attributes` | object |  |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `takehome_percentage` | number | 1 minus the estimated store commission. |
| `tax_percentage` | number | Always 0 today. |
| `commission_percentage` | number | Estimated store commission (0.3 for App Store and Google Play, 0 for Test Store). |
| `offer_code` | null |  |
| `is_trial_conversion` | boolean | True for the first paid period after a free trial. |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "96E753E0-4DEC-4F9B-ABC5-55FBC363769A",
    "type": "RENEWAL",
    "event_timestamp_ms": 1790800923895,
    "app_id": "appvnrm0a5h",
    "app_user_id": "user_trial_conversion",
    "original_app_user_id": "user_trial_conversion",
    "aliases": [
      "user_trial_conversion"
    ],
    "product_id": "pro_monthly",
    "period_type": "NORMAL",
    "purchased_at_ms": 1790800923895,
    "expiration_at_ms": 1793392923895,
    "environment": "SANDBOX",
    "entitlement_id": null,
    "entitlement_ids": [
      "pro"
    ],
    "presented_offering_id": null,
    "transaction_id": "test_1790800923895_c8ba6a2d-5f87-4e08-bb4b-f880624bcd6c..1",
    "original_transaction_id": "test_1790800923895_c8ba6a2d-5f87-4e08-bb4b-f880624bcd6c",
    "is_family_share": false,
    "country_code": null,
    "currency": "USD",
    "price": 9.99,
    "price_in_purchased_currency": 9.99,
    "subscriber_attributes": {},
    "store": "TEST_STORE",
    "takehome_percentage": 1,
    "tax_percentage": 0,
    "commission_percentage": 0,
    "offer_code": null,
    "is_trial_conversion": true
  }
}
```

## CANCELLATION

Auto-renew was turned off, or the purchase was refunded. Access continues to `expiration_at_ms` unless it was a refund. A refund has `cancel_reason: CUSTOMER_SUPPORT` and a negative price.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `period_type` | `NORMAL`, `TRIAL`, `INTRO`, `PROMOTIONAL`, `PREPAID` |  |
| `purchased_at_ms` | integer | Start of the period. Epoch milliseconds. |
| `expiration_at_ms` | integer or null | End of the period, or null for lifetime. Epoch milliseconds. |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `entitlement_id` | null | Always null (deprecated in RevenueCat's payload). |
| `entitlement_ids` | array of string | Lookup keys of the entitlements the product unlocks, or null. |
| `presented_offering_id` | string or null | Offering the purchase was made from, when the SDK sent it. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `is_family_share` | boolean |  |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `currency` | string or null | ISO 4217. |
| `price` | number or null | USD. Money moved only on INITIAL_PURCHASE, RENEWAL, NON_RENEWING_PURCHASE, REFUND_REVERSED and refunds (negative); 0 on other events. |
| `price_in_purchased_currency` | number or null | Same as price, in `currency`. |
| `subscriber_attributes` | object |  |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `takehome_percentage` | number | 1 minus the estimated store commission. |
| `tax_percentage` | number | Always 0 today. |
| `commission_percentage` | number | Estimated store commission (0.3 for App Store and Google Play, 0 for Test Store). |
| `offer_code` | null |  |
| `cancel_reason` | `UNSUBSCRIBE`, `BILLING_ERROR`, `DEVELOPER_INITIATED`, `PRICE_INCREASE`, `CUSTOMER_SUPPORT`, `UNKNOWN` |  |

Example (auto-renew turned off):

```json
{
  "api_version": "1.0",
  "event": {
    "id": "5A47B64A-DBC9-48CF-B0BE-F15041559619",
    "type": "CANCELLATION",
    "event_timestamp_ms": 1790800924019,
    "app_id": "appvnrm0a5h",
    "app_user_id": "user_cancel",
    "original_app_user_id": "user_cancel",
    "aliases": [
      "user_cancel"
    ],
    "product_id": "pro_monthly",
    "period_type": "NORMAL",
    "purchased_at_ms": 1790800924019,
    "expiration_at_ms": 1793392924019,
    "environment": "SANDBOX",
    "entitlement_id": null,
    "entitlement_ids": [
      "pro"
    ],
    "presented_offering_id": null,
    "transaction_id": "test_1790800924019_bd497110-3c45-48fb-a928-437d22de3e2b",
    "original_transaction_id": "test_1790800924019_bd497110-3c45-48fb-a928-437d22de3e2b",
    "is_family_share": false,
    "country_code": null,
    "currency": "USD",
    "price": 0,
    "price_in_purchased_currency": 0,
    "subscriber_attributes": {},
    "store": "TEST_STORE",
    "takehome_percentage": 1,
    "tax_percentage": 0,
    "commission_percentage": 0,
    "offer_code": null,
    "cancel_reason": "UNSUBSCRIBE"
  }
}
```

Example (refund):

```json
{
  "api_version": "1.0",
  "event": {
    "id": "BF6C2BFB-91A8-4AD8-B3BB-5BE5E708B3DF",
    "type": "CANCELLATION",
    "event_timestamp_ms": 1790800924088,
    "app_id": "appvnrm0a5h",
    "app_user_id": "user_refund",
    "original_app_user_id": "user_refund",
    "aliases": [
      "user_refund"
    ],
    "product_id": "pro_monthly",
    "period_type": "NORMAL",
    "purchased_at_ms": 1790800924088,
    "expiration_at_ms": 1793392924088,
    "environment": "SANDBOX",
    "entitlement_id": null,
    "entitlement_ids": [
      "pro"
    ],
    "presented_offering_id": null,
    "transaction_id": "test_1790800924088_d06c5cf7-096e-41e7-8d2c-d91e5ac57fb1",
    "original_transaction_id": "test_1790800924088_d06c5cf7-096e-41e7-8d2c-d91e5ac57fb1",
    "is_family_share": false,
    "country_code": null,
    "currency": "USD",
    "price": -9.99,
    "price_in_purchased_currency": -9.99,
    "subscriber_attributes": {},
    "store": "TEST_STORE",
    "takehome_percentage": 1,
    "tax_percentage": 0,
    "commission_percentage": 0,
    "offer_code": null,
    "cancel_reason": "CUSTOMER_SUPPORT"
  }
}
```

## UNCANCELLATION

Auto-renew was turned back on before the subscription expired.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `period_type` | `NORMAL`, `TRIAL`, `INTRO`, `PROMOTIONAL`, `PREPAID` |  |
| `purchased_at_ms` | integer | Start of the period. Epoch milliseconds. |
| `expiration_at_ms` | integer or null | End of the period, or null for lifetime. Epoch milliseconds. |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `entitlement_id` | null | Always null (deprecated in RevenueCat's payload). |
| `entitlement_ids` | array of string | Lookup keys of the entitlements the product unlocks, or null. |
| `presented_offering_id` | string or null | Offering the purchase was made from, when the SDK sent it. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `is_family_share` | boolean |  |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `currency` | string or null | ISO 4217. |
| `price` | number or null | USD. Money moved only on INITIAL_PURCHASE, RENEWAL, NON_RENEWING_PURCHASE, REFUND_REVERSED and refunds (negative); 0 on other events. |
| `price_in_purchased_currency` | number or null | Same as price, in `currency`. |
| `subscriber_attributes` | object |  |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `takehome_percentage` | number | 1 minus the estimated store commission. |
| `tax_percentage` | number | Always 0 today. |
| `commission_percentage` | number | Estimated store commission (0.3 for App Store and Google Play, 0 for Test Store). |
| `offer_code` | null |  |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "0C1F6F2E-5B7A-4E8B-9D1C-3A2B1C0D9E01",
    "type": "UNCANCELLATION",
    "event_timestamp_ms": 1790800914034,
    "app_id": "appugfw01uy",
    "app_user_id": "user_1",
    "original_app_user_id": "user_1",
    "aliases": [
      "user_1"
    ],
    "product_id": "pro_monthly",
    "period_type": "NORMAL",
    "purchased_at_ms": 1790800914000,
    "expiration_at_ms": 1793392914000,
    "environment": "PRODUCTION",
    "entitlement_id": null,
    "entitlement_ids": [
      "pro"
    ],
    "presented_offering_id": null,
    "transaction_id": "2000000912345679",
    "original_transaction_id": "2000000912345678",
    "is_family_share": false,
    "country_code": "US",
    "currency": "USD",
    "price": 0,
    "price_in_purchased_currency": 0,
    "subscriber_attributes": {},
    "store": "APP_STORE",
    "takehome_percentage": 0.7,
    "tax_percentage": 0,
    "commission_percentage": 0.3,
    "offer_code": null
  }
}
```

## NON_RENEWING_PURCHASE

A one-time purchase: consumable, non-consumable or lifetime.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `period_type` | `NORMAL`, `TRIAL`, `INTRO`, `PROMOTIONAL`, `PREPAID` |  |
| `purchased_at_ms` | integer | Start of the period. Epoch milliseconds. |
| `expiration_at_ms` | integer or null | End of the period, or null for lifetime. Epoch milliseconds. |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `entitlement_id` | null | Always null (deprecated in RevenueCat's payload). |
| `entitlement_ids` | array of string | Lookup keys of the entitlements the product unlocks, or null. |
| `presented_offering_id` | string or null | Offering the purchase was made from, when the SDK sent it. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `is_family_share` | boolean |  |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `currency` | string or null | ISO 4217. |
| `price` | number or null | USD. Money moved only on INITIAL_PURCHASE, RENEWAL, NON_RENEWING_PURCHASE, REFUND_REVERSED and refunds (negative); 0 on other events. |
| `price_in_purchased_currency` | number or null | Same as price, in `currency`. |
| `subscriber_attributes` | object |  |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `takehome_percentage` | number | 1 minus the estimated store commission. |
| `tax_percentage` | number | Always 0 today. |
| `commission_percentage` | number | Estimated store commission (0.3 for App Store and Google Play, 0 for Test Store). |
| `offer_code` | null |  |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "457C5C58-FF87-4CF3-908A-EB31E34846E1",
    "type": "NON_RENEWING_PURCHASE",
    "event_timestamp_ms": 1790800924176,
    "app_id": "appvnrm0a5h",
    "app_user_id": "user_life",
    "original_app_user_id": "user_life",
    "aliases": [
      "user_life"
    ],
    "product_id": "pro_lifetime",
    "period_type": "NORMAL",
    "purchased_at_ms": 1790800924176,
    "expiration_at_ms": null,
    "environment": "SANDBOX",
    "entitlement_id": null,
    "entitlement_ids": [
      "pro"
    ],
    "presented_offering_id": null,
    "transaction_id": "test_1790800924176_a2fda0f6-622f-4e5d-9a5c-003144fb7a2f",
    "original_transaction_id": "test_1790800924176_a2fda0f6-622f-4e5d-9a5c-003144fb7a2f",
    "is_family_share": false,
    "country_code": null,
    "currency": "USD",
    "price": 49.99,
    "price_in_purchased_currency": 49.99,
    "subscriber_attributes": {},
    "store": "TEST_STORE",
    "takehome_percentage": 1,
    "tax_percentage": 0,
    "commission_percentage": 0,
    "offer_code": null
  }
}
```

## SUBSCRIPTION_PAUSED

A Google Play subscription is scheduled to pause. It will not renew at the end of the period.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `period_type` | `NORMAL`, `TRIAL`, `INTRO`, `PROMOTIONAL`, `PREPAID` |  |
| `purchased_at_ms` | integer | Start of the period. Epoch milliseconds. |
| `expiration_at_ms` | integer or null | End of the period, or null for lifetime. Epoch milliseconds. |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `entitlement_id` | null | Always null (deprecated in RevenueCat's payload). |
| `entitlement_ids` | array of string | Lookup keys of the entitlements the product unlocks, or null. |
| `presented_offering_id` | string or null | Offering the purchase was made from, when the SDK sent it. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `is_family_share` | boolean |  |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `currency` | string or null | ISO 4217. |
| `price` | number or null | USD. Money moved only on INITIAL_PURCHASE, RENEWAL, NON_RENEWING_PURCHASE, REFUND_REVERSED and refunds (negative); 0 on other events. |
| `price_in_purchased_currency` | number or null | Same as price, in `currency`. |
| `subscriber_attributes` | object |  |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `takehome_percentage` | number | 1 minus the estimated store commission. |
| `tax_percentage` | number | Always 0 today. |
| `commission_percentage` | number | Estimated store commission (0.3 for App Store and Google Play, 0 for Test Store). |
| `offer_code` | null |  |
| `auto_resume_at_ms` | integer or null | When it resumes. Epoch milliseconds. |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "0C1F6F2E-5B7A-4E8B-9D1C-3A2B1C0D9E02",
    "type": "SUBSCRIPTION_PAUSED",
    "event_timestamp_ms": 1790800914034,
    "app_id": "app9l7z3oij",
    "app_user_id": "user_1",
    "original_app_user_id": "user_1",
    "aliases": [
      "user_1"
    ],
    "product_id": "pro",
    "period_type": "NORMAL",
    "purchased_at_ms": 1790800914000,
    "expiration_at_ms": 1793392914000,
    "environment": "PRODUCTION",
    "entitlement_id": null,
    "entitlement_ids": [
      "pro"
    ],
    "presented_offering_id": null,
    "transaction_id": "GPA.3372-1234-5678-90123..1",
    "original_transaction_id": "GPA.3372-1234-5678-90123",
    "is_family_share": false,
    "country_code": "US",
    "currency": "USD",
    "price": 0,
    "price_in_purchased_currency": 0,
    "subscriber_attributes": {},
    "store": "PLAY_STORE",
    "takehome_percentage": 0.7,
    "tax_percentage": 0,
    "commission_percentage": 0.3,
    "offer_code": null,
    "auto_resume_at_ms": 1796071314000
  }
}
```

## EXPIRATION

Access ended: the period ran out, billing retry gave up or the subscription paused.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `period_type` | `NORMAL`, `TRIAL`, `INTRO`, `PROMOTIONAL`, `PREPAID` |  |
| `purchased_at_ms` | integer | Start of the period. Epoch milliseconds. |
| `expiration_at_ms` | integer or null | End of the period, or null for lifetime. Epoch milliseconds. |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `entitlement_id` | null | Always null (deprecated in RevenueCat's payload). |
| `entitlement_ids` | array of string | Lookup keys of the entitlements the product unlocks, or null. |
| `presented_offering_id` | string or null | Offering the purchase was made from, when the SDK sent it. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `is_family_share` | boolean |  |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `currency` | string or null | ISO 4217. |
| `price` | number or null | USD. Money moved only on INITIAL_PURCHASE, RENEWAL, NON_RENEWING_PURCHASE, REFUND_REVERSED and refunds (negative); 0 on other events. |
| `price_in_purchased_currency` | number or null | Same as price, in `currency`. |
| `subscriber_attributes` | object |  |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `takehome_percentage` | number | 1 minus the estimated store commission. |
| `tax_percentage` | number | Always 0 today. |
| `commission_percentage` | number | Estimated store commission (0.3 for App Store and Google Play, 0 for Test Store). |
| `offer_code` | null |  |
| `expiration_reason` | `UNSUBSCRIBE`, `BILLING_ERROR`, `DEVELOPER_INITIATED`, `PRICE_INCREASE`, `CUSTOMER_SUPPORT`, `UNKNOWN`, `SUBSCRIPTION_PAUSED` |  |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "91A2F69A-FCA7-4C27-9EAE-65C8207BAD7D",
    "type": "EXPIRATION",
    "event_timestamp_ms": 1790800924128,
    "app_id": "appvnrm0a5h",
    "app_user_id": "user_expire",
    "original_app_user_id": "user_expire",
    "aliases": [
      "user_expire"
    ],
    "product_id": "pro_monthly",
    "period_type": "NORMAL",
    "purchased_at_ms": 1788122524128,
    "expiration_at_ms": 1790800924128,
    "environment": "SANDBOX",
    "entitlement_id": null,
    "entitlement_ids": [
      "pro"
    ],
    "presented_offering_id": null,
    "transaction_id": "test_1790800924128_a715897b-5461-4c93-abb6-d8d3ea3d11cd",
    "original_transaction_id": "test_1790800924128_a715897b-5461-4c93-abb6-d8d3ea3d11cd",
    "is_family_share": false,
    "country_code": null,
    "currency": "USD",
    "price": 0,
    "price_in_purchased_currency": 0,
    "subscriber_attributes": {},
    "store": "TEST_STORE",
    "takehome_percentage": 1,
    "tax_percentage": 0,
    "commission_percentage": 0,
    "offer_code": null,
    "expiration_reason": "UNSUBSCRIBE"
  }
}
```

## BILLING_ISSUE

A renewal charge failed. The store retries; access may continue in a grace period.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `period_type` | `NORMAL`, `TRIAL`, `INTRO`, `PROMOTIONAL`, `PREPAID` |  |
| `purchased_at_ms` | integer | Start of the period. Epoch milliseconds. |
| `expiration_at_ms` | integer or null | End of the period, or null for lifetime. Epoch milliseconds. |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `entitlement_id` | null | Always null (deprecated in RevenueCat's payload). |
| `entitlement_ids` | array of string | Lookup keys of the entitlements the product unlocks, or null. |
| `presented_offering_id` | string or null | Offering the purchase was made from, when the SDK sent it. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `is_family_share` | boolean |  |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `currency` | string or null | ISO 4217. |
| `price` | number or null | USD. Money moved only on INITIAL_PURCHASE, RENEWAL, NON_RENEWING_PURCHASE, REFUND_REVERSED and refunds (negative); 0 on other events. |
| `price_in_purchased_currency` | number or null | Same as price, in `currency`. |
| `subscriber_attributes` | object |  |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `takehome_percentage` | number | 1 minus the estimated store commission. |
| `tax_percentage` | number | Always 0 today. |
| `commission_percentage` | number | Estimated store commission (0.3 for App Store and Google Play, 0 for Test Store). |
| `offer_code` | null |  |
| `grace_period_expiration_at_ms` | integer or null | End of the grace period, or null when there is none. Epoch milliseconds. |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "59A0C090-CC89-458B-BDF2-57D9F1447C19",
    "type": "BILLING_ISSUE",
    "event_timestamp_ms": 1790800924056,
    "app_id": "appvnrm0a5h",
    "app_user_id": "user_billing_issue",
    "original_app_user_id": "user_billing_issue",
    "aliases": [
      "user_billing_issue"
    ],
    "product_id": "pro_monthly",
    "period_type": "NORMAL",
    "purchased_at_ms": 1788122524056,
    "expiration_at_ms": 1790800924056,
    "environment": "SANDBOX",
    "entitlement_id": null,
    "entitlement_ids": [
      "pro"
    ],
    "presented_offering_id": null,
    "transaction_id": "test_1790800924056_16f6f7bd-6289-454a-b3b8-1fac8424f8a0",
    "original_transaction_id": "test_1790800924056_16f6f7bd-6289-454a-b3b8-1fac8424f8a0",
    "is_family_share": false,
    "country_code": null,
    "currency": "USD",
    "price": 0,
    "price_in_purchased_currency": 0,
    "subscriber_attributes": {},
    "store": "TEST_STORE",
    "takehome_percentage": 1,
    "tax_percentage": 0,
    "commission_percentage": 0,
    "offer_code": null,
    "grace_period_expiration_at_ms": 1791405724056
  }
}
```

## PRODUCT_CHANGE

The customer changed product: an upgrade now, or a downgrade or crossgrade scheduled for the next renewal. `product_id` is the old product.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `period_type` | `NORMAL`, `TRIAL`, `INTRO`, `PROMOTIONAL`, `PREPAID` |  |
| `purchased_at_ms` | integer | Start of the period. Epoch milliseconds. |
| `expiration_at_ms` | integer or null | End of the period, or null for lifetime. Epoch milliseconds. |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `entitlement_id` | null | Always null (deprecated in RevenueCat's payload). |
| `entitlement_ids` | array of string | Lookup keys of the entitlements the product unlocks, or null. |
| `presented_offering_id` | string or null | Offering the purchase was made from, when the SDK sent it. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `is_family_share` | boolean |  |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `currency` | string or null | ISO 4217. |
| `price` | number or null | USD. Money moved only on INITIAL_PURCHASE, RENEWAL, NON_RENEWING_PURCHASE, REFUND_REVERSED and refunds (negative); 0 on other events. |
| `price_in_purchased_currency` | number or null | Same as price, in `currency`. |
| `subscriber_attributes` | object |  |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `takehome_percentage` | number | 1 minus the estimated store commission. |
| `tax_percentage` | number | Always 0 today. |
| `commission_percentage` | number | Estimated store commission (0.3 for App Store and Google Play, 0 for Test Store). |
| `offer_code` | null |  |
| `new_product_id` | string | The product the customer changed to. |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "0C1F6F2E-5B7A-4E8B-9D1C-3A2B1C0D9E03",
    "type": "PRODUCT_CHANGE",
    "event_timestamp_ms": 1790800914034,
    "app_id": "appugfw01uy",
    "app_user_id": "user_1",
    "original_app_user_id": "user_1",
    "aliases": [
      "user_1"
    ],
    "product_id": "pro_monthly",
    "new_product_id": "pro_annual",
    "period_type": "NORMAL",
    "purchased_at_ms": 1790800914000,
    "expiration_at_ms": 1793392914000,
    "environment": "PRODUCTION",
    "entitlement_id": null,
    "entitlement_ids": [
      "pro"
    ],
    "presented_offering_id": null,
    "transaction_id": "2000000912345679",
    "original_transaction_id": "2000000912345678",
    "is_family_share": false,
    "country_code": "US",
    "currency": "USD",
    "price": 0,
    "price_in_purchased_currency": 0,
    "subscriber_attributes": {},
    "store": "APP_STORE",
    "takehome_percentage": 0.7,
    "tax_percentage": 0,
    "commission_percentage": 0.3,
    "offer_code": null
  }
}
```

## SUBSCRIPTION_EXTENDED

The current period got longer without a new payment: an App Store renewal extension or a Google Play deferral.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `period_type` | `NORMAL`, `TRIAL`, `INTRO`, `PROMOTIONAL`, `PREPAID` |  |
| `purchased_at_ms` | integer | Start of the period. Epoch milliseconds. |
| `expiration_at_ms` | integer or null | End of the period, or null for lifetime. Epoch milliseconds. |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `entitlement_id` | null | Always null (deprecated in RevenueCat's payload). |
| `entitlement_ids` | array of string | Lookup keys of the entitlements the product unlocks, or null. |
| `presented_offering_id` | string or null | Offering the purchase was made from, when the SDK sent it. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `is_family_share` | boolean |  |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `currency` | string or null | ISO 4217. |
| `price` | number or null | USD. Money moved only on INITIAL_PURCHASE, RENEWAL, NON_RENEWING_PURCHASE, REFUND_REVERSED and refunds (negative); 0 on other events. |
| `price_in_purchased_currency` | number or null | Same as price, in `currency`. |
| `subscriber_attributes` | object |  |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `takehome_percentage` | number | 1 minus the estimated store commission. |
| `tax_percentage` | number | Always 0 today. |
| `commission_percentage` | number | Estimated store commission (0.3 for App Store and Google Play, 0 for Test Store). |
| `offer_code` | null |  |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "0C1F6F2E-5B7A-4E8B-9D1C-3A2B1C0D9E04",
    "type": "SUBSCRIPTION_EXTENDED",
    "event_timestamp_ms": 1790800914034,
    "app_id": "appugfw01uy",
    "app_user_id": "user_1",
    "original_app_user_id": "user_1",
    "aliases": [
      "user_1"
    ],
    "product_id": "pro_monthly",
    "period_type": "NORMAL",
    "purchased_at_ms": 1790800914000,
    "expiration_at_ms": 1793997714000,
    "environment": "PRODUCTION",
    "entitlement_id": null,
    "entitlement_ids": [
      "pro"
    ],
    "presented_offering_id": null,
    "transaction_id": "2000000912345679",
    "original_transaction_id": "2000000912345678",
    "is_family_share": false,
    "country_code": "US",
    "currency": "USD",
    "price": 0,
    "price_in_purchased_currency": 0,
    "subscriber_attributes": {},
    "store": "APP_STORE",
    "takehome_percentage": 0.7,
    "tax_percentage": 0,
    "commission_percentage": 0.3,
    "offer_code": null
  }
}
```

## REFUND_REVERSED

A refund was reversed and access is back.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `period_type` | `NORMAL`, `TRIAL`, `INTRO`, `PROMOTIONAL`, `PREPAID` |  |
| `purchased_at_ms` | integer | Start of the period. Epoch milliseconds. |
| `expiration_at_ms` | integer or null | End of the period, or null for lifetime. Epoch milliseconds. |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `entitlement_id` | null | Always null (deprecated in RevenueCat's payload). |
| `entitlement_ids` | array of string | Lookup keys of the entitlements the product unlocks, or null. |
| `presented_offering_id` | string or null | Offering the purchase was made from, when the SDK sent it. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `is_family_share` | boolean |  |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `currency` | string or null | ISO 4217. |
| `price` | number or null | USD. Money moved only on INITIAL_PURCHASE, RENEWAL, NON_RENEWING_PURCHASE, REFUND_REVERSED and refunds (negative); 0 on other events. |
| `price_in_purchased_currency` | number or null | Same as price, in `currency`. |
| `subscriber_attributes` | object |  |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `takehome_percentage` | number | 1 minus the estimated store commission. |
| `tax_percentage` | number | Always 0 today. |
| `commission_percentage` | number | Estimated store commission (0.3 for App Store and Google Play, 0 for Test Store). |
| `offer_code` | null |  |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "0C1F6F2E-5B7A-4E8B-9D1C-3A2B1C0D9E05",
    "type": "REFUND_REVERSED",
    "event_timestamp_ms": 1790800914034,
    "app_id": "appugfw01uy",
    "app_user_id": "user_1",
    "original_app_user_id": "user_1",
    "aliases": [
      "user_1"
    ],
    "product_id": "pro_monthly",
    "period_type": "NORMAL",
    "purchased_at_ms": 1790800914000,
    "expiration_at_ms": 1793392914000,
    "environment": "PRODUCTION",
    "entitlement_id": null,
    "entitlement_ids": [
      "pro"
    ],
    "presented_offering_id": null,
    "transaction_id": "2000000912345679",
    "original_transaction_id": "2000000912345678",
    "is_family_share": false,
    "country_code": "US",
    "currency": "USD",
    "price": 9.99,
    "price_in_purchased_currency": 9.99,
    "subscriber_attributes": {},
    "store": "APP_STORE",
    "takehome_percentage": 0.7,
    "tax_percentage": 0,
    "commission_percentage": 0.3,
    "offer_code": null
  }
}
```

## PRICE_INCREASE_CONSENT_REQUIRED

The store asks the customer to accept a price increase.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `currency` | string or null | ISO 4217. |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `subscriber_attributes` | object |  |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "0C1F6F2E-5B7A-4E8B-9D1C-3A2B1C0D9E06",
    "type": "PRICE_INCREASE_CONSENT_REQUIRED",
    "event_timestamp_ms": 1790800914034,
    "app_id": "appugfw01uy",
    "app_user_id": "user_1",
    "original_app_user_id": "user_1",
    "aliases": [
      "user_1"
    ],
    "product_id": "pro_monthly",
    "environment": "PRODUCTION",
    "transaction_id": "2000000912345679",
    "original_transaction_id": "2000000912345678",
    "country_code": "US",
    "currency": "USD",
    "subscriber_attributes": {},
    "store": "APP_STORE"
  }
}
```

## PRICE_INCREASE_CONSENT_APPROVED

The customer accepted the price increase.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `currency` | string or null | ISO 4217. |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `subscriber_attributes` | object |  |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "0C1F6F2E-5B7A-4E8B-9D1C-3A2B1C0D9E07",
    "type": "PRICE_INCREASE_CONSENT_APPROVED",
    "event_timestamp_ms": 1790800914034,
    "app_id": "appugfw01uy",
    "app_user_id": "user_1",
    "original_app_user_id": "user_1",
    "aliases": [
      "user_1"
    ],
    "product_id": "pro_monthly",
    "environment": "PRODUCTION",
    "transaction_id": "2000000912345679",
    "original_transaction_id": "2000000912345678",
    "country_code": "US",
    "currency": "USD",
    "subscriber_attributes": {},
    "store": "APP_STORE"
  }
}
```

## TRANSFER

A purchase moved to another customer because that customer restored it (transfer behaviour `transfer` or `transfer_if_no_active`).

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `transferred_from` | array of string | App user ids of the previous owner. |
| `transferred_to` | array of string | App user ids of the new owner. |
| `subscriber_attributes` | object |  |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "90CB2D5B-DDD2-4F25-9430-4E5290CC493A",
    "type": "TRANSFER",
    "event_timestamp_ms": 1790800924235,
    "app_id": "appvnrm0a5h",
    "environment": "SANDBOX",
    "subscriber_attributes": {},
    "store": "TEST_STORE",
    "transferred_from": [
      "alice"
    ],
    "transferred_to": [
      "bob"
    ]
  }
}
```

## TEST

Sent by the dashboard's "Send test event" or `POST .../integrations/webhooks/{id}/test`. Shaped like a purchase.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique event id (upper-case UUID). Deduplicate on it. |
| `type` | string | Event type. |
| `event_timestamp_ms` | integer | When RevenueDot recorded the event. Epoch milliseconds. |
| `app_id` | string | RevenueDot app id. Left out for promotional grants. |
| `app_user_id` | string | The app user id the event is about (a non-anonymous alias when there is one). |
| `original_app_user_id` | string | The customer's first app user id. |
| `aliases` | array of string | Every app user id of the customer. |
| `product_id` | string | Store product id. For PRODUCT_CHANGE, the product the customer changed from. |
| `period_type` | `NORMAL`, `TRIAL`, `INTRO`, `PROMOTIONAL`, `PREPAID` |  |
| `purchased_at_ms` | integer | Start of the period. Epoch milliseconds. |
| `expiration_at_ms` | integer or null | End of the period, or null for lifetime. Epoch milliseconds. |
| `environment` | `PRODUCTION`, `SANDBOX` |  |
| `entitlement_id` | null | Always null (deprecated in RevenueCat's payload). |
| `entitlement_ids` | array of string | Lookup keys of the entitlements the product unlocks, or null. |
| `presented_offering_id` | string or null | Offering the purchase was made from, when the SDK sent it. |
| `transaction_id` | string or null | Store transaction id of this period. |
| `original_transaction_id` | string or null | First transaction id of the subscription. |
| `is_family_share` | boolean |  |
| `country_code` | string or null | ISO 3166-1 alpha-2. |
| `currency` | string or null | ISO 4217. |
| `price` | number or null | USD. Money moved only on INITIAL_PURCHASE, RENEWAL, NON_RENEWING_PURCHASE, REFUND_REVERSED and refunds (negative); 0 on other events. |
| `price_in_purchased_currency` | number or null | Same as price, in `currency`. |
| `subscriber_attributes` | object |  |
| `store` | `APP_STORE`, `MAC_APP_STORE`, `PLAY_STORE`, `AMAZON`, `STRIPE`, `RC_BILLING`, `PROMOTIONAL`, `TEST_STORE`, `PADDLE`, `ROKU`, `EXTERNAL` |  |
| `takehome_percentage` | number | 1 minus the estimated store commission. |
| `tax_percentage` | number | Always 0 today. |
| `commission_percentage` | number | Estimated store commission (0.3 for App Store and Google Play, 0 for Test Store). |
| `offer_code` | null |  |

Example:

```json
{
  "api_version": "1.0",
  "event": {
    "id": "F48A3CEE-2785-4001-9A4D-590F95C1A9F0",
    "type": "TEST",
    "event_timestamp_ms": 1790800924267,
    "app_id": "appvnrm0a5h",
    "app_user_id": "$RCAnonymousID:10daafcef1da4cea82bdf031565747fc",
    "original_app_user_id": "$RCAnonymousID:10daafcef1da4cea82bdf031565747fc",
    "aliases": [
      "$RCAnonymousID:10daafcef1da4cea82bdf031565747fc"
    ],
    "product_id": "test_product",
    "period_type": "NORMAL",
    "purchased_at_ms": 1790800924267,
    "expiration_at_ms": 1793392924267,
    "environment": "SANDBOX",
    "entitlement_id": null,
    "entitlement_ids": null,
    "presented_offering_id": null,
    "transaction_id": "test_transaction_id",
    "original_transaction_id": "test_original_transaction_id",
    "is_family_share": false,
    "country_code": "US",
    "currency": "USD",
    "price": 0,
    "price_in_purchased_currency": 0,
    "subscriber_attributes": {},
    "store": "TEST_STORE",
    "takehome_percentage": 1,
    "tax_percentage": 0,
    "commission_percentage": 0,
    "offer_code": null
  }
}
```

## Related

- [Webhooks guide](https://revenuedot.app/docs/guides/webhooks.md): signature verification code, retries, testing
- [Subscriptions and events](https://revenuedot.app/docs/concepts/subscriptions-and-events.md): which store change produces which event
- [OpenAPI document](https://revenuedot.app/docs/api/openapi.yaml): the `webhooks` section
