API v1

Developer documentation

REST API to verify licenses, list extensions, manage your account programmatically.

Authentication

All authenticated endpoints expect a Bearer token in the Authorization header. Generate keys at /account/api-keys.

curl https://xen-support.com/api/v1/me \
  -H "Authorization: Bearer xs_live_a1b2c3d4e5f6..."

Format clé : xs_live_ + 32 caractères hex. La clé n'est affichée qu'une seule fois à la création — seul son hash SHA-256 est conservé en base.

Rate limiting

60 requests per minute per key (sliding window). When exceeded, you get:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
Retry-After: 60

{"error": {"code": "rate_limited", "message": "Rate limit exceeded (60/min)."}}

GET /api/v1/me

Scope : me:read

{
  "data": {
    "id": 42,
    "email": "user@example.com",
    "name": "John Doe",
    "username": "john-doe",
    "created_at": "2026-01-15 10:32:11"
  }
}

GET /api/v1/extensions

Public — no auth required. Returns published extensions.

curl https://xen-support.com/api/v1/extensions

GET /api/v1/licenses

Scope : licenses:read — Lists your licenses.

GET /api/v1/licenses/{key}

Public verification of a license by key (no auth). Returns validity status.

{
  "data": {
    "valid": true,
    "revoked": false,
    "expired": false,
    "domain": "forum.example.com",
    "expires_at": "2027-01-15 10:32:11",
    "extension": {
      "name": "Teams",
      "slug": "extension",
      "version": "1.0.0"
    }
  }
}

POST /api/v1/licenses/{key}/heartbeat

Scope : licenses:verify — Periodic check from your forum. Updates last_verified_at + verify_count. Body (optional):

POST https://xen-support.com/api/v1/licenses/XS-ABC-DEF-GHI/heartbeat
Authorization: Bearer xs_live_...
Content-Type: application/json

{"domain": "forum.example.com"}

GET /api/v1/orders

Scope : orders:read — Returns last 100 orders for your account.

Webhooks

Configure webhooks at /account/webhooks. Each POST is signed with HMAC-SHA256 in the header X-Webhook-Signature.

Available events:

  • license.activated
  • license.revoked
  • license.domain_changed
  • order.paid
  • order.refunded
  • subscription.created
  • subscription.canceled

Verify signature in PHP:

$payload   = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$expected  = hash_hmac('sha256', $payload, 'whsec_VOTRE_SECRET');
if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}
$event = json_decode($payload, true);
// process $event...

Error handling

All errors return a JSON object:

{
  "error": {
    "code": "license_not_found",
    "message": "License key not found."
  }
}

Common codes: missing_authorization · invalid_token · insufficient_scope · rate_limited · license_not_found · domain_mismatch