Skip to main content
The Privy API supports two authentication methods — both use bearer tokens in the Authorization header:
  • API tokens — Generate a long-lived token from the dashboard and use it directly. Best for scripts and quick integrations.
  • OAuth applications — Exchange client credentials for a short-lived access token. Best for third-party integrations with automated rotation.

OAuth: How it works

  1. Create an OAuth application in your Privy dashboard to get a client ID and client secret.
  2. Exchange those credentials for an access token using the OAuth 2.0 client credentials flow.
  3. Include the access token in the Authorization header of every request.
curl -X GET "https://api.privy.com/v1/contacts" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Creating an OAuth application

Navigate to Settings > Apps in your Privy dashboard and create a new application. You’ll choose a name and select which scopes the application should have access to. All applications are granted contacts_read by default — you can optionally enable contacts_write during creation or later from the application’s settings. When the application is created, the dashboard displays the client secret once. Copy it immediately — you won’t be able to view it again. If you lose it, you can regenerate a new secret from the application’s settings.

Scopes

Scopes control what your token can access. Your OAuth application must have a scope enabled before you can request it — configure scopes in Settings > Apps in your dashboard.
ScopeDescriptionDefault
contacts_readList and filter contactsYes
contacts_writeCreate, update, unsubscribe, and delete contactsNo
  • contacts_read is the default scope. If you don’t specify a scope parameter in your token request, your token is granted contacts_read only.
  • contacts_write must be explicitly requested by including scope in your token request.

Getting an access token

Exchange your client ID and client secret for an access token by making a POST request to the token endpoint.

Read-only access (default)

If you only need to read contacts, no scope parameter is required:
curl -X POST "https://api.privy.com/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"
{
  "access_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 7200,
  "scope": "contacts_read",
  "created_at": 1712150400
}

Read and write access

To create, update, or delete contacts, request contacts_write explicitly:
curl -X POST "https://api.privy.com/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "scope=contacts_read contacts_write"
{
  "access_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 7200,
  "scope": "contacts_read contacts_write",
  "created_at": 1712150400
}
The scope response field confirms which scopes were actually granted. Always check this to verify your token has the access you need.
FieldDescription
access_tokenThe bearer token to include in API requests.
token_typeAlways Bearer.
expires_inToken lifetime in seconds. Access tokens expire after 2 hours (7200 seconds).
scopeThe scopes granted to this token.
If your client ID or secret is wrong, the API returns a 401 error with "error": "invalid_client". If you request a scope that isn’t enabled on your application, the API returns a 401 error with "error": "invalid_scope".

Refreshing tokens

When your access token expires, request a new one by repeating the client credentials exchange above. There is no refresh token in the client credentials flow — simply request a new access token.

Security tips

  • Keep credentials secret. Never share your client secret or access tokens in client-side code, public repositories, or URLs.
  • Rotate secrets regularly. Regenerate your client secret periodically from the dashboard, especially if a team member leaves.
  • Use one application per integration. This makes it easy to revoke access for a single integration without affecting others.

Invalid tokens

If your token is missing, expired, or malformed, the API returns a 401 unauthorized error:
{
  "error": {
    "code": "unauthorized",
    "message": "Bearer token is missing or invalid"
  }
}
See the Errors page for all error codes.