Purchase Status Updates
This event is triggered whenever a change happens to a purchase throughout its lifecycle.
The purchase.updated
data structure provides you all the relevant information known about the purchase at the time the event is sent. It is delivered to you via your webhook.
Interested in a Direct Connection to your Data Warehouse?
Contact [email protected] if you're interested in receiving this data in bulk or integrated directly into your data warehouse.
Delivery Timing
Events are sent in a near real-time. You will receive a purchase.updated
event on a 2 minute delay after the update occurred. If an update occurs to a purchase within the 2 minutes, the timer is reset until there are no changes detected from the Nami SDK or the Platform Provider before sending on to you.
This mechanism ensures the data is provided in a timely fashion, while also cutting down on the number of events sent for one purchase.
Multiple updates for a purchase are possible. The collapse_key
is the primary key for a specific purchase. Store the most recent version of each purchase update for a given collapse_key
to have a complete view of all purchases Nami knows about.
Event Data Structure
Top-Level Elements
Field Name | Type | Definition |
---|---|---|
billing_cycles | Integer or Null | The number of total billing cycles that have occurred for this purchase. The original purchase counts as first cycle. |
canceled_at | Timestamp or Null | When the subscription was cancelled. |
current_term_length | String (ISO-8601 Time Interval Format) or Null | The current term length of the subscriptions. Requires Platform Product Sync to be enabled. Contact support for details. |
devices_with_access | List of of DevicesWithAccess | A list of devices that have access to the purchase. Ordered by device claim date, oldest to newest. |
entitlements | List of PurchaseEntitlements | A list of entitlements the purchase grants. |
expires_at | Timestamp or Null | The current time when the subscription will expire. |
is_active | Boolean or Null | Whether the purchase is currently active. |
is_auto_renewable | Boolean or Null | Whether the purchase is auto-renewing. |
is_free_trial_conversion | Boolean or Null | Whether the purchase converted from a free trial. Note: If Nami did not observe the original purchase, we do not know if the purchase was a free trial. In this case, this field will be null. |
is_in_trial_period | Boolean or Null | Whether the purchase is currently in a trial period. Note: We only know if the purchase is in a free trial, if we observed the original purchase. |
is_production | Boolean | Whether the purchase occurred in production or not. |
is_in_intro_offer_period | Boolean or Null | Whether the purchase is in an introductory offer period. |
last_seen_device_id | UUID or Null | The identifier for the last seen device with access to this purchase. |
last_seen_external_id | String or Null | The external identifier associated with this purchase. |
not_before | Timestamp or Null | When this purchase became active. |
original_purchase_guid | String or Null | A reference to a previous purchase in the case of a plan change. |
payment_issues_began_at | Timestamp or Null | When payment issues started. |
platform_type | String | The platform type (e.g. apple, google) |
price_in_usd | Decimal or Null | The estimated pricing in USD using currency exchange rates from the day of the purchase. |
product_ref_id | String | The identifier for this purchase as configured with the app store platform. |
purchase_country | String (2 Character Enum) or Null | The country code for the purchase from the app store platform. |
purchase_currency | String (3 Character Enum) or Null | The currency code for the purchase from the app store platform. |
purchase_guid | String | The identifier provided for the purchase from the app store platform. |
purchase_price | Decimal or Null | The local price for the purchase from the app store platform. |
revoked_at | Timestamp or Null | When the purchase was revoked. |
transaction_id | String | The transaction identifier for the purchase from the app store platform. |
DevicesWithAccess
Elements
DevicesWithAccess
ElementsA list of devices that have access to the purchase.
Field Name | Type | Definition |
---|---|---|
claim_type | String | How a device gained access to purchase (original_purchaser, family_sharing, cross_platform_shared, etc). |
first_launch | Timestamp | The time the device first registered with Nami |
id | UUID | The device install's unique identifier. |
last_active | Timestamp | The end time of the last known app session. |
platform_type | String | What app platform of the device (apple, google) |
PurchaseEntitlement
Elements
PurchaseEntitlement
ElementsA list of entitlements the purchase grants.
Field Name | Type | Description |
---|---|---|
description | String | Entitlement description in Nami Control Center. |
entitlement_ref_id | String | Entitlement reference in Nami Control Center. |
id | UUID | Nami internal identifier for an entitlement. |
name | String | Entitlement display name in Nami Control Center. |
type | String | binary_auth is an entitlement to gate features with an βon/offβ switch. |
EventAttributes
Elements
EventAttributes
ElementsMetadata which can be useful when processing this event.
Field Name | Type | Definition |
---|---|---|
app_id | UUID or Null | Nami App ID (if applicable) for the event. |
collapse_key | String | Collapse Key is the primary key for versioned events. |
event_id | UUID | Unique ID for a specific event. |
event_time | Timestamp | UTC Timestamp of Event in ISO-8601 format. |
event_type | String | The type of event. |
org_id | UUID or Null | Your Nami Org ID. |
platform_id | UUID or Null | App Platform ID (if applicable) for the event. |
subscription_id | UUID or Null | Subscription that caused the event delivery. |
version | String | Version of event format |
Example Payload
{
"attributes": {
"app_id": "486c1c9f-37b1-4873-9ff6-e78e563d184a",
"collapse_key": "6b275a67-0bbb-4f3a-99b9-6600bf711993",
"event_id": "b4ad74e4-8986-461b-aa08-473a19c608b2",
"event_time": "2022-09-20T20:12:35.818538Z",
"event_type": "purchase.updated",
"org_id": "a8d39aa3-e393-46ee-8cb4-e8b8c0bd50e7",
"platform_id": "aaf69dba-ef67-40f5-82ec-c7623a2848a6",
"subscription_id": "7e0977f8-27c9-49c5-8356-e82cbf34b161",
"version": "2.0"
},
"data": {
"billing_cycles": 5,
"canceled_at": null,
"current_term_length": null,
"devices_with_access": [
{
"claim_type": "original_purchaser",
"first_launch": "2022-09-19T23:15:25.201213Z",
"id": "eadea2bf-79b3-444c-b3a4-9e0127abc840",
"last_active": "2022-09-20T19:37:38.713391Z",
"platform_type": "google"
}
],
"entitlements": [
{
"description": null,
"entitlement_ref_id": "premium",
"id": "71a267cd-de70-4ba9-b743-24ef2b4be3ae",
"name": "Premium",
"type": "binary_auth"
},
{
"description": null,
"entitlement_ref_id": "gold",
"id": "c1ec3e32-25b5-4eb9-b1e1-6fd429581b4a",
"name": "Gold",
"type": "binary_auth"
}
],
"expires_at": "2022-09-20T20:19:31.302000Z",
"is_active": true,
"is_auto_renewable": true,
"is_free_trial_conversion": false,
"is_in_intro_offer_period": false,
"is_in_trial_period": false,
"is_production": false,
"last_seen_device_id": "eadea2bf-79b3-444c-b3a4-9e0127abc840",
"last_seen_external_id": null,
"not_before": "2022-09-20T19:37:30.193000Z",
"original_purchase_guid": null,
"payment_issues_began_at": null,
"platform_type": "google",
"price_in_usd": "4.99",
"product_ref_id": "your_product_name",
"purchase_country": "US",
"purchase_currency": "USD",
"purchase_guid": "google_play_token_or_apple_original_transacation_id",
"purchase_price": "4.9900",
"revoked_at": null,
"transaction_id": "GPA.1234-5678-9012-12345..3"
}
}
Switching from RevenueCat?
For customers switching from RevenueCat, this event provides substantially similar information as the ETL Exports. Here's what you need to know about the differences between RevenueCat ETL Exports and Nami Purchase Updated events:
Data structure differences
RevenueCat Field | Nami Field | Notes |
---|---|---|
renewal_number | billing_cycles | Nami counts the original purchase as first cycle |
unsubscribe_detected_at | canceled_at | |
entitlement_identifiers | entitlements | Entitlements are provided as objects instead of a list of strings. |
end_time | expires_at | |
n/a | is_active | |
is_trial_conversion | is_free_trial_conversion | If we did not observe the original purchase, we may not know if the purchase was a free trial conversion. In this case, we will provide a null value for this field. |
is_trial_period | is_in_trial_period | If we did not observe the original purchase, we may not know if the purchase is in a free trial. In this case, we will provide a null value for this field. |
is_sandbox | is_production | |
rc_last_seen_app_user_id_alias | last_seen_device_id | RevenueCat doesnβt distinguish an external ID from an anonymous device ID. |
rc_last_seen_app_user_id_alias | last_seen_external_id | RevenueCat seems to provide either the external ID or the anonymous ID but not both. |
start_time | not_before | |
n/a | original_purchase_guid | A reference to the original store purchase identifier, which may be available in the case of cross grades, downgrades, or upgrades. |
billing_issues_detected_at | payment_issues_began_at | |
store | platform_type | |
product_identifier | product_ref_id | |
country | purchase_country | |
purchased_currency | purchase_currency | |
original_store_transaction_id | purchase_guid | |
price_in_purchased_currency | purchase_price | |
refunded_at | revoked_at | More precise definition as we know if a subscription is revoked, but we do not always know if that involved a refund. |
store_transaction_id | transaction_id |
Updated about 2 years ago