Version 1.1.0
Last Updated: October 21, 2025
Complete API documentation for Bravura Admin Pro licensing infrastructure.
---
---
Bravura Admin Pro provides a RESTful API for license validation, activation, and management.
Production: https://yourdomain.com/api
Development: http://localhost:8000/api
All API responses follow this format:
{
"success": true,
"message": "Operation completed successfully",
"timestamp": "2025-01-15T12:00:00Z",
"data": { /* endpoint-specific data */ }
}
Error responses:
{
"success": false,
"message": "Error description",
"error_code": "ERROR_CODE",
"timestamp": "2025-01-15T12:00:00Z",
"details": { /* additional error information */ }
}
All requests and responses use application/json unless otherwise specified.
---
Admin endpoints require JWT bearer token authentication.
Obtain Token:
POST /api/admin/login
Content-Type: application/x-www-form-urlencoded
username=admin&password=your_password
Response:
{
"success": true,
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"expires_in": 28800
}
Using Token:
GET /api/admin/licenses
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Customer portal uses password or license key authentication.
Password Login:
POST /api/customer/login
Content-Type: application/json
{
"email": "customer@example.com",
"password": "customer_password"
}
License Key Login:
POST /api/customer/login-license
Content-Type: application/json
{
"license_key": "XXXX-XXXX-XXXX-XXXX"
}
---
Verify a license key and optionally bind to a machine ID.
Endpoint: POST /api/licenses/validate
Request:
{
"license_key": "XXXX-XXXX-XXXX-XXXX",
"machine_id": "optional-machine-identifier",
"app_version": "1.0.0"
}
Success Response:
{
"success": true,
"valid": true,
"tier": "PROFESSIONAL",
"expires": "2026-01-15",
"license_type": "PERPETUAL",
"subscription_active": null,
"offline_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"features": [
"complete_admin_panel",
"subscription_billing",
"white_label",
"priority_support"
],
"remaining_activations": 4,
"has_update_access": true,
"update_expiry_date": "2026-01-15",
"update_access_status": "Active",
"can_access_source": false,
"signed_license_data": {
"license_key": "XXXX-XXXX-XXXX-XXXX",
"tier": "PROFESSIONAL",
"expires": "2026-01-15",
"signature": "cryptographic_signature_here"
}
}
Invalid License Response:
{
"success": true,
"valid": false,
"message": "License has been revoked"
}
Validation Rules:
ACTIVE---
Bind a license to a specific machine ID.
Endpoint: POST /api/licenses/activate
Request:
{
"license_key": "XXXX-XXXX-XXXX-XXXX",
"machine_id": "MACHINE-UUID-HERE",
"machine_name": "John's MacBook Pro",
"app_version": "1.0.0"
}
Success Response:
{
"success": true,
"activated": true,
"activation_count": 1,
"max_activations": 5,
"license_data": {
"license_key": "XXXX-XXXX-XXXX-XXXX",
"tier": "PROFESSIONAL",
"expires": "2026-01-15",
"activated_at": "2025-01-15T12:00:00Z"
}
}
Activation Limit Exceeded:
{
"success": false,
"activated": false,
"message": "Activation limit exceeded. You have used 5 of 5 activations.",
"activation_count": 5,
"max_activations": 5
}
Activation Rules:
max_activations limit---
Retrieve SHA256 hashes of revoked license keys for offline validation.
Endpoint: GET /api/licenses/revocation-list
Response:
{
"success": true,
"revoked_hashes": [
"a1b2c3d4e5f6...",
"f6e5d4c3b2a1..."
],
"count": 2,
"last_updated": "2025-01-15T12:00:00Z",
"cache_ttl": 86400
}
Usage:
Example Validation:
import hashlib
# Hash the license key
license_hash = hashlib.sha256(license_key.encode()).hexdigest()
# Check against revocation list
if license_hash in revoked_hashes:
print("License has been revoked")
else:
print("License is valid")
---
Endpoint: GET /api/admin/licenses
Query Parameters:
page (integer): Page number (default: 1)per_page (integer): Items per page (default: 25, max: 100)search (string): Search by license key or customer emailtier (string): Filter by tier (STANDARD, PROFESSIONAL, ENTERPRISE)status (string): Filter by status (ACTIVE, REVOKED, EXPIRED, SUSPENDED)Response:
{
"success": true,
"licenses": [
{
"id": 1,
"license_key": "XXXX-XXXX-XXXX-XXXX",
"tier": "PROFESSIONAL",
"status": "ACTIVE",
"license_type": "PERPETUAL",
"expiration_date": "2026-01-15",
"activation_count": 1,
"max_activations": 5,
"customer_email": "customer@example.com",
"created_at": "2025-01-15T12:00:00Z",
"amount_paid": 3999.99,
"currency": "USD"
}
],
"total": 150,
"page": 1,
"per_page": 25
}
Endpoint: POST /api/admin/licenses
Request:
{
"customer_email": "customer@example.com",
"tier": "PROFESSIONAL",
"expiration_date": "2026-01-15",
"max_activations": 5,
"stripe_payment_intent": "pi_xxx",
"amount_paid": 3999.99,
"currency": "USD"
}
Response:
{
"success": true,
"message": "License created successfully",
"license": {
"id": 1,
"license_key": "XXXX-XXXX-XXXX-XXXX",
"tier": "PROFESSIONAL",
"status": "ACTIVE",
"customer_email": "customer@example.com"
}
}
Endpoint: PUT /api/admin/licenses/{license_id}
Request:
{
"status": "SUSPENDED",
"tier": "ENTERPRISE",
"expiration_date": "2027-01-15",
"max_activations": 25,
"update_expiry_date": "2027-01-15"
}
Response:
{
"success": true,
"message": "License updated successfully",
"license": {
"id": 1,
"status": "SUSPENDED",
"tier": "ENTERPRISE"
}
}
Endpoint: POST /api/admin/licenses/{license_id}/revoke
Request:
{
"reason": "Customer requested refund"
}
Response:
{
"success": true,
"message": "License revoked successfully",
"license_id": 1
}
Endpoint: GET /api/admin/stats
Response:
{
"licenses": {
"total_licenses": 150,
"active_licenses": 130,
"expired_licenses": 10,
"revoked_licenses": 10,
"by_tier": {
"STANDARD": 50,
"PROFESSIONAL": 75,
"ENTERPRISE": 25
},
"total_revenue": 549850.00,
"refunded_licenses": 5,
"refund_rate": 3.3
},
"customers": {
"total_customers": 140
},
"subscriptions": {
"active_subscriptions": 50,
"mrr": 4999.50
}
}
---
Endpoint: POST /api/webhooks/stripe
Headers:
Stripe-Signature: t=timestamp,v1=signature
Supported Events:
payment_intent.succeeded - One-time purchase completedcharge.refunded - Refund processedcustomer.subscription.created - New subscriptioncustomer.subscription.updated - Subscription modifiedcustomer.subscription.deleted - Subscription canceledinvoice.payment_succeeded - Subscription payment successfulinvoice.payment_failed - Subscription payment failedEvent Processing:
Webhook Testing:
Use Stripe CLI to test webhooks locally:
stripe listen --forward-to localhost:8000/api/webhooks/stripe
stripe trigger payment_intent.succeeded
---
Endpoint: GET /api/customer/licenses
Headers:
Authorization: Bearer {customer_token}
Response:
{
"success": true,
"licenses": [
{
"license_key": "XXXX-XXXX-XXXX-XXXX",
"tier": "PROFESSIONAL",
"status": "ACTIVE",
"license_type": "PERPETUAL",
"expires": "2026-01-15",
"created_at": "2025-01-15T12:00:00Z",
"product_name": "Your Software"
}
]
}
Endpoint: GET /api/customer/downloads
Headers:
Authorization: Bearer {customer_token}
Response:
{
"success": true,
"downloads": [
{
"version": "1.0.0",
"tier": "PROFESSIONAL",
"release_date": "2025-01-15",
"download_url": "https://yourdomain.com/downloads/...",
"file_size": 52428800,
"release_notes": "Initial release"
}
]
}
---
| Code | Description |
|---|---|
| `INVALID_LICENSE` | License key not found or invalid format |
| `LICENSE_EXPIRED` | License has passed expiration date |
| `LICENSE_REVOKED` | License has been revoked |
| `LICENSE_SUSPENDED` | License is temporarily suspended |
| `ACTIVATION_LIMIT_EXCEEDED` | Too many activations |
| `SUBSCRIPTION_INACTIVE` | Subscription has expired or canceled |
| `INVALID_CREDENTIALS` | Login failed |
| `UNAUTHORIZED` | Authentication required |
| `FORBIDDEN` | Insufficient permissions |
| `NOT_FOUND` | Resource not found |
| `VALIDATION_ERROR` | Request validation failed |
| `RATE_LIMIT_EXCEEDED` | Too many requests |
| `WEBHOOK_SIGNATURE_INVALID` | Stripe signature verification failed |
| `DATABASE_ERROR` | Database operation failed |
| `INTERNAL_ERROR` | Unexpected server error |
---
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1642262400
{
"success": false,
"error_code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Please retry after 60 seconds.",
"retry_after": 60
}
---
import requests
def validate_license(license_key, machine_id=None):
url = "https://yourdomain.com/api/licenses/validate"
data = {
"license_key": license_key,
"machine_id": machine_id,
"app_version": "1.0.0"
}
response = requests.post(url, json=data)
result = response.json()
if result["success"] and result["valid"]:
print(f"License valid! Tier: {result['tier']}")
return True
else:
print(f"License invalid: {result.get('message')}")
return False
# Usage
validate_license("XXXX-XXXX-XXXX-XXXX", "MACHINE-UUID")
async function adminLogin(username, password) {
const formData = new URLSearchParams();
formData.append('username', username);
formData.append('password', password);
const response = await fetch('https://yourdomain.com/api/admin/login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formData
});
const result = await response.json();
if (result.success) {
localStorage.setItem('admin_token', result.access_token);
console.log('Login successful');
return result.access_token;
} else {
console.error('Login failed:', result.message);
return null;
}
}
// Usage
adminLogin('admin', 'your_password');
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
public class LicenseActivator
{
private readonly HttpClient _httpClient;
public LicenseActivator()
{
_httpClient = new HttpClient();
}
public async Task<bool> ActivateLicense(string licenseKey, string machineId)
{
var url = "https://yourdomain.com/api/licenses/activate";
var data = new
{
license_key = licenseKey,
machine_id = machineId,
machine_name = Environment.MachineName,
app_version = "1.0.0"
};
var json = JsonSerializer.Serialize(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(url, content);
var responseJson = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<ActivationResponse>(responseJson);
if (result.success && result.activated)
{
Console.WriteLine({{RenderedMarkdown}}quot;License activated! {result.activation_count}/{result.max_activations} activations used");
return true;
}
else
{
Console.WriteLine({{RenderedMarkdown}}quot;Activation failed: {result.message}");
return false;
}
}
}
public class ActivationResponse
{
public bool success { get; set; }
public bool activated { get; set; }
public string message { get; set; }
public int activation_count { get; set; }
public int max_activations { get; set; }
}
---
.env files to version control---
For API questions or issues:
---
Bravura Admin Pro API Reference v1.0.0
Copyright © 2025 Wigley Studios LLC. All rights reserved.