# Product access

For subscriptions, the **`productAccess`** array on the user object is the source of truth for **what a user can use right now**. Your application gates features and content by checking whether a product ID appears in that array.

***

## What it contains

`productAccess` is an array of **product IDs** — strings like `p-live-pro` for live products or `p-test-abc123` for sandbox products. Each ID corresponds to a subscription the user **currently has active access to**. The array can hold zero, one, or many IDs depending on what the user has purchased.

The full user object that contains this array is documented in [User object](/reference/authentication/user-object.md).

***

## When it's populated and updated

| When                                        | What happens                                                                                                               |
| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| After successful checkout                   | The purchased product ID is added to `productAccess`. `userChange` fires with `event: 'checkout'`.                         |
| On session restore                          | tiun rebuilds `productAccess` for the returning user. `userChange` fires with `event: 'init'`.                             |
| After login                                 | `productAccess` reflects whatever subscriptions are active for that user. `userChange` fires with `event: 'login'`.        |
| When a subscription expires or is cancelled | The product ID is **removed** from `productAccess` and `userChange` fires. The customer should lose access at that moment. |
| After logout                                | The user object becomes `null`; there is no `productAccess` to check.                                                      |

You don't manage renewals yourself — tiun handles billing cycles and keeps `productAccess` consistent with what the customer has paid for. See [Subscriptions](/reference/checkout/subscriptions.md) for the full lifecycle.

***

## Checking access

Read `productAccess` from the `userChange` payload (preferred) or via `tiun.user`:

```javascript
tiun.on('userChange', (data) => {
  if (!data.isAuthenticated) return;

  const hasPro = data.user.productAccess.includes('p-live-pro');
  const hasLight = data.user.productAccess.includes('p-live-light');

  if (hasPro) {
    renderProExperience();
  } else if (hasLight) {
    renderLightExperience();
  }
});
```

Replace the example IDs with the product IDs from your [tiun.business dashboard](https://my.tiun.business/). For the broader UI gating pattern that combines this with `isAuthenticated`, see [Protecting content](/reference/authentication/protecting-content.md).

{% hint style="info" %}
Prefer `userChange` over polling `tiun.user`. The event fires precisely when access changes, so your gates stay in sync without manual refresh logic.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tiun.io/reference/checkout/product-access.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
