> For the complete documentation index, see [llms.txt](https://docs.webtonative.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.webtonative.com/javascript-apis/age-safety.md).

# Age Safety

Functions to support age assurance and regulatory compliance in your app. You can request the user's age signals / declared age range from the platform's native age-verification service, and (on iOS) notify the system about a significant change to your app's content.

These APIs wrap **Google Play's Age Signals API** on Android and Apple's **Declared Age Range** framework on iOS. They are intended for apps that need to gate content or features by age in regulated regions.

{% hint style="info" %}
You'll need to import the javascript file in your website before starting from this [link](https://docs.webtonative.com/javascript-apis/getting-started).
{% endhint %}

{% hint style="warning" %}
**Platform support:** `getAgeSignals` works on Android and iOS. `notifySignificantChange` is **iOS only**. The native age-range/permission APIs on iOS require **iOS 26.2 or later**.

**Store services required:** Both functions only run when the app build has store services enabled. If store services are disabled, the call is ignored and no callback fires.
{% endhint %}

## getAgeSignals

Requests the platform's age signals for the current user against a configured age gate.

* **Android** — calls the Google Play Age Signals API and returns the user's verification status and (when available) an age range.
* **iOS** — calls `AgeRangeService.requestAgeRange`, which may present a system sheet, and returns the declared age range. Requires iOS 26.2+.

The response shape differs between platforms (see the per-platform tables below), so check `success` first and then read the fields relevant to the running platform.

{% tabs %}
{% tab title="Plain Javascript" %}

```javascript
window.WTN.AgeSafety.getAgeSignals({
  ageGates: 18,
  callback: function (response) {
    console.log(response);
  },
});
```

{% endtab %}

{% tab title="npm" %}

```javascript
import { getAgeSignals } from "webtonative/AgeSafety";

getAgeSignals({
  ageGates: 18,
  callback: (response) => {
    console.log(response);
  },
});
```

{% endtab %}
{% endtabs %}

**Parameters:**

| Key        | Type       | Required | Description                                                                                                                      |
| ---------- | ---------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `ageGates` | `Number`   | No       | The primary age threshold to check against, e.g. `18`. On iOS this drives the age band returned by the system. Defaults to `18`. |
| `callback` | `Function` | No       | Callback function invoked with the age-signals response.                                                                         |

{% hint style="info" %}
**iOS note:** The underlying iOS API supports up to three age gates (creating up to four age bands, each spanning at least 2 years). The JavaScript API currently sends a single primary `ageGates` value.
{% endhint %}

### Callback Response — common fields

| Key       | Type      | Description                                                                             |
| --------- | --------- | --------------------------------------------------------------------------------------- |
| `type`    | `String`  | Always `"getAgeSignals"`.                                                               |
| `success` | `Boolean` | `true` if the age signals were retrieved successfully, `false` otherwise.               |
| `error`   | `String`  | Present when `success` is `false`. A human-readable message describing what went wrong. |

### Callback Response — Android

Returned by Google Play's Age Signals API.

| Key                      | Type     | Description                                                                    |
| ------------------------ | -------- | ------------------------------------------------------------------------------ |
| `userStatus`             | `String` | The user's age-verification status as reported by Play.                        |
| `ageLower`               | `Number` | Present when available. The lower bound of the user's age range.               |
| `ageUpper`               | `Number` | Present when available. The upper bound of the user's age range.               |
| `installId`              | `String` | Present when available. An install identifier associated with the signals.     |
| `mostRecentApprovalDate` | `String` | Present when available. The date of the most recent age approval, as a string. |

### Callback Response — iOS

Returned by Apple's Declared Age Range framework (iOS 26.2+).

| Key                        | Type       | Description                                                                                                                             |
| -------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `isEligibleForAgeFeatures` | `Boolean`  | `true` if the user is in a regulated region where age assurance is required. `false` means age sharing is voluntary.                    |
| `declined`                 | `Boolean`  | `true` if the user declined to share their age range (or no sharing occurred in a non-regulated region).                                |
| `lowerBound`               | `Number`   | Present when sharing. The lower bound of the declared age range. Absent (`nil`) means the user is **below** the lowest age gate.        |
| `upperBound`               | `Number`   | Present when sharing. The upper bound of the declared age range. Absent (`nil`) means the user is **at or above** the highest age gate. |
| `activeParentalControls`   | `String[]` | Active parental controls in effect, e.g. `["communicationLimits"]`. Empty array when none.                                              |
| `isSupervised`             | `Boolean`  | `true` if any parental controls are active (i.e. `activeParentalControls` is non-empty).                                                |
| `ageRangeDeclaration`      | `String`   | How the age was established. See the table below. Present only when sharing.                                                            |
| `errorCode`                | `String`   | Present on certain failures. One of `"invalidRequest"` or `"notAvailable"` (see error table).                                           |

**`ageRangeDeclaration` values (iOS):**

| Value                          | Description                                   |
| ------------------------------ | --------------------------------------------- |
| `selfDeclared`                 | Age was declared by the user themselves.      |
| `guardianDeclared`             | Age was declared by a guardian.               |
| `paymentChecked`               | Age was verified via a payment method.        |
| `governmentIDChecked`          | Age was verified via a government ID.         |
| `checkedByOtherMethod`         | Age was verified by another method.           |
| `guardianPaymentChecked`       | Guardian's age verified via a payment method. |
| `guardianGovernmentIDChecked`  | Guardian's age verified via a government ID.  |
| `guardianCheckedByOtherMethod` | Guardian's age verified by another method.    |
| `unknown`                      | An unrecognized declaration type.             |

**iOS `errorCode` values:**

| Code             | Description                                                                                             |
| ---------------- | ------------------------------------------------------------------------------------------------------- |
| `invalidRequest` | The age gates were invalid — each band must be ≥ 2 years, with a maximum of 3 gates in ascending order. |
| `notAvailable`   | The age range service is not available on this device (e.g. no iCloud account, parental restrictions).  |

**Example:**

```javascript
window.WTN.AgeSafety.getAgeSignals({
  ageGates: 18,
  callback: function (response) {
    if (!response.success) {
      console.error("Age signals failed:", response.errorCode, response.error);
      return;
    }

    // iOS
    if (typeof response.isEligibleForAgeFeatures !== "undefined") {
      if (response.declined) {
        console.log("User declined to share their age range");
      } else {
        console.log("Age range:", response.lowerBound, "-", response.upperBound);
        console.log("Supervised:", response.isSupervised);
      }
    }

    // Android
    if (response.userStatus) {
      console.log("User status:", response.userStatus);
      console.log("Age range:", response.ageLower, "-", response.ageUpper);
    }
  },
});
```

## notifySignificantChange

Notifies the system that the app has undergone a significant change to its content or experience (for example, a major content update relevant to age assurance). On iOS this presents a PermissionKit prompt via `AskCenter` so the user / guardian can be re-asked.

{% hint style="warning" %}
**Platform support:** iOS only, requires iOS 26.2+. On other platforms the call does nothing.
{% endhint %}

{% tabs %}
{% tab title="Plain Javascript" %}

```javascript
window.WTN.AgeSafety.notifySignificantChange({
  topicString: "Major content update for the 2026 season",
  callback: function (response) {
    console.log(response.success);
  },
});
```

{% endtab %}

{% tab title="ES5+" %}

```javascript
import { notifySignificantChange } from "webtonative/AgeSafety";

notifySignificantChange({
  topicString: "Major content update for the 2026 season",
  callback: (response) => {
    console.log(response.success);
  },
});
```

{% endtab %}
{% endtabs %}

**Parameters:**

| Key           | Type       | Required | Description                                                 |
| ------------- | ---------- | -------- | ----------------------------------------------------------- |
| `topicString` | `String`   | Yes      | A description of the significant change. Must be non-empty. |
| `callback`    | `Function` | No       | Callback function invoked with the response.                |

**Callback Response:**

| Key                  | Type      | Description                                                                                                                                                                                                                     |
| -------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`               | `String`  | Always `"notifySignificantChange"`.                                                                                                                                                                                             |
| `success`            | `Boolean` | `true` if the notification was submitted successfully, `false` otherwise.                                                                                                                                                       |
| `error`              | `String`  | Present when `success` is `false`. A human-readable message describing the failure.                                                                                                                                             |
| `regionNotSupported` | `Boolean` | Present and `true` when the failure is because PermissionKit / `AskCenter` is not available in the user's region (currently limited to EU/EEA). Use this to show a tailored message rather than treating it as a generic error. |
| `_simulator`         | `Boolean` | Present and `true` only on the iOS Simulator, where the PermissionKit UI cannot be presented (stubbed response).                                                                                                                |
| `_note`              | `String`  | Present only on the iOS Simulator. Explains that the response is a simulator stub.                                                                                                                                              |

**Example:**

```javascript
window.WTN.AgeSafety.notifySignificantChange({
  topicString: "Major content update for the 2026 season",
  callback: function (response) {
    if (response.success) {
      console.log("Significant change submitted");
    } else if (response.regionNotSupported) {
      console.log("This feature isn't available in your region yet");
    } else {
      console.error("Failed to notify:", response.error);
    }
  },
});
```

## Notes

* Both functions require **store services** to be enabled on the build; otherwise the call is silently ignored.
* `getAgeSignals` returns different fields on Android vs iOS. Always branch on the field you need (`userStatus` for Android, `isEligibleForAgeFeatures` / `declined` for iOS) rather than assuming a single shape.
* On iOS, `lowerBound`/`upperBound` being absent is meaningful: a missing `lowerBound` means the user is **below** the lowest age gate, and a missing `upperBound` means they are **at or above** the highest age gate.
* The iOS age-range and significant-change APIs require **iOS 26.2 or later**. On older iOS versions the callback fires with `success: false` and an explanatory `error`.
* On the **iOS Simulator**, `notifySignificantChange` cannot present the PermissionKit UI and returns a stub response with `_simulator: true`. Test the full flow on a real device.
* `notifySignificantChange` (and the underlying PermissionKit `AskCenter`) is currently restricted to certain regions (EU/EEA). Outside those regions it fails with `regionNotSupported: true`.
* **Debug only (Android):** in debug builds, `getAgeSignals` honors an optional `testScenario` value (e.g. `"SUPERVISED"`, `"VERIFIED"`) that drives a fake signals manager for testing. This is ignored in release builds, which always use the real Play Age Signals API.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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.webtonative.com/javascript-apis/age-safety.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.
