Skip to main content

Authentication

CryptoPay uses Bearer token authentication for all API requests. This guide covers how to obtain and use authentication tokens securely.

Getting Your API Key

1. Register an Account

First, create your merchant account:

curl -X POST /api/auth/register \
-H "Content-Type: application/json" \
-d '{
"username": "your-username",
"email": "your-email@example.com",
"password": "your-secure-password",
"shop_name": "Your Business Name"
}'

2. Login to Get Access Token

curl -X POST /api/auth/login \
-H "Content-Type: application/json" \
-d '{
"username": "your-username",
"password": "your-password"
}'

Response:

{
"access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"user": {
"id": 123,
"username": "your-username",
"email": "your-email@example.com"
}
}

Using Authentication Tokens

Bearer Token Format

Include your access token in the Authorization header:

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...

Example API Request

curl -X GET /api/payment-orders/ \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json"

JavaScript Example

const apiKey = process.env.CRYPTOPAY_API_KEY;

const response = await fetch('/api/payment-orders/', {
method: 'GET',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});

Token Management

Token Expiration

  • Access tokens expire after 24 hours
  • Refresh tokens expire after 30 days
  • Use refresh tokens to get new access tokens without re-login

Refreshing Tokens

curl -X POST /api/auth/token/refresh/ \
-H "Content-Type: application/json" \
-d '{
"refresh": "your-refresh-token"
}'

Response:

{
"access": "new-access-token",
"refresh": "new-refresh-token"
}

Automatic Token Refresh

class CryptoPayClient {
constructor(accessToken, refreshToken) {
this.accessToken = accessToken;
this.refreshToken = refreshToken;
}

async makeRequest(url, options = {}) {
let response = await fetch(url, {
...options,
headers: {
'Authorization': `Bearer ${this.accessToken}`,
'Content-Type': 'application/json',
...options.headers
}
});

// If token expired, refresh and retry
if (response.status === 401) {
await this.refreshAccessToken();

response = await fetch(url, {
...options,
headers: {
'Authorization': `Bearer ${this.accessToken}`,
'Content-Type': 'application/json',
...options.headers
}
});
}

return response;
}

async refreshAccessToken() {
const response = await fetch('/api/auth/token/refresh/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
refresh: this.refreshToken
})
});

if (response.ok) {
const data = await response.json();
this.accessToken = data.access;
this.refreshToken = data.refresh;
} else {
throw new Error('Failed to refresh token');
}
}
}

API Key Management

Creating API Keys

For production applications, create dedicated API keys:

  1. Login to your dashboard
  2. Go to Settings > API Keys
  3. Click Create New Key
  4. Set permissions and expiration
  5. Copy the key immediately (it won't be shown again)

API Key Permissions

You can create keys with specific permissions:

  • Read Only: View payment orders and transactions
  • Create Payments: Create new payment orders
  • Manage Webhooks: Configure webhook endpoints
  • Full Access: All operations

Key Rotation

Regularly rotate your API keys for security:

// Environment-based key management
const getApiKey = () => {
const env = process.env.NODE_ENV;

switch (env) {
case 'production':
return process.env.CRYPTOPAY_PROD_API_KEY;
case 'staging':
return process.env.CRYPTOPAY_STAGING_API_KEY;
default:
return process.env.CRYPTOPAY_DEV_API_KEY;
}
};

Security Best Practices

Secure Storage

✅ Do:

// Store in environment variables
const apiKey = process.env.CRYPTOPAY_API_KEY;

// Use secure key management services
const apiKey = await getSecretFromVault('cryptopay-api-key');

❌ Don't:

// Never hardcode keys
const apiKey = 'cp_live_abc123def456';

// Never commit keys to version control
const config = {
apiKey: 'cp_live_abc123def456' // This will be in git history!
};

Network Security

Always use HTTPS for API requests:

// ✅ Secure
const apiUrl = '';

// ❌ Insecure
const apiUrl = 'http://api.cryptopay.com';

Error Handling

Handle authentication errors gracefully:

async function makeAuthenticatedRequest(url, options) {
try {
const response = await fetch(url, {
...options,
headers: {
'Authorization': `Bearer ${apiKey}`,
...options.headers
}
});

if (response.status === 401) {
throw new Error('Authentication failed - check your API key');
} else if (response.status === 403) {
throw new Error('Insufficient permissions for this operation');
} else if (!response.ok) {
throw new Error(`API request failed: ${response.status}`);
}

return await response.json();

} catch (error) {
console.error('API request error:', error);
throw error;
}
}

Testing Authentication

Sandbox Environment

Use sandbox for testing without real money:

const config = {
apiUrl: process.env.NODE_ENV === 'production'
? ''
: 'https://sandbox-api.cryptopay.com',
apiKey: process.env.NODE_ENV === 'production'
? process.env.CRYPTOPAY_PROD_API_KEY
: process.env.CRYPTOPAY_SANDBOX_API_KEY
};

Verify Authentication

Test your authentication setup:

# Test API key validity
curl -X GET /api/auth/verify/ \
-H "Authorization: Bearer YOUR_API_KEY"

Success Response:

{
"valid": true,
"user": {
"id": 123,
"username": "your-username",
"permissions": ["read", "create_payments"]
},
"expires_at": "2024-01-02T12:00:00Z"
}

Common Authentication Errors

401 Unauthorized

Cause: Invalid or expired token Solution: Check your API key or refresh your token

{
"error": {
"code": "INVALID_TOKEN",
"message": "The provided token is invalid or expired"
}
}

403 Forbidden

Cause: Insufficient permissions Solution: Use an API key with appropriate permissions

{
"error": {
"code": "INSUFFICIENT_PERMISSIONS",
"message": "Your API key doesn't have permission for this operation"
}
}

429 Rate Limited

Cause: Too many requests Solution: Implement exponential backoff

{
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests. Try again later."
},
"retry_after": 60
}

HTTP Client Examples

JavaScript with fetch()

const apiKey = process.env.CRYPTOPAY_API_KEY;
const apiUrl = process.env.NODE_ENV === 'production'
? ''
: 'https://sandbox-api.cryptopay.com';

// List payment orders
const response = await fetch(`${apiUrl}/api/payment-orders/`, {
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});

const orders = await response.json();

Python with requests

import os
import requests

api_key = os.environ['CRYPTOPAY_API_KEY']
api_url = '' if os.environ.get('NODE_ENV') == 'production' else 'https://sandbox-api.cryptopay.com'

# List payment orders
response = requests.get(
f'{api_url}/api/payment-orders/',
headers={
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}
)

orders = response.json()

Webhook Authentication

Webhooks use HMAC signatures instead of Bearer tokens:

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedSignature, 'hex')
);
}

app.post('/webhooks/cryptopay', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const payload = JSON.stringify(req.body);

if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}

// Process webhook...
res.status(200).send('OK');
});

Next Steps