Skip to content

Commit bec08b2

Browse files
Sharing paid access — improvements
1 parent caf7cd1 commit bec08b2

2 files changed

Lines changed: 32 additions & 0 deletions

File tree

src/content/docs/version-3.0/event-flows.mdx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,18 @@ For Apple Family Sharing transactions (`in_app_ownership_type=FAMILY_SHARED`), o
329329
If a user taps **Restore Purchases** but already has access on the same profile, the restore is a no-op and no webhook events fire. The events in this section only fire when access actually transfers between profiles.
330330
:::
331331

332+
For an at-a-glance view of which events fire when a second profile claims an existing subscription, use this matrix. The sections that follow show the full JSON payload for each flow.
333+
334+
| Event | Enabled (default) | Transfer access to new user | Disabled |
335+
| --- | --- | --- | --- |
336+
| New profile: **Access level updated** (`is_active=true`) | Fires | Fires | Does not fire |
337+
| Old profile: **Access level updated** (`is_active=false`) | Does not fire — both profiles keep access | Fires when the new identified device propagates the transaction | Does not fire — the original profile keeps access |
338+
| `profiles_sharing_access_level` field on the new event | Lists the other profiles that share the access level | `null` | Not applicable — no event fires |
339+
340+
Renewals, refunds, and expiries on a transferred subscription continue to fire `subscription_renewed`, `subscription_refunded`, and `subscription_expired` events on whichever profile currently holds the access level. The transfer event itself does not emit a `subscription_started` event, because no new transaction is recorded — only the attribution changes.
341+
342+
For per-mode contract details, see [Practical reference](sharing-paid-access-between-user-accounts#practical-reference).
343+
332344
### Transfer Access to New User Flow
333345

334346
The recommended option is to transfer the access level to the new user. This preserves the original user’s transaction history for consistent analytics. Only 2 **Access level updated** events will be created:

src/content/docs/version-3.0/sharing-paid-access-between-user-accounts.mdx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ When you disable the default setting, and enable **Transfer access to new user**
6565
The switch occurs when a user triggers a new store event: for example, renews the subscription, or restores their purchases.
6666
:::
6767

68+
:::important
69+
Adapty revokes the old profile only when the new profile has a [Customer User ID](identifying-users#set-customer-user-id-on-configuration) at the moment the SDK propagates the transaction. If `restorePurchases` runs on an anonymous profile, both the old Customer User ID and the new anonymous profile end up with the access level. The old profile is revoked later, when you identify the anonymous profile.
70+
71+
To avoid this, call the SDK methods in order: `activate``identify``restorePurchases`.
72+
:::
73+
6874
## Disable paid access sharing
6975

7076
This setting is **only appropriate** for applications with **mandatory authentication** or an independent access management implementation. In other cases, the users may not be able to access their purchases, and your application risks **failing the mandatory store review**.
@@ -79,6 +85,16 @@ When you disable paid access sharing, you prevent customer IDs from inheriting p
7985
In emergency situations, you may need to [delete a user profile](api-adapty/operations/deleteProfile) in order for the next available profile (whether identified or anonymous) to claim its access level.
8086
:::
8187

88+
## Practical reference
89+
90+
After you pick a mode, the contracts below describe what to expect: which profiles see the access, when the old profile loses it, and which webhook events fire.
91+
92+
| Mode | Multiple profiles share one purchase? | Old profile revoked on transfer? | When the old profile is revoked | Webhook events when a second profile claims the subscription |
93+
| --- | --- | --- | --- | --- |
94+
| **Enabled (default)** | Yes — every profile that restores or signs in inherits access | Never | N/A | `access_level_updated` (`is_active=true`) for each new profile that inherits |
95+
| **Transfer access to new user** | No — exclusive, but movable between profiles | Yes | Immediately when the new identified device propagates the transaction (`restorePurchases`, identify, or the next store-side event) | New profile: `access_level_updated` (`is_active=true`). Old profile: `access_level_updated` (`is_active=false`) |
96+
| **Disabled** | No — one Customer User ID per purchase, permanently | N/A — access never transfers | N/A | None on the second profile. The SDK shows no access for it |
97+
8298
## Sharing paid access on sandbox
8399

84100
You can set a sharing paid access policy specifically for the sandbox environment. When you test purchases in the sandbox environment, expect the following behavior:
@@ -89,6 +105,10 @@ You can set a sharing paid access policy specifically for the sandbox environmen
89105

90106
This behavior occurs **independently of your sharing paid access setting**. Your app doesn't display the paywall, you can't buy the product. The only solution is to **clear your account's purchase history**. Follow the [sandbox testing guide](test-purchases-in-sandbox) for in-depth instructions.
91107

108+
:::warning
109+
Sandbox subscriptions on Apple auto-renew every few minutes. These rapid renewals can swap which profile Adapty treats as the [parent](how-profiles-work#parent-and-inheritor-profiles) — a chain pattern production rarely reproduces. Test the mode you ship in production, and confirm behavior with a real Apple ID before drawing conclusions from sandbox.
110+
:::
111+
92112
## Paid access sharing in analytics
93113

94114
* Adapty logs transactions as they occur. A single transaction may be associated with more than one profile, but isn't counted more than once.

0 commit comments

Comments
 (0)