as

Settings
Sign out
Notifications
Alexa
Amazon Appstore
AWS
Documentation
Support
Contact Us
My Cases
Devices
Build
Test
Publish
Connect
Documentation

Integrate and Test the GetUserAgeData API

This page contains example code that shows how to access the GetUserAgeData API from your app and how to consume the responses. The example code provides a test implementation that you can use to simulate the actual API's behavior immediately, ahead of January 1, 2026. For developing and testing your integration of the GetUserAgeData API, use the provided non-production values in the AmazonUserDataClient class in combination with the TestContentProvider class, which serves mock data.

Overview

To integrate the GetUserAgeData API in your app, use the following high-level steps:

  1. If testing with mock data, register the TestContentProvider class in the Android manifest of the app that you're using to test.
  2. Create a simple Java object to hold the user age data.
  3. Create a helper class that models the extracted user age data from the Java object.
  4. Implement the AmazonUserDataClient class to query for user age data.
  5. Call the AmazonUserDataClient class from your app where you'll add logic to handle the response.

For testing

In the version of the AmazonUserDataClient class that you use for testing:

  • Set the AUTHORITY string to amzn_test_appstore
  • Set the PATH string to /getUserAgeData?testOption=k (where k is a number from 1 to 10)

These are non-production values and won't access Amazon systems.

The implementation of the TestContentProvider class provided on this page returns mock response combinations based on the actual response structure of the GetUserAgeData API. To test the functionality, pass a value from 1 to 10 in the testOption query parameter. The TestContentProvider class returns a response that corresponds to the value of the testOption parameter. For a list of the available mock responses provided, see Test data responses.

For production

For production, omit the TestContentProvider class and its manifest registration, and point your app to the production GetUserAgeData API.

To use the production GetUserAgeData API, in the AmazonUserDataClient class:

  • Set the AUTHORITY string to amzn_appstore
  • Set the PATH string to /getUserAgeData

The GetUserAgeData API will only start returning live responses from January 1, 2026. However, if called before January 1, 2026, you will get one of these values: null, Exception, or FEATURE_NOT_SUPPORTED.

AmazonUserDataClient

The following is example code that calls the mocked GetUserAgeData API from your app.

Copied to clipboard.

import android.content.Context;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.CancellationSignal;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.Optional;

public class AmazonUserDataClient {
    
    // This endpoint specified below is purely for testing purposes. 
    // Replace with "amzn_appstore" for production/live API.
    public static final String AUTHORITY = "amzn_test_appstore";

    // This PATH specified below is purely for testing purposes.
    // Modify the query parameter testOption with a value from 1 to 10 (for example, testOption=1 to testOption=10)
    // to get corresponding getResponse1() to getResponse10()'s output of TestContentProvider.
    
    // Replace with "/getUserAgeData" for production/live API.
    private static final String PATH = "/getUserAgeData?testOption=1";

    private static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + PATH);

    private Context context;

    public AmazonUserDataClient(Context context) {
        this.context = context;
    }

    public UserData getMyData(Context context) throws TimeoutException, InterruptedException, ExecutionException {
        CancellationSignal signal = new CancellationSignal();
        CompletableFuture<UserData> future = CompletableFuture.supplyAsync(() ->
            queryUserDataInternal(context, signal)
        );
        try {
            return future.get(5, TimeUnit.SECONDS);
        } catch (TimeoutException e) {
            signal.cancel();
            throw e;
        }
    }
    
    private UserData queryUserDataInternal(Context context, CancellationSignal signal) {
        try (Cursor cursor = context.getContentResolver().query(CONTENT_URI, null, null, null, null, signal)) {
            int ageLowerColumnIndex = cursor.getColumnIndex(UserAgeDataResponse.COLUMN_AGE_LOWER);
            int ageUpperColumnIndex = cursor.getColumnIndex(UserAgeDataResponse.COLUMN_AGE_UPPER);
            return Optional.ofNullable(cursor)
                .filter(Cursor::moveToFirst)
                .map(c -> new UserData(
                    c.getString(c.getColumnIndex(UserAgeDataResponse.COLUMN_RESPONSE_STATUS)),
                    c.getString(c.getColumnIndex(UserAgeDataResponse.COLUMN_USER_STATUS)),
                    !c.isNull(ageLowerColumnIndex) ? c.getInt(ageLowerColumnIndex) : null,
                    !c.isNull(ageUpperColumnIndex) ? c.getInt(ageUpperColumnIndex) : null,
                    c.getString(c.getColumnIndex(UserAgeDataResponse.COLUMN_USER_ID)),
                    c.getString(c.getColumnIndex(UserAgeDataResponse.COLUMN_MOST_RECENT_APPROVAL_DATE))
                ))
                .orElseThrow(() -> new RuntimeException("No user data available"));
        } catch (Exception e) {
            throw new RuntimeException("Query failed", e);
        }
    }
}

To handle the user data response, use the following "plain old Java object" (POJO) model. For more details, see GetUserAgeData API.

Copied to clipboard.

public class UserData {
    private final String responseStatus;
    private final String userStatus;
    private final Integer ageLower;
    private final Integer ageUpper;
    private final String userId;
    private final String mostRecentApprovalDate;

    public UserData(String responseStatus, String userStatus, Integer ageLower, 
                   Integer ageUpper, String userId, String mostRecentApprovalDate) {
        this.responseStatus = responseStatus;
        this.userStatus = userStatus;
        this.ageLower = ageLower;
        this.ageUpper = ageUpper;
        this.userId = userId;
        this.mostRecentApprovalDate = mostRecentApprovalDate;
    }

    public String getResponseStatus() { return responseStatus; }
    public String getUserStatus() { return userStatus; }
    public Integer getAgeLower() { return ageLower; }
    public Integer getAgeUpper() { return ageUpper; }
    public String getUserId() { return userId; }
    public String getMostRecentApprovalDate() { return mostRecentApprovalDate; }
}

UserAgeDataResponse

In the AmazonUserDataClient class, you can use the following helper class that models the user age data that you extract. The example code in the AmazonUserDataClient section uses this helper class.

Copied to clipboard.

public final class UserAgeDataResponse {
    private UserAgeDataResponse() {}
    public static final String COLUMN_RESPONSE_STATUS = "responseStatus";
    public static final String COLUMN_USER_STATUS = "userStatus";
    public static final String COLUMN_USER_ID = "userId";
    public static final String COLUMN_MOST_RECENT_APPROVAL_DATE = "mostRecentApprovalDate";
    public static final String COLUMN_AGE_LOWER = "ageLower";
    public static final String COLUMN_AGE_UPPER = "ageUpper";
}

TestContentProvider

The following implementations are completely standalone and don't interact with Amazon Appstore. Use this class only for early development, unit tests, or testing purposes. It is neither intended for full stack integration tests nor for production usage.

With the implementation of the TestContentProvider class, you can simulate the behavior of the actual GetUserAgeData API. In either a new app, a test app, or as test logic in your actual app, use the TestContentProvider class to get the mocked response.

For details on the GetUserAgeData API response, see GetUserAgeData API.

Copied to clipboard.

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;

/**
 * Content provider to vend the age signals.
 * Returns responseStatus, userStatus, ageLower, ageUpper, userId, mostRecentApprovalDate
 */
public class TestContentProvider extends ContentProvider {


    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        sUriMatcher.addURI(AmazonUserDataClient.AUTHORITY, "getUserAgeData", 1);
    }

    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        throw new UnsupportedOperationException("Insert not supported");
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException("Delete not supported");
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException("Update not supported");
    }

    @Override
    public final Cursor query(Uri uri, String[] projection, Bundle queryArgs, CancellationSignal cancellationSignal) {
        return query(uri, null, null, null, null, cancellationSignal);
    }

    @Override
    public final Cursor query(final Uri uri, final String[] projection, final String selection, final String[] selectionArgs, final String sortOrder) {
        return query(uri, projection, selection, selectionArgs, sortOrder, null);
    }

    @Override
    public final Cursor query(final Uri uri, final String[] projection, final String selection,
                              final String[] selectionArgs, final String sortOrder, CancellationSignal cancellationSignal) {
        int match = sUriMatcher.match(uri);
        if (match != 1) {
            throw new IllegalArgumentException("Unknown URI: " + uri);
        }

        String param1 = uri.getQueryParameter("testOption");
        if (param1 == null) {
            throw new IllegalArgumentException("testOption parameter is required");
        }

        int option;
        try {
            option = Integer.parseInt(param1);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("testOption must be a valid integer");
        }

        if (option < 1 || option > 10) {
            throw new IllegalArgumentException("testOption must be between 1 and 10");
        }
        MatrixCursor cursor = createCursor();
        cursor.addRow(getResponse(option));
        return cursor;
    }

    private Object[] getResponse(int option) {
        switch (option) {
            case 2: return getResponse2();
            case 3: return getResponse3();
            case 4: return getResponse4();
            case 5: return getResponse5();
            case 6: return getResponse6();
            case 7: return getResponse7();
            case 8: return getResponse8();
            case 9: return getResponse9();
            case 10: return getResponse10();
        }
        return getResponse1();
    }

    private MatrixCursor createCursor() {
        return new MatrixCursor(new String[]{
                UserAgeDataResponse.COLUMN_RESPONSE_STATUS,
                UserAgeDataResponse.COLUMN_USER_STATUS,
                UserAgeDataResponse.COLUMN_AGE_LOWER,
                UserAgeDataResponse.COLUMN_AGE_UPPER,
                UserAgeDataResponse.COLUMN_USER_ID,
                UserAgeDataResponse.COLUMN_MOST_RECENT_APPROVAL_DATE
        });
    }

    /***
     * Sample response for 18+ user who is age verified
     * For more details see API documentation.
     */
    private static Object[] getResponse1() {
        return new Object[]{ "SUCCESS", "VERIFIED", 18, null, null, null };
    }


    /***
     * Sample response for any user where age verification/consent is not ascertainable.
     * For more details see API documentation.
     */
    private static Object[] getResponse2() {
        return new Object[]{ "SUCCESS", "UNKNOWN", null, null, null, null };
    }


    /***
     * Response for user with age range between 0 to 12.
     * For more details see API documentation.
     */
    private static Object[] getResponse3() {
        return new Object[]{ "SUCCESS", "SUPERVISED", 0, 12, "randomTestUserId1jC3QQeivdAytchaIVkWOjDiDlvz8xglhUcLwkbUHNQZKKw", "2023-07-01T00:00:00.008+02:00" };
    }


    /***
     * Response for user with age range between 13 to 15.
     * For more details see API documentation.
     */
    private static Object[] getResponse4() {
        return new Object[]{ "SUCCESS", "SUPERVISED", 13, 15, "randomTestUserId1jC3QQeivdAytchaIVkWOjDiDlvz8pUxhUcLwkbUHNQZKKw", "2023-07-01T00:00:00.008Z" };
    }


    /***
     * Response for user with age range between 16 to 17.
     * For more details see API documentation.
     */
    private static Object[] getResponse5() {
        return new Object[]{ "SUCCESS", "SUPERVISED", 16, 17, "randomTestUserId1jC3QQeivdhBcchaIVkWOjDiDlvz8pUxhUcLwkbUHNQZKKw", "2023-07-01T00:00:00.008Z" };
    }


    /***
     * Response for any scenarios in general where age verification law is not applicable.
     * For more details see API documentation.
     */
    private static Object[] getResponse6() {
        return new Object[]{ "SUCCESS", "", null, null, null, null };
    }


    /***
     * Response when API returns APP_NOT_OWNED status
     * For more details see API documentation.
     */
    private static Object[] getResponse7() {
        return new Object[]{ "APP_NOT_OWNED", "", null, null, null, null };
    }


    /***
     * Response when API returns INTERNAL_TRANSIENT_ERROR status
     * For more details see API documentation.
     */
    private static Object[] getResponse8() {
        return new Object[]{ "INTERNAL_TRANSIENT_ERROR", "", null, null, null, null };
    }


    /***
     * Response when API returns INTERNAL_ERROR status
     * For more details see API documentation.
     */
    private static Object[] getResponse9() {
        return new Object[]{ "INTERNAL_ERROR", "", null, null, null, null };
    }


    /***
     * Response when API returns FEATURE_NOT_SUPPORTED status
     * For more details see API documentation.
     */
    private static Object[] getResponse10() {
        return new Object[]{ "FEATURE_NOT_SUPPORTED", "", null, null, null, null };
    }
}

Test data responses

The following table lists the ten mock responses returned from the TestContentProvider API as written in the previous section. testOption is a query parameter used only in the mock user data query to serve the following predefined responses.

testOption value Use case Response data
1 Response for user who is 18+ years old and who's age is verified.
{
  "responseStatus": "SUCCESS",
  "userStatus": "VERIFIED",
  "ageLower": 18,
  "ageUpper": null,
  "userId": null,
  "mostRecentApprovalDate": null
}
2 Response for any user where age verification and consent isn't ascertainable.
{
  "responseStatus": "SUCCESS",
  "userStatus": "UNKNOWN",
  "ageLower": null,
  "ageUpper": null,
  "userId": null,
  "mostRecentApprovalDate": null
}
3 Response for a user between the ages of 0 to 12 (inclusive).
{
  "responseStatus": "SUCCESS",
  "userStatus": "SUPERVISED",
  "ageLower": 0,
  "ageUpper": 12,
  "userId": "randomTestUserId1jC3QQeivdAytchaIVkWOjDiDlvz8xglhUcLwkbUHNQZKKw",
  "mostRecentApprovalDate": "2023-07-01T00:00:00.008+02:00"
}
4 Response for a user between the ages of 13 to 15 (inclusive).
{
  "responseStatus": "SUCCESS",
  "userStatus": "SUPERVISED",
  "ageLower": 13,
  "ageUpper": 15,
  "userId": "randomTestUserId1jC3QQeivdAytchaIVkWOjDiDlvz8pUxhUcLwkbUHNQZKKw",
  "mostRecentApprovalDate": "2023-07-01T00:00:00.008Z"
}
5 Response for a user between the ages of 16 to 17 (inclusive).
{
  "responseStatus": "SUCCESS",
  "userStatus": "SUPERVISED",
  "ageLower": 16,
  "ageUpper": 17,
  "userId": "randomTestUserId1jC3QQeivdhBcchaIVkWOjDiDlvz8pUxhUcLwkbUHNQZKKw",
  "mostRecentApprovalDate": "2023-07-01T00:00:00.008Z"
}
6 Response for any scenario where age verification law isn't applicable.
{
  "responseStatus": "SUCCESS",
  "userStatus": "",
  "ageLower": null,
  "ageUpper": null,
  "userId": null,
  "mostRecentApprovalDate": null
}
7 Response for when the API returns APP_NOT_OWNED status.
{
  "responseStatus": "APP_NOT_OWNED",
  "userStatus": "",
  "ageLower": null,
  "ageUpper": null,
  "userId": null,
  "mostRecentApprovalDate": null
}
8 Response for when the API returns INTERNAL_TRANSIENT_ERROR status.
{
  "responseStatus": "INTERNAL_TRANSIENT_ERROR",
  "userStatus": "",
  "ageLower": null,
  "ageUpper": null,
  "userId": null,
  "mostRecentApprovalDate": null
}
9 Response for when the API returns INTERNAL_ERROR status.
{
  "responseStatus": "INTERNAL_ERROR",
  "userStatus": "",
  "ageLower": null,
  "ageUpper": null,
  "userId": null,
  "mostRecentApprovalDate": null
}
10 Response for when the API returns FEATURE_NOT_SUPPORTED status.
{
  "responseStatus": "FEATURE_NOT_SUPPORTED",
  "userStatus": "",
  "ageLower": null,
  "ageUpper": null,
  "userId": null,
  "mostRecentApprovalDate": null
}

Register the TestContentProvider class in your Android manifest

To use the TestContentProvider class, you must register it in your AndroidManifest.xml file. Only the app that is going to serve you the TestContentProvider API logic, such as a test app, requires this registration step. Change the android:name attribute in the provider element to match the fully qualified class name of your TestContentProvider class.

<application
            android:name="{.MainApplication or your application}"
            android:label="Test App">

        <!-- Test content provider -->
        <provider
                android:name="com.test_app.TestContentProvider"
                android:authorities="amzn_test_appstore"
                android:exported="true" />

</application>

Access the user data provided by Amazon in your app

The following code shows how to get the user data provided through the AmazonUserDataClient class. Use this code in your app where you'll add logic to handle user age verification status and user age ranges.

// //From calling place of your app.
UserData userData = new AmazonUserDataClient().getUserData(context);
// if("SUCCESS".equals(userData.getResponseStatus())) {
//     // Appropriate logic, based on userStatus and age range values.
//     //Refer API documentation for more details.
// }
// //Handle other status appropriately.

Other language representations

This is example code only—refer to the language or framework's official documentation for complete syntax.

React Native

// Works directly with React Native ContentResolver bridge
const userData = await ContentResolver.query('content://amzn_appstore/getUserAgeData');

Flutter

// Works with platform channels
final userData = await platform.invokeMethod('queryContentProvider', {
'uri': 'content://amzn_appstore/getUserAgeData'
});

Last updated: Nov 06, 2025