Server APIs for Subscriptions

Purchasing Subscriptions

Subscriptions can only be purchased as in-app purchases. To sell subscriptions in-app, reference the SKU of the subscription offer using the same methods for offering in-app purchases. For more information about defining subscription offers in Developer Center, see Subscriptions.

For information on how to implement in-app purchases in your app, see In-App Purchase Integration.

Verifying Subscriptions

This topic describes how to use the server-to-server (S2S) REST APIs available on the Oculus Platform to verify the status of any subscriptions a user might have to your content.

This feature accesses user data and you must complete the Data Use Checkup form prior to submitting your app to the Quest Store for review. For more information, see Complete a Data Use Checkup.

Server-to-Server Endpoint

All server-to-server requests are made to the following endpoint:

https://graph.oculus.com

Access Token

An access token is sent with every message and either authenticates the request as a valid server request or as a request on behalf a particular user. The access token can contain one of the following:

App Credentials

App credentials verify your server back-end as a trusted resource. These credentials should never be shared with a client-side app.

An access token with app credentials contains the App ID and App Secret from the API page in the Developer Dashboard in the following format: OC|$APPID|$APPSECRET.

You can generate a new app secret if your credentials are compromised or you need a fresh set of API credentials. If you change the app secret, the permissions of the previous app secret are revoked. Note that you must use an admin account to access the app secret from the API page.

Note: Older versions of Unity use .NET 3.5 or earlier, which does not support SSL certificates that use SHA2 and cannot be used for server-to-server requests.

User Access Token

A user access token verifies a request on behalf of a user is valid. Use a user access token when interacting on behalf of a user, or in reference to a specific user. For example, after a server-hosted multiplayer match may want to update a client-authoritative leaderboard with the results of the match. In this scenario, your server would make a call to update the leaderboard entry for each user with the results of the match using the user access token to identify the user.

Retrieve the user token with the ovr_User_GetAccessToken() method.

The token will be returned as a response and can be passed from the client to your server. An access token with a user credentials contains OC and a long alpha numeric string similar to the following: OC12342GhFccWvUBxPMR4KXzM5s2ZCMp0mlWGq0ZBrOMXyjh4EmuAPvaXiMCAMV9okNm9DXdUA2EWNplrQ.

Additionally, you can retrieve your user token for testing purposes at the bottom of the API page in the Developer Dashboard.

App ID

Some server calls require an app ID, which you can find on the API page in the Developer Dashboard.

Query Subscription Status (GET)

Retrieves subscription status. Detailed subscription status is contained in several response fields. If specific response fields aren’t specified, the query returns only sku, owner{id}, and is_active.

Request method/URI:

GET https://graph.oculus.com/application/subscriptions

Parameters

Using the app-secret access token returns subscription data for all users, which can be a substantial amount of data. Using the user access token returns subscription data for only that user.

If using the app-secret access token, expect a large, paginated data set that includes a paging.next field that contains the URL to the next page of data for you to request. Stop paging when the paging.next link no longer appears. For more information on how to handle paginated results, see Using the Graph API.

ParameterRequired or OptionalDescriptionTypeExample
access_tokenRequiredBearer token that contains OC|$APP_ID |$APP_SECRET or the User Access Tokenstring“Bearer OC|1234|456789”
fieldsOptionalA comma-separated list of field names. Can contain: owner, sku, period_start_time, period_end_time, cancellation_time, is_trial, is_active. For more information, see Response Fields.comma-separated string“sku, is_trial, is_active, period_end_time”
owner_idOptionalRestricts the result to a single owner ID. Can only be used with an app-secret access token. Use with a user access token will result in an error.string 
is_activeOptionalSet to true when a subscription is active.booltrue
is_trialOptionalSet to true when the most recent subscription period is a free trial (7d, 14d, 30d). Does not indicate that the subscription itself is active.booltrue
skusOptionalSKUs of subscriptionscomma-separated string“SKU1,SKU2”


Response Fields

The response fields contain additional subscription data that you can request by way of the fields parameter. If specific response fields aren’t specified, the query returns only sku, owner{id}, and is_active.

FieldDefinitionType
owner{id}Unique user identifierstring
skuSKU of subscriptionstring
period_start_timeThe date when the most recent subscription period startedtimestamp
period_end_timeThe date when the most recent subscription will endtimestamp
cancellation_timeThe date when the user last canceled the subscription. Does not affect period_end_time.timestamp
is_trialSet to true when the most recent subscription period is a free trial (7d, 14d, 30d). Does not indicate that the subscription itself is active.bool
is_activeSet to true when a subscription is active.bool

Example Request

$ curl -G -d "access_token=<ACCESS_TOKEN>" -d "fields=sku,owner{id},is_active,is_trial,cancellation_time,period_start_time,period_end_time" https://graph.oculus.com/application/subscriptions

Example Result

{
  "data": [
    {
      "sku": "OPTIONAL_SUBSCRIPTION",
      "owner": {
        "id": "3559884437424131"
      },
      "is_active": false,
      "is_trial": false,
      "period_start_time": "2021-03-09T13:04:20+0000",
      "period_end_time": "2021-03-09T13:04:20+0000"
    },
  ],
  "paging": {
    "cursors": {
      "before": "QVFIUlliZAnlkTEVnUkFkVTBJZAW9lMWprR0dkaGtuQjhTT0lTdzRiTEo1dkstSXoybDVRWEFFUzA0RURfQjVMMUxXZAzJ4VENTV1RadU9uejFaUmlIUlo4cUlR",
      "after": "QVFIUlZAGTmllREUwcWdJRkhGcUtBWXZA2WWFvSkJHMlJ1dnpfVVRLU2ZAPNHc1MjVCbXc0d3YyWi1meU1DNjhQWTBJaldrcDIxVkpxNWZAMSmNfa2lOcldVTUhB"
    }
  }
}