Events
17 subscription events that can be sent to 3rd party analytics and webhook. These events will help you to better understand the behavior of your subscribers
Apple and Google send subscription events directly to the server using App Store Server Notifications and Real-time Developer Notifications (RTDN). Therefore, mobile apps can not send events to analytical systems correctly and on-time. For example, if the user subscribed and then didn't open the app, without a server developer will get zero information about subscription status.
After installing Adapty SDK and setting up App Store Server Notifications for iOS and Real-time Developer Notifications (RTDN). for Android, Adapty receives info about your customer behavior and converts it into human-readable events.
Adapty processes events into human-readable format instantly as they created and enriches them with additional information, such as customer ID, consecutive payments, store commission info, and others. Besides that Apple doesn't send events about subscription renewals but we do.
Events
Event Name | Description |
---|---|
subscription_initial_purchase | A user has activated a subscription without a trial period i.e. he was billed instantly |
subscription_renewed | A subscription was renewed and the user was charged. For both trial and non-trial subscriptions, this event is sent starting from the second billing |
subscription_expired | A user has canceled a subscription and it is completely finished |
trial_started | A user has activated a trial subscription |
trial_converted | A trial period has ended and the user was billed, i.e. first purchase was made |
trial_cancelled | A trial has expired without converting to a subscription |
non_subscription_purchase | Any non-subscription purchase e.g. lifetime access or consumable product such as coins |
billing_issue_detected | An attempt to charge the user was made, but a billing issue happened. Usually, it means the user doesn't have enough card balance |
entered_grace_period | The payment was not successful and the user entered into a grace period. The user still has access to the premium features of your app until the grace period is finished |
auto_renew_off | A user turned off subscription auto-renewal during the trial. A user still has access to premium features of your app until the end of the trial period |
auto_renew_on | A user turned on subscription auto-renewal during the trial period |
auto_renew_off_subscription | A user turned off subscription auto-renewal. A user still has access to the premium features of your app until the end of the subscription period |
auto_renew_on_subscription | A user turned on subscription auto-renewal |
subscription_refunded | A subscription was refunded (e.g. by Apple support) |
non_subscription_purchase_refunded | Non-subscription purchase was refunded |
subscription_paused | User activated subscription pause (Android only) |
access_level_updated | User's access level updated (Webhook only) |
SUBSCRIPTION_EXPIRED(previously SUBSCRIPTION_CANCELED) event means that the subscription completely finished and the user has no longer access to the premium features of the app. When the user unsubscribes, AUTO_RENEW_OFF or AUTO_RENEW_OFF_SUBSCRIPTION is sent. The same logic applied to TRIAL_CANCELLED.
The events above fully cover the users' state in terms of purchases. Let's look at some examples.
Example 1
The user has activated a monthly subscription on April 1st with 7 days trial. On the 4th day, he unsubscribed.
In that case following events will be sent:
- trial_started on April 1st
- auto_renew_off on 4th April
- trial_cancelled on 7th April
Example 2
The user has activated a monthly subscription on April 1st with 7 days trial. On the 10th day, he unsubscribed.
In that case following events will be sent:
- trial_started on April 1st
- trial_converted on April 7th
- auto_renew_off_subscription on April 10th
- subscription_cancelled on May 1st
Properties
Property | Type | Description |
---|---|---|
price_usd | float | Product price before Apple/Google cut. Revenue. |
proceeds_usd | float | Product price after Apple/Google cut. Net revenue. |
transaction_id | str | A unique identifier for a transaction such as a purchase or renewal. |
original_transaction_id | str | The transaction identifier of the original purchase. |
purchase_date | ISO 8601 date | The date and time of product purchase. |
original_purchase_date | ISO 8601 date | The date and time of the original purchase. |
environment | str | Could be Sandbox or Production. |
vendor_product_id | str | Product id in Apple/Google store. |
event_datetime | ISO 8601 date | The date and time of the event. |
store | str | Could be app_store or play_store. |
trial_duration | str | Duration of a trial period in days. Sent in a format "{} days" , for example, "7 days". |
cancellation_reason | str |
A reason why the user canceled a subscription. Can be
|
subscription_expires_at | ISO 8601 date | The Expiration date of subscription. Usually in the future. |
consecutive_payments | int | The number of periods, that a user is subscribed without interruptions. Includes the current period. |
rate_after_first_year | bool | Boolean indicates that a vendor reduces cuts to 15%. Apple and Google have 30% first-year cut and 15% after it. |
paywall_name | str | Name of the paywall where the transaction originated. |
paywall_revision | int | Revision of the paywall where the transaction originated. |
developer_id | str | Developer (SDK) ID of the paywall where the transaction originated. |
ab_test_name | str | Name of the A/B test where the transaction originated. |
ab_test_revision | int | Revision of the A/B test where the transaction originated. |
profile_event_id | uuid | Unique event ID that can be used for deduplication. |
store_country | str | Country sent to us by the store. |
profile_country | str | Determined by Adapty, based on profile IP |
profile_total_revenue_usd | float | Total revenue for the profile, refunds included. |
variation_id | uuid | Unique ID of the paywall where the purchase was made. |
Each event has the following properties:
transaction_id, original_transaction_id, purchase_date, original_purchase_date, environment, vendor_product_id, event_datetime, store
In addition, some events have additional properties. For the events subscription_refunded
and non_subscription_purchase_refunded
, it is mandatory to provide the values of price_usd
and proceeds_usd
as additional properties.
Event Name | Properties |
---|---|
subscription_initial_purchase | price_usd, proceeds_usd, subscription_expires_at, consecutive_payments, rate_after_first_year, trial_duration |
subscription_renewed | price_usd, proceeds_usd, subscription_expires_at, consecutive_payments, rate_after_first_year, trial_duration |
subscription_cancelled | cancellation_reason, trial_duration |
trial_started | subscription_expires_at, trial_duration |
trial_converted | price_usd, proceeds_usd, subscription_expires_at, consecutive_payments, rate_after_first_year, trial_duration |
trial_cancelled | cancellation_reason, trial_duration |
non_subscription_purchase | price_usd, proceeds_usd |
billing_issue_detected | subscription_expires_at, trial_duration |
entered_grace_period | subscription_expires_at, trial_duration |
Event example
{
"price_usd": 9.99,
"proceeds_usd": 6.99,
"transaction_id": "1000000628581600",
"original_transaction_id": "1000000628581600",
"purchase_date": "2020-02-18T18:40:22.000000+0000",
"original_purchase_date": "2020-02-18T18:40:22.000000+0000",
"environment": "Sandbox",
"vendor_product_id": "premium",
"event_datetime": "2020-02-18T18:40:22.000000+0000",
"store": "app_store"
}
Adapty sends events to your server and 3rd party analytical systems.
Access Level Updated
Adapty has a special event access_level_updated
. It is sent only to webhook integration every time the access level is updated/set for a specific customer. Use this event to update a customer's subscription in your database/system. Before you had to keep track of several events to sync subscription state and some cases were not covered, like setting access level manually from Adapty CRM. Now, no matter what was the source of access level changes, you will always receive a dedicated event for that, therefore it's more precise and has more details than subscription_renewed
, trial_started
, entered_grace_period
, etc.

Property | Type |
---|---|
transaction_id | str |
original_transaction_id | str |
event_datetime | ISO 8601 date |
access_level_id | str |
is_active | bool |
is_lifetime | bool |
expires_at | ISO 8601 date |
starts_at | ISO 8601 date |
will_renew | bool |
vendor_product_id | str |
store | str |
activated_at | ISO 8601 date |
renewed_at | ISO 8601 date |
billing_issue_detected_at | ISO 8601 date |
is_in_grace_period | bool |
active_introductory_offer_type | str |
active_promotional_offer_type | str |
active_promotional_offer_id | str |
cancellation_reason | str |
is_refund | bool |
We don't send access_level_updated
upon subscription expiration - please, refer to expires_at value to end the subscriptions on your side.
Sending Failed
We determine the deliverability based on http status and consider everything outside 200-399 range to be a fail.
If the event failed to reach the integration, Adapty will perform 3 more attempts to send it.
The intervals for each retry are 1, 3 and 5 minutes respectively.
Updated 2 months ago