User Storage
Records are kept for 12 months by default. Longer retention is available on request.
What it does
A record is created for every user who logs into your app and buys something. It holds their subscriptions and non-consumables together with the current state of each (e.g. active, expired, cancelled).
Your app reads that record with the Get User endpoint, or through the game engine SDKs. Go through the returned list and unlock what is still active, or tell the user why something stopped working.
Consumables are not stored. They are spent at the moment of purchase, so there is nothing to restore.
User Storage is required for subscriptions. Without it there is nowhere to record that a subscription renewed, expired or was cancelled. For one-time purchases it is optional.
User Behaviour
Set this per application in App Setup. It decides whether purchases are tied to a user at all, and what happens when the same receipt arrives from a different account.
| Mode | Effect | When to use it |
|---|---|---|
Disabled | Default. Nothing is stored. Each validation is answered on its own. | You keep track of who owns what yourself, or do not want to rely on it all. |
Alias | One original user plus up to 5 more may share a purchase. The 7th account is rejected. | Households or shared devices, where some sharing is expected. |
Transfer | The purchase belongs to one user. It can move to another account, but only once every 5 days. | Users who change accounts now and then, without leaving the door open. |
Block | The purchase belongs to one user and stays there. Any other account is rejected. | Highest protection. Requires that users can recover their login, or they lose access to what they bought. |
Every mode other than Disabled requires a user identifier on each validation request. If you use our SDKs, set User ID on the IAPGUARD component before initialisation and pick the matching Inventory Request Type.
User identifiers
Purchases are only as safe as the identifier they are tied to. You supply that identifier — we do not ship an authentication system, because the right one depends on your platform and engine.
Use a native provider such as Play Games Services or Sign in with Apple, a cross-platform login such as Facebook Login, or your own backend. Tell users why signing in is worth it: their purchases follow them to a new device and across stores.
| Do | Do not |
|---|---|
| Use an identifier that cannot be guessed | Use an email address or other personal data |
| Include randomisation | Use a device identifier such as IDFA or Ad-ID, which is not unique |
| Keep the same identifier across logins | Hardcode an identifier, which makes every user the same person |
Identifiers may be at most 100 characters, and may not be empty, null or voided.
If you send no identifier, the server creates one for you and returns it, for example 3ed5e911-5eaa-46b3-8efc-74612d2b878d. Save it on the device, or in the platform's key-value storage such as Google Play Games Services or iCloud, and send it with every later request. Lose it and the user loses their inventory.
Requests from a single client can be rate limited. Ask for the inventory once after user login, not on a timer or every scene load.
Expiration
The record is deleted on its expiration date. Every new transaction added to it resets that date, so a user who buys something every few months never expires.
Consumables are not stored, but they still push the date forward as long as the record already holds at least one active product.
If your subscriptions renew less often than the retention period — a yearly subscription against 12 months of storage, for example — the record can expire between two renewals. Ask for a retention period longer than your longest subscription cycle.
If a record does expire, the user can rebuild it by running the store's restore purchases flow in your app.