RevenueCat

Build With RevenueCat

Build a customized mobile subscription business with RevenueCat. We do the heavy lifting of normalizing subscribers from any source and maintain a single source of truth for subscription status, so you can get back to building your app.

RevenueCat is a powerful, secure, reliable, and free to use in-app purchase server with global support. All you need to get started is an API key.

Suggest Edits

RevenueCat REST API

 

Authentication

Authentication for the RevenueCat REST API is achieved by setting the Authorization header with a valid API key. You'll find two types of API keys in your RevenueCat dashboard: public and secret.

Certain endpoints require secret keys, which should be kept out of any publicly accessible areas such as GitHub, client-side code, and so forth. See our Authentication guide for more information.

Authorization: Bearer YOUR_REVENUECAT_API_KEY

Payload

The body of the POST requests should be encoded in JSON and have the 'Content-Type' header set to 'application/json'.

Content-Type: application/json
{
  "app_user_id": "user-1456",
  "fetch_token": "MQABC...EFH1234="
}
Suggest Edits

Get or Create Subscriber

Gets the latest subscriber info or creates one if it doesn't exist.

 

Header Auth

 Authentication is required for this endpoint.
gethttps://api.revenuecat.com/v1/subscribers/app_user_id
curl --request GET \
  --url https://api.revenuecat.com/v1/subscribers/app_user_id
var request = require("request");

var options = { method: 'GET',
  url:
   'https://api.revenuecat.com/v1/subscribers/app_user_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.revenuecat.com/v1/subscribers/app_user_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://api.revenuecat.com/v1/subscribers/app_user_id");

xhr.send(data);
import requests

url = "https://api.revenuecat.com/v1/subscribers/app_user_id"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{
    "request_date": "2019-07-26T17:40:10Z",
    "request_date_ms": 1564162810884,
    "subscriber": {
        "entitlements": {
            "pro_cat": {
                "expires_date": null,
                "product_identifier": "onetime",
                "purchase_date": "2019-04-05T21:52:45Z"
            }
        },
        "first_seen": "2019-02-21T00:08:41Z",
        "non_subscriptions": {
            "onetime": [
                {
                    "id": "cadba0c81b",
                    "is_sandbox": true,
                    "purchase_date": "2019-04-05T21:52:45Z",
                    "store": "app_store"
                }
            ]
        },
        "original_app_user_id": "XXX-XXXXX-XXXXX-XX",
        "original_application_version": "1.0",
        "other_purchases": {
            "onetime": {
                "purchase_date": "2019-04-05T21:52:45Z"
            }
        },
        "subscriptions": {
            "annual": {
                "billing_issues_detected_at": null,
                "expires_date": "2019-06-14T21:07:40Z",
                "is_sandbox": true,
                "original_purchase_date": "2019-02-21T00:42:05Z",
                "period_type": "normal",
                "purchase_date": "2019-06-14T20:07:40Z",
                "store": "app_store",
                "unsubscribe_detected_at": "2019-06-17T22:48:38Z"
            },
            "onemonth": {
                "billing_issues_detected_at": null,
                "expires_date": "2019-06-17T22:47:55Z",
                "is_sandbox": true,
                "original_purchase_date": "2019-02-21T00:42:05Z",
                "period_type": "normal",
                "purchase_date": "2019-06-17T22:42:55Z",
                "store": "app_store",
                "unsubscribe_detected_at": "2019-06-17T22:48:38Z"
            },
            "rc_promo_pro_cat_monthly": {
                "billing_issues_detected_at": null,
                "expires_date": "2019-08-26T01:02:16Z",
                "is_sandbox": false,
                "original_purchase_date": "2019-07-26T01:02:16Z",
                "period_type": "normal",
                "purchase_date": "2019-07-26T01:02:16Z",
                "store": "promotional",
                "unsubscribe_detected_at": null
            }
        }
    }
}
{'message': "Bad parameters"}
{'message': "Invalid API key"}

Path Params

app_user_id
string
required

The app user id used with the mobile SDK.

Headers

X-Platform
string

Optionally set the X-Platform header to update the subscriber record's last_seen field. Set to either ios, android, macos or uikitformac. Don't set this if you are calling the getter for informational purposes.

 

Get OR create a subscriber

If the provided app_user_id doesn't exists, a new subscriber will be created with the App User Id.

Response

If the provided app_user_id exists, the response will contain the latest purchase information for that user.

Attribute
Description

request_date

The ISO 8601 datetime of the request.

request_date_ms

The Unix timestamp of the request.

subscriber

The Subscriber object:

Attribute
Description

original_app_user_id

The first App User Id that was registered for this user.

original_application_version

Only available on iOS. This will be null until an iOS receipt is sent for the user. After a receipt has been sent, it will indicate the first App Store version of your app that user installed.

first_seen

The ISO 8601 datetime string corresponding to when this user was first seen in RevenueCat .

last_seen

The ISO 8601 datetime string corresponding to when this user was last seen in RevenueCat.

entitlements

A mapping of Entitlement objects keyed by entitlement ID.

subscriptions

A mapping of Subscription objects keyed by product ID.

non_subscriptions

A mapping of Non-Subscription object arrays keyed by product ID.

other_purchases

Deprecated. See non_subscriptions

subscriber_attributes

A dictionary of subscriber attribute keys to Subscriber Attribute objects. Only included in requests made with secret keys.

For more details on subscriber attributes, see our subscriber attributes guide.

The Entitlement object:

Attribute
Description

expires_date

The ISO 8601 datetime this entitlement is set to expire (may be in the past).

purchase_date

The ISO 8601 datetime of the latest purchase or renewal.

product_identifier

The product identifier that unlocked this entitlement.

The Subscription object:

Attribute
Description

expires_date

The ISO 8601 datetime of the latest known expiration date.

purchase_date

The ISO 8601 datetime of the latest purchase or renewal.

original_purchase_date

The ISO 8601 datetime of the first recorded purchase of this product.

period_type

Possible values for period_type:

  • normal: The product is in it's normal period (default)
  • trial: The product is in a free trial period
  • intro: The product is in an introductory pricing period

store

Possible values for store:

  • app_store: The product was purchased through Apple App Store.
  • mac_app_store: The product was purchased through the Mac App Store.
  • play_store: The product was purchased through the Google Play Store.
  • stripe: The product was purchased through Stripe.
  • promotional: The product was granted via RevenueCat.

is_sandbox

Boolean indicating whether the subscription was purchased in sandbox or production environment.

unsubscribe_detected_at

The ISO 8601 datetime that an unsubscribe was detected. Will be null if previously unsubscribed user has resubscribed. Note the subscription may still be active, check the expires_date attribute.

billing_issues_detected_at

The ISO 8601 datetime that billing issues were detected. Will be null if previous billing issues were resolved. Note the subscription may still be active, check the expires_date attribute.

The Non-Subscription object:

Attribute
Description

id

A unique identifier for the transaction. You can use this to ensure you track consumption of all consumable products.

purchase_date

The ISO 8601 datetime that the purchase happened.

store

Possible values for store:

  • app_store: The product was purchased through Apple App Store.
  • mac_app_store: The product was purchased through the Mac App Store.
  • play_store: The product was purchased through the Google Play Store.
  • stripe: The product was purchased through Stripe.

is_sandbox

Boolean indicating whether the subscription was purchased in sandbox or production environment.

The Subscriber Attribute object:

Attribute
Description

value

The string value of the attribute.

updated_at_ms

The Unix timestamp of when the attribute was last updated.

Secret API Key Required For Subscriber Attributes

The Subscriber Attribute object will only be included in requests made with a secret API key.

Suggest Edits

Update Subscriber Attributes

Updates subscriber attributes for a user.

 

Header Auth

 Authentication is required for this endpoint.
posthttps://api.revenuecat.com/subscribers/app_user_id/attributes
curl --request POST \
  --url https://api.revenuecat.com/subscribers/app_user_id/attributes \
  --header 'Content-Type: application/json' \
  --data \ 
  '{ 
	"attributes" :  {
		"key_name_1": {
			"value": "custom_value_1"
		},
		"key_name_2": {
			"value": "custom_value_2"
		}
	}
}'
A binary file was returned

You couldn't be authenticated

// See the Subscriber object for response fields
{
  "code": 7263,
  "message": "Some subscriber attributes keys were unable to saved.",
  "attribute_erors": [
    {
      "key_name": "$email",
      "message": "Value is not a valid email address."
    },
    {
      "key_name": "invalid key name with spaces",
      "message": "Key name format is not valid."
    },
    {
      "key_name": "too_much_data",
      "message": "Value is too long."
    }
  ]
}

Path Params

app_user_id
string
required

The app user id used with the mobile SDK.

Body Params

attributes
object
 
attributes.key_name
object
required

Mapping of key names to subscriber attribute objects.

 
attributes.key_name.value
string
required

The value of the attribute. If the value is null or an empty string, the attribute will be deleted.

attributes.key_name.updated_at_ms
timestamp

UNIX epoch in milliseconds of when the attribute was updated. This value is used to resolve conflicts, an attribute will only be updated if the new updated_at_ms value is newer than the value for the stored attribute.

Headers

Content-Type
string

Required.

 

Response

If the request is successful, it will contain an empty response.

If the request is not successful because of invalid attributes, an attributes_error dictionary will be included in the response with additional details as to which attributes could not be saved and why (see the example 400 response for an example error body).

Attribute Key Restrictions

For a full list of reserved attribute keys and restrictions refer to the Subscriber Attributes guide here.

Suggest Edits

Delete Subscriber

Permanently deletes a subscriber.

 

Header Auth

 Authentication is required for this endpoint.
deletehttps://api.revenuecat.com/v1/subscribers/app_user_id
curl --request DELETE \
  --url https://api.revenuecat.com/v1/subscribers/app_user_id
var request = require("request");

var options = { method: 'DELETE',
  url:
   'https://api.revenuecat.com/v1/subscribers/app_user_id' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.revenuecat.com/v1/subscribers/app_user_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Delete.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("DELETE", "https://api.revenuecat.com/v1/subscribers/app_user_id");

xhr.send(data);
import requests

url = "https://api.revenuecat.com/v1/subscribers/app_user_id"

response = requests.request("DELETE", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

{"app_user_id": "XXX-XXXXX-XXXXX-XX", deleted: True}

Path Params

app_user_id
string
required

The app user id, or alias, of the subscriber.

 

Secret API Key Required

This endpoint requires a secret API key to be used.

Deleted Subscribers Cannot Be Recovered

Be careful when using this endpoint, when a subscriber is deleted, it cannot be brought back.

Response

If successful, the response will contain the deleted app_user_id.

Attribute
Description

app_user_id

The app user ID, or alias of the deleted subscriber.

Suggest Edits

Create a Purchase

Records a purchase for a user from iOS, Android, or Stripe.

 

Header Auth

 Authentication is required for this endpoint.
posthttps://api.revenuecat.com/v1/receipts
curl --request POST \
  --url https://api.revenuecat.com/v1/receipts \
  --header 'content-type: application/json' \
  --header 'x-platform: ios'
var request = require("request");

var options = { method: 'POST',
  url: 'https://api.revenuecat.com/v1/receipts',
  headers:
   { 'x-platform': 'ios',
     'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.revenuecat.com/v1/receipts")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["x-platform"] = 'ios'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.revenuecat.com/v1/receipts");
xhr.setRequestHeader("content-type", "application/json");
xhr.setRequestHeader("x-platform", "ios");

xhr.send(data);
import requests

url = "https://api.revenuecat.com/v1/receipts"

headers = {
    'content-type': "application/json",
    'x-platform': "ios"
    }

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

// See the Subscriber object for response fields

Body Params

app_user_id
string
required

User id of the user the receipt is associated with.

fetch_token
string
required

For iOS, the base64 encoded receipt file, for Android the receipt token.

price
float

Price paid, only if associated with a purchase. Not required for Android.

currency
string

Currency code paid

payment_mode
string

Optionally used by the iOS SDK to communicate intro pricing periods. Either pay_as_you_go = 0, pay_up_front = 1, or free_trial = 2.

introductory_price
float

Introductory price paid

product_id
string

The Apple product identifier or SKU

is_restore
string

If true, the purchase will create an alias between any other users sharing the same fetch_token

Headers

Content-Type
string
required

Required.

X-Platform
string
required

The platform this purchase is for. Either ios, android, macos or uikitformac

 

Response

If the response is successful, it will contain the updated Subscriber object.

Suggest Edits

Grant a Promotional Entitlement

Grants a user a promotional entitlement.

 

Header Auth

 Authentication is required for this endpoint.
posthttps://api.revenuecat.com/v1/subscribers/app_user_id/entitlements/entitlement_identifier/promotional
curl --request POST \
  --url https://api.revenuecat.com/v1/subscribers/app_user_id/entitlements/entitlement_identifier/promotional
var request = require("request");

var options = { method: 'POST',
  url:
   'https://api.revenuecat.com/v1/subscribers/app_user_id/entitlements/entitlement_identifier/promotional' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.revenuecat.com/v1/subscribers/app_user_id/entitlements/entitlement_identifier/promotional")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.revenuecat.com/v1/subscribers/app_user_id/entitlements/entitlement_identifier/promotional");

xhr.send(data);
import requests

url = "https://api.revenuecat.com/v1/subscribers/app_user_id/entitlements/entitlement_identifier/promotional"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

// See the Subscriber object for response fields

Path Params

app_user_id
string
required

The app user id, or alias, of the subscriber.

entitlement_identifier
string
required

The identifier for the entitlement you want to grant to the user.

Body Params

duration
string
required

How long of a duration to grant the promotional entitlement for. See below for possible values.

start_time_ms
date-time

A Unix epoch in milliseconds for when the promotional entitlement should start - can be in the past or future. If not provided, the entitlement will be granted immediately.

Headers

Content-Type
string

Required.

 

Secret API Key Required

This endpoint requires a secret API key to be used.

Duration Values

The duration parameter must be one of the following supported durations:

Value
Description

daily

24 hour access

weekly

7 day access

monthly

1 month access

two_month

2 month access

three_month

3 month access

six_month

6 month access

yearly

1 year access

lifetime

200 year access

Response

If the response is successful, it will contain the updated Subscriber object.

Suggest Edits

Revoke Promotional Entitlements

Revokes all promotional entitlements for a given entitlement identifier and app user ID.

 

Header Auth

 Authentication is required for this endpoint.
posthttps://api.revenuecat.com/v1/subscribers/app_user_id/entitlements/entitlement_identifier/revoke_promotionals
curl --request POST \
  --url https://api.revenuecat.com/v1/subscribers/app_user_id/entitlements/entitlement_identifier/revoke_promotionals
var request = require("request");

var options = { method: 'POST',
  url:
   'https://api.revenuecat.com/v1/subscribers/app_user_id/entitlements/entitlement_identifier/revoke_promotionals' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.revenuecat.com/v1/subscribers/app_user_id/entitlements/entitlement_identifier/revoke_promotionals")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.revenuecat.com/v1/subscribers/app_user_id/entitlements/entitlement_identifier/revoke_promotionals");

xhr.send(data);
import requests

url = "https://api.revenuecat.com/v1/subscribers/app_user_id/entitlements/entitlement_identifier/revoke_promotionals"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

// See the Subscriber object for response fields

Path Params

app_user_id
string
required

The app user id, or alias, of the subscriber.

entitlement_identifier
string
required

The identifier for the entitlement you want to grant to the user.

 

Secret API Key Required

This endpoint requires a secret API key to be used.

Response

If the response is successful, it will contain the updated Subscriber object.

Suggest Edits

Refund a Google Subscription

Immediately revokes access to a Google Subscription and issues a refund for the last purchase.

 

Header Auth

 Authentication is required for this endpoint.
posthttps://api.revenuecat.com/v1/subscribers/app_user_id/subscriptions/product_identifier/revoke
curl --request POST \
  --url https://api.revenuecat.com/v1/subscribers/app_user_id/subscriptions/product_identifier/revoke
var request = require("request");

var options = { method: 'POST',
  url:
   'https://api.revenuecat.com/v1/subscribers/app_user_id/subscriptions/product_identifier/revoke' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.revenuecat.com/v1/subscribers/app_user_id/subscriptions/product_identifier/revoke")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.revenuecat.com/v1/subscribers/app_user_id/subscriptions/product_identifier/revoke");

xhr.send(data);
import requests

url = "https://api.revenuecat.com/v1/subscribers/app_user_id/subscriptions/product_identifier/revoke"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

// See the Subscriber object for response fields

Path Params

app_user_id
string
required

The app user id, or alias, of the subscriber.

product_identifier
string
required

The identifier of the product belonging to the subscription that is being revoked.

 

Secret API Key Required

This endpoint requires a secret API key to be used.

Response

If the response is successful, it will contain the updated Subscriber object.

Suggest Edits

Add User Attribution

Attaches attribution data to a subscriber from specific supported networks.

 

Header Auth

 Authentication is required for this endpoint.
posthttps://api.revenuecat.com/v1/subscribers/app_user_id/attribution
curl --request POST \
  --url https://api.revenuecat.com/v1/subscribers/your%20user%20id/attribution \
  --header 'content-type: application/json'
var request = require("request");

var options = { method: 'POST',
  url:
   'https://api.revenuecat.com/v1/subscribers/your%20user%20id/attribution',
  headers:
   { 'content-type': 'application/json' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://api.revenuecat.com/v1/subscribers/your%20user%20id/attribution")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://api.revenuecat.com/v1/subscribers/your%20user%20id/attribution");
xhr.setRequestHeader("content-type", "application/json");

xhr.send(data);
import requests

url = "https://api.revenuecat.com/v1/subscribers/your%20user%20id/attribution"

headers = {'content-type': 'application/json'}

response = requests.request("POST", url, headers=headers)

print(response.text)
A binary file was returned

You couldn't be authenticated

Try the API to see results

Path Params

app_user_id
string
required

The app user id, or alias, of the subscriber.

Body Params

data
object
required

The data returned by the attribution network callbacks.

 
data.rc_idfa
string

The idfa from AdSupport on iOS. (iOS Only)

data.rc_gps_adid
string

The Google Play Services Advertising identifier. (Android Only)

network
int32
required

The attribution network the data is coming from. See below for possible values.

Headers

Content-Type
string
required

Required.

 

Attribution Source Network Codes

Attribution Source
Code

Apple Search Ads

0

Adjust

1

AppsFlyer

2

Branch

3

Tenjin

4

Facebook

5

Response

If the response is successful, it will contain an empty object { }.