License API Reference
Base URL: https://api.ektasi.io. All POST endpoints require the header
X-Ektasi-Client-Secret: <your secret> (server-side only — never ship it in plaintext JS).
POST /api/v1/license/validate
Activate / bind a purchase code. Domain-locks on first activation.
{ "purchase_code": "xxxx", "product_id": "ektasi_plugin_001", "domain": "shop.com", "instance_id": "uuid" }
→ { "status": "active", "license_token": "…", "expires_at": "…" }
Errors: 401 invalid code · 409 domain lock · 404 unknown product/code · 410 revoked.
POST /api/v1/license/heartbeat
Authoritative state check (the revocation signal).
{ "license_token": "…", "domain": "shop.com" }
→ { "status": "active" | "revoked" | "expired" | "domain_mismatch" }
POST /api/v1/license/entitlement
Request a short-lived capability for a premium action (only granted while active).
{ "license_token": "…", "domain": "shop.com", "capability": "premium" }
→ { "status": "granted", "entitlement": "…", "expires_in": 300 }
GET /api/v1/license/status
Stateless token signature/expiry check (no DB) — ?token=….
POST /api/v1/license/issue
Mint a direct code for an own-platform sale (server-to-server).
{ "product_id": "ektasi_app_001", "email": "buyer@x.com" }
→ { "code": "EKD.…" }
Webhook: POST /api/webhooks/marketplace
Signed (X-Ektasi-Signature, HMAC-SHA256). Normalized event types drive license status:
revoke (refund, dispute, subscription.cancelled, payment.failed) ·
reactivate (subscription.renewed, payment.succeeded). Selector: purchase_code | license_id | subscription_ref.