http://localhost:8000/api/v1
Brand APIs require authentication via API key. Include the API key in the request header:
X-API-Key: your-api-key-hereOr via Authorization header:
Authorization: Bearer your-api-key-hereProduct APIs authenticate using license keys provided in the request body.
Create a new license key and associated licenses for a customer.
Endpoint: POST /brand/licenses/provision
Headers:
X-API-Key: Your brand API keyContent-Type: application/json
Request Body:
{
"customer_email": "customer@example.com",
"products": ["product-uuid-1", "product-uuid-2"],
"expiration_date": "2025-12-31T23:59:59Z",
"max_seats": 5,
"idempotency_key": "optional-idempotency-key"
}Fields:
customer_email(required): Customer email addressproducts(required): Array of product UUIDsexpiration_date(optional): ISO 8601 expiration datemax_seats(optional): Maximum concurrent activations (default: 1)idempotency_key(optional): Idempotency key for duplicate prevention
Response (201 Created):
{
"license_key": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"key": "BRAND-XXXX-XXXX-XXXX-XXXX",
"customer_email": "customer@example.com",
"created_at": "2024-01-01T00:00:00Z"
},
"licenses": [
{
"id": "660e8400-e29b-41d4-a716-446655440000",
"product_id": "product-uuid-1",
"status": "valid",
"seat_limit": 5,
"expires_at": "2025-12-31T23:59:59Z",
"created_at": "2024-01-01T00:00:00Z"
}
]
}Error Responses:
400 Bad Request: Invalid request data401 Unauthorized: Invalid or missing API key404 Not Found: Brand or product not found409 Conflict: Duplicate idempotency key
Extend a license's expiration date.
Endpoint: POST /brand/licenses/{license_id}/renew
Headers:
X-API-Key: Your brand API keyContent-Type: application/json
Request Body:
{
"expiration_date": "2026-12-31T23:59:59Z"
}Response (200 OK):
{
"id": "license-uuid",
"status": "valid",
"expires_at": "2026-12-31T23:59:59Z",
"updated_at": "2024-01-01T12:00:00Z"
}Error Responses:
400 Bad Request: Invalid expiration date401 Unauthorized: Invalid API key404 Not Found: License not found
Temporarily disable a license. Suspended licenses cannot be activated.
Endpoint: POST /brand/licenses/{license_id}/suspend
Headers:
X-API-Key: Your brand API key
Response (200 OK):
{
"id": "license-uuid",
"status": "suspended",
"updated_at": "2024-01-01T12:00:00Z"
}Re-enable a suspended license.
Endpoint: POST /brand/licenses/{license_id}/resume
Headers:
X-API-Key: Your brand API key
Response (200 OK):
{
"id": "license-uuid",
"status": "valid",
"updated_at": "2024-01-01T12:00:00Z"
}Permanently cancel a license. Cancelled licenses cannot be reactivated.
Endpoint: POST /brand/licenses/{license_id}/cancel
Headers:
X-API-Key: Your brand API key
Response (200 OK):
{
"id": "license-uuid",
"status": "cancelled",
"updated_at": "2024-01-01T12:00:00Z"
}Query all licenses for a customer by email address.
Endpoint: GET /brand/licenses?email={email}
Headers:
X-API-Key: Your brand API key
Query Parameters:
email(required): Customer email address
Response (200 OK):
{
"licenses": [
{
"id": "license-uuid",
"license_key": {
"id": "key-uuid",
"key": "BRAND-XXXX-XXXX-XXXX-XXXX",
"customer_email": "customer@example.com"
},
"product": {
"id": "product-uuid",
"name": "Product Name",
"slug": "product-slug"
},
"status": "valid",
"seat_limit": 5,
"seats_used": 2,
"seats_remaining": 3,
"expires_at": "2025-12-31T23:59:59Z"
}
]
}Activate a license on a specific instance (URL, hostname, or machine ID).
Endpoint: POST /product/licenses/activate
Headers:
Content-Type: application/json
Request Body:
{
"license_key": "BRAND-XXXX-XXXX-XXXX-XXXX",
"instance_identifier": "https://example.com",
"instance_type": "url"
}Fields:
license_key(required): License key stringinstance_identifier(required): Instance identifier (URL, hostname, or machine ID)instance_type(required): One ofurl,hostname,machine_id
Response (201 Created):
{
"activation_id": "activation-uuid",
"status": "active",
"seats_used": 1,
"seats_remaining": 4,
"activated_at": "2024-01-01T00:00:00Z"
}Error Responses:
400 Bad Request: Invalid request data404 Not Found: License key not found or invalid409 Conflict: License already activated on this instance422 Unprocessable Entity: License invalid, expired, suspended, or seat limit exceeded
Verify license validity and seat availability for a specific instance.
Endpoint: GET /product/licenses/check?license_key={key}&instance_identifier={identifier}
Query Parameters:
license_key(required): License key stringinstance_identifier(required): Instance identifier
Response (200 OK):
{
"is_valid": true,
"license": {
"id": "license-uuid",
"status": "valid",
"seat_limit": 5,
"seats_used": 2,
"seats_remaining": 3,
"expires_at": "2025-12-31T23:59:59Z"
},
"is_activated": true,
"activation": {
"id": "activation-uuid",
"activated_at": "2024-01-01T00:00:00Z",
"last_checked_at": "2024-01-01T12:00:00Z"
}
}Error Responses:
404 Not Found: License key not found422 Unprocessable Entity: License invalid, expired, or suspended
Release a seat for reuse. This deactivates the license on a specific instance.
Endpoint: POST /product/licenses/deactivate
Headers:
Content-Type: application/json
Request Body:
{
"license_key": "BRAND-XXXX-XXXX-XXXX-XXXX",
"instance_identifier": "https://example.com"
}Response (200 OK):
{
"status": "deactivated",
"seats_used": 0,
"seats_remaining": 5
}Error Responses:
404 Not Found: License key or activation not found
Endpoint: GET /health
Response (200 OK):
{
"status": "healthy",
"timestamp": "2024-01-01T00:00:00Z"
}Endpoint: GET /health/db
Response (200 OK):
{
"status": "healthy",
"database": "connected"
}Endpoint: GET /health/cache
Response (200 OK):
{
"status": "healthy",
"cache": "connected"
}Endpoint: GET /ready
Response (200 OK):
{
"status": "ready",
"database": "connected",
"cache": "connected"
}All error responses follow this format:
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message",
"details": {}
}
}VALIDATION_ERROR: Request validation failedAUTHENTICATION_ERROR: Authentication failedAUTHORIZATION_ERROR: Insufficient permissionsNOT_FOUND: Resource not foundCONFLICT: Resource conflict (e.g., duplicate)UNPROCESSABLE_ENTITY: Business rule violation
Rate limiting may be applied to prevent abuse. Check response headers:
X-RateLimit-Limit: Request limit per windowX-RateLimit-Remaining: Remaining requestsX-RateLimit-Reset: Reset time (Unix timestamp)
Brand API write operations support idempotency keys. Include
idempotency_key in the request to ensure idempotent behavior:
- Same key within 24 hours returns cached response
- Prevents duplicate operations
- Useful for retries
List endpoints may support pagination in the future. Check response for:
page: Current page numberpage_size: Items per pagetotal: Total number of itemsnext: URL for next pageprevious: URL for previous page