Authentication
Secure your Phoenix Wallet API requests with OAuth 2.0
Phoenix Wallet uses OAuth 2.0 with the Client Credentials flow for API authentication. This guide explains how to obtain and use access tokens.
Overview
All API requests must include a valid access token in the Authorization header:
Authorization: Bearer <access_token>Obtaining an Access Token
Use your client credentials to request an access token from the token endpoint:
curl -X POST https://auth.phoenixwallet.io/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=wallets:read wallets:write"const response = await fetch('https://auth.phoenixwallet.io/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
scope: 'wallets:read wallets:write',
}),
});
const { access_token, expires_in } = await response.json();
console.log('Token expires in:', expires_in, 'seconds');import os
import requests
response = requests.post(
'https://auth.phoenixwallet.io/oauth/token',
data={
'grant_type': 'client_credentials',
'client_id': os.environ['CLIENT_ID'],
'client_secret': os.environ['CLIENT_SECRET'],
'scope': 'wallets:read wallets:write',
},
)
token_data = response.json()
access_token = token_data['access_token']
expires_in = token_data['expires_in']
print(f'Token expires in: {expires_in} seconds')Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "wallets:read wallets:write"
}Token Lifecycle
Access tokens expire after the duration specified in expires_in (typically 1 hour). Your application should refresh tokens before they expire.
Token Caching
For optimal performance, cache your access token and reuse it until it expires:
class TokenManager {
constructor(clientId, clientSecret) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.token = null;
this.expiresAt = null;
}
async getToken() {
// Return cached token if still valid (with 5-minute buffer)
if (this.token && this.expiresAt > Date.now() + 300000) {
return this.token;
}
// Fetch new token
const response = await fetch('https://auth.phoenixwallet.io/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: this.clientId,
client_secret: this.clientSecret,
scope: 'wallets:read wallets:write',
}),
});
const data = await response.json();
this.token = data.access_token;
this.expiresAt = Date.now() + data.expires_in * 1000;
return this.token;
}
}Available Scopes
Request only the scopes your application needs:
| Scope | Description |
|---|---|
wallets:read | Read wallet data and balances |
wallets:write | Create wallets and perform operations |
policies:read | Read policy configurations |
policies:write | Create and modify policies |
ledger:read | Read ledger entries and history |
events:subscribe | Subscribe to webhook events |
Security Best Practices
Never expose your client secret in client-side code, version control, or logs.
Credential Management
- Store credentials in environment variables or a secure secrets manager
- Use different credentials for development and production environments
- Rotate client secrets periodically
Token Handling
- Never log access tokens
- Use HTTPS for all API requests
- Implement token refresh logic to avoid service interruptions
- Set appropriate token expiry for your use case
Network Security
- Allowlist Phoenix Wallet API endpoints in your firewall
- Use mutual TLS (mTLS) for enhanced security if available
- Monitor for unauthorized access attempts
Error Handling
Common authentication errors:
| Error | Description | Solution |
|---|---|---|
invalid_client | Invalid client credentials | Verify your client ID and secret |
invalid_scope | Requested scope not allowed | Check your allowed scopes |
invalid_grant | Grant type not supported | Use client_credentials |
unauthorized | Token expired or invalid | Refresh your access token |
{
"error": "invalid_client",
"error_description": "Client authentication failed"
}Next Steps
- Follow the Quickstart to make your first API call
- Learn about Error Handling for robust integrations
- Set up Webhooks for real-time notifications