Skip to main content

Create an OAuth client

Register an OAuth client and implement RevenueCat's authorization flow

AIAsk AIChatGPTClaude

This article shows you how to register an OAuth client and implement RevenueCat's authorization flow. You'll register the client, send developers through authorization, and call the REST API with the tokens you receive. By the end, your client can access RevenueCat on behalf of developers who approve it.

📘Who this page is for

This page is for teams building an OAuth client that other RevenueCat developers will connect to. If you want to connect to an existing client, or revoke one you already authorized, see OAuth. If you're calling the REST API for your own project, create a secret API key instead.

How client authorization works

RevenueCat supports the OAuth 2.0 Authorization Code flow. Public clients must use Proof Key for Code Exchange (PKCE) (S256). Confidential clients can omit it. If a client sends a code_challenge, RevenueCat validates it. A RevenueCat developer approves your client on a consent screen, then your client receives an authorization code and exchanges it for an access token (atk_) and refresh token (rtk_).

OAuth tokens are developer-level: they can access the projects that developer owns or collaborates on, limited by the scopes they granted. Access tokens expire after 1 hour. Refresh tokens expire after 30 days. Refreshing rotates both tokens.

Client creation steps

  1. Register your client with RevenueCat Support. You'll get a client ID, and a client secret if the client is confidential.
  2. Send the developer through authorization. Direct them to the authorize endpoint, handle the redirect, and exchange the code for tokens.
  3. Call the REST API with the access token, and refresh when it expires.

Public clients must implement PKCE. Confidential clients can send it too. The rest of this page covers each of those in detail.

Client Registration

To integrate with RevenueCat's OAuth server, you'll need to register your application as an OAuth client. Contact our support team to register your client with the following information:

  • Client Name: Display name for your application
  • Client URI: Your application's homepage URL
  • Redirect URIs: Valid callback URLs for your application
  • Client Type: Public (for native/desktop apps) or Confidential (for server-side apps)
  • Token auth method: Confidential clients use HTTP Basic authentication by default. Public clients use none. If your integration requires sending credentials in the token request body, request client_secret_post when you register your client.
  • Scopes: Available scopes your application would like to request

Authorization Flow

Step 1: Initiate Authorization

Direct users to the authorization endpoint:

GET https://api.revenuecat.com/oauth2/authorize

Required Parameters:

  • client_id: Your client identifier
  • response_type: Must be code
  • redirect_uri: Must match a registered redirect URI
  • scope: Space-separated list of requested permissions
  • state: Opaque value you generate and later compare to the redirect (required; omitting it returns invalid_request)
  • code_challenge: PKCE code challenge (required for public clients, optional for confidential clients)
  • code_challenge_method: Must be S256 (required when code_challenge is present)

Example Authorization URL:

https://api.revenuecat.com/oauth2/authorize?
client_id=your_client_id&
response_type=code&
redirect_uri=https://yourapp.com/callback&
scope=project_configuration:apps:read&
state=random_state_string&
code_challenge=your_code_challenge&
code_challenge_method=S256

Step 2: Handle Authorization Response

After the user grants permission, they'll be redirected to your redirect_uri. Confirm that state matches the value you sent in Step 1.

Success Response:

https://yourapp.com/callback?code=authorization_code&state=random_state_string

Error Response:

https://yourapp.com/callback?error=access_denied&error_description=description&state=random_state_string

Step 3: Exchange Code for Tokens

Exchange the authorization code for access and refresh tokens:

curl -X POST https://api.revenuecat.com/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "your_client_id:your_client_secret" \
-d "grant_type=authorization_code&code=your_auth_code&redirect_uri=https://yourapp.com/callback"

Parameters:

  • grant_type: Must be authorization_code
  • code: The authorization code from Step 2
  • redirect_uri: Must match the redirect URI from Step 1
  • code_verifier: PKCE code verifier (required when a code_challenge was sent)

Confidential clients authenticate with the client ID and client secret using HTTP Basic authentication by default. If your client is registered with client_secret_post, send client_id and client_secret in the form body instead of using the Authorization header.

Success Response:

{
"access_token": "atk_...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "rtk_...",
"scope": "project_configuration:apps:read"
}

Token Management

Access Tokens

  • Lifetime: 1 hour
  • Usage: Include in API requests via Authorization: Bearer {access_token} header
  • Prefix: atk_

Refresh Tokens

  • Lifetime: 30 days
  • Usage: Exchange for new access tokens when they expire
  • Prefix: rtk_

Refreshing Tokens

When your access token expires, use the refresh token to get a new pair:

curl -X POST https://api.revenuecat.com/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "your_client_id:your_client_secret" \
-d "grant_type=refresh_token&refresh_token=your_refresh_token"

Parameters:

  • grant_type: Must be refresh_token
  • refresh_token: Your current refresh token
⚠️Token Rotation

When tokens are refreshed, both the old access and refresh tokens are revoked, and new ones are issued. Make sure to update your stored tokens.

Available Scopes

Request only the scopes your application needs:

Project Configuration

  • project_configuration:projects:read - List projects
  • project_configuration:projects:read_write - Create projects
  • project_configuration:apps:read - Read apps and app config
  • project_configuration:apps:read_write - Create, update, and delete apps
  • project_configuration:entitlements:read - Read entitlements and attached products
  • project_configuration:entitlements:read_write - Create, update, and delete entitlements
  • project_configuration:offerings:read - Read offerings and paywalls
  • project_configuration:offerings:read_write - Create, update, and delete offerings and paywalls
  • project_configuration:packages:read - Read packages and attached products
  • project_configuration:packages:read_write - Create, update, and delete packages
  • project_configuration:products:read - Read products
  • project_configuration:products:read_write - Create, update, delete, and push products to stores
  • project_configuration:integrations:read - List webhook integrations
  • project_configuration:integrations:read_write - Create, update, and delete webhook integrations
  • project_configuration:virtual_currencies:read - Read virtual currencies
  • project_configuration:virtual_currencies:read_write - Create, update, and delete virtual currencies

Customer Information

  • customer_information:customers:read - Read customers, aliases, attributes, and active entitlements
  • customer_information:customers:read_write - Manage customers and customer-level actions
  • customer_information:subscriptions:read - Read subscriptions and related entitlements or transactions
  • customer_information:subscriptions:read_write - Manage subscriptions, including cancellations and refunds
  • customer_information:purchases:read - Read purchases and purchase entitlements
  • customer_information:purchases:read_write - Manage purchases and virtual currency balance operations
  • customer_information:invoices:read - Read customer invoices

Charts & Metrics

  • charts_metrics:overview:read - Read overview metrics for a project
  • charts_metrics:charts:read - Read chart data and options for a chart

Making API Requests

OAuth access tokens authenticate REST API v2 requests. Don't configure the RevenueCat SDK with an OAuth token. For your own app or backend, use API keys instead.

Include the access token in the Authorization header, using the same Bearer format as a secret API key:

curl -H "Authorization: Bearer atk_your_access_token" \
https://api.revenuecat.com/v2/projects

PKCE Implementation

Proof Key for Code Exchange (PKCE) is required for public clients. Confidential clients can omit it. If a client sends a code_challenge, it must use S256 and send the matching code_verifier when exchanging the code.

1. Generate Code Verifier and Challenge

// Generate a random code verifier (43-128 characters)
function generateCodeVerifier() {
const array = new Uint8Array(32);
crypto.getRandomValues(array);
return base64URLEncode(array);
}

// Create code challenge from verifier
async function generateCodeChallenge(verifier) {
const encoder = new TextEncoder();
const data = encoder.encode(verifier);
const digest = await crypto.subtle.digest("SHA-256", data);
return base64URLEncode(new Uint8Array(digest));
}

// Base64 URL encoding helper
function base64URLEncode(str) {
return btoa(String.fromCharCode.apply(null, str))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=/g, "");
}

2. Use in Authorization Request

Include code_challenge and code_challenge_method=S256 in your authorization URL.

3. Include in Token Exchange

Send the original code_verifier when exchanging the authorization code for tokens.

Error Handling

Authorization Errors

  • invalid_request - Missing or invalid parameters
  • unauthorized_client - Client not authorized for this grant type
  • access_denied - User denied authorization
  • unsupported_response_type - Invalid response type
  • invalid_scope - Requested scope is invalid or unknown
  • server_error - Internal server error

Token Errors

  • invalid_request - Missing or invalid parameters
  • invalid_client - Client authentication failed
  • invalid_grant - Authorization code/refresh token is invalid or expired
  • unauthorized_client - Client not authorized for this grant type
  • unsupported_grant_type - Grant type not supported

Best Practices

  1. Store tokens securely - Never expose tokens in client-side code
  2. Implement proper error handling - Handle token expiration gracefully
  3. Use HTTPS only - All OAuth flows must use secure connections
  4. Validate state parameter - Prevent CSRF attacks
  5. Request minimal scopes - Only request permissions you actually need
  6. Implement token refresh - Handle access token expiration automatically

Rate Limits

OAuth tokens are subject to the same rate limits as API keys. Monitor your usage and implement appropriate backoff strategies.

Next steps

  • OAuth — how RevenueCat developers connect to your client and revoke access
  • REST API v2 — the endpoints your access token can call

To register a client or ask about the integration, contact support@revenuecat.com.

Was this page helpful?