CrystalQore

Authentication

Authenticate every CrystalQore API request with an API key, tenant ID, and — when the operation is user-scoped — a user email.

Authentication

Every request to /api/v1 identifies who is calling (the API client), which organization to use, and optionally which user the call should act as.

Headers

HeaderRequiredExample
X-API-KeyYes (or Bearer)cq_ + 64 hex characters
AuthorizationAlternative to X-API-KeyBearer cq_…
X-Tenant-IdYesTenant UUID
X-User-EmailPer operationjordan@example.com
Content-TypeOn JSON bodiesapplication/json

Send either X-API-Key or Authorization: Bearer cq_…, not a session cookie. Browser cookies from the CrystalQore app are not accepted.

curl -sS "https://app.crystalqore.com/api/v1/users?limit=5" \
  -H "X-API-Key: $CRYSTALQORE_API_KEY" \
  -H "X-Tenant-Id: $CRYSTALQORE_TENANT_ID"

API keys

Keys are created by CrystalQore operators (Superadmin → API Clients). The full key is shown once.

  • Format: cq_ followed by 64 hexadecimal characters
  • Stored as a hash; only an 11-character prefix is kept for logs
  • Disable, rotate, or delete a client from the same screen
  • Each client has its own permissions, tenant allow-list, rate limit, and optional browser origins

Treat the key like a password. Do not commit it, put it in a mobile app, or share it across integrations. Use one client per system.

Tenant isolation

X-Tenant-Id must be a tenant the client is allowed to access (allow all tenants or an explicit tenant list). A valid key for tenant A cannot read tenant B.

If the tenant is disabled, or the client is not entitled to that tenant, the API returns TENANT_DISABLED or TENANT_ACCESS_DENIED.

User context

X-User-Email must match an enabled user in that tenant. The email is compared case-insensitively.

Required for:

  • POST /contacts, POST /click2dial
  • All chat conversation and message calls
  • GET and POST /calendar
  • PUT /presence

Optional for reads such as users, CDR, contacts, files, fax, and presence. When you send it on CDR or contacts, results are limited to that user.

Missing required user → MISSING_USER_EMAIL. Unknown or disabled user → USER_NOT_FOUND or USER_DISABLED.

Entitlement

After the key and tenant are valid, the API checks the platform.api capability on the tenant. Organizations without API access receive ENTITLEMENT_REQUIRED or SUBSCRIPTION_INACTIVE.

Browser CORS

Server-to-server calls do not need CORS. Browser calls only receive CORS headers when the client's allowed origins list includes that Origin (or *). The playground on docs.crystalqore.com uses a same-origin proxy so you do not need to add the docs site as an origin.

Failed auth

CodeHTTPMeaning
MISSING_API_KEY401No key header
INVALID_API_KEY_FORMAT401Key is not cq_ + 64 hex
INVALID_API_KEY401Unknown or revoked key
CLIENT_DISABLED403Client is disabled
MISSING_TENANT_ID400No X-Tenant-Id
TENANT_ACCESS_DENIED403Tenant not on the client
TENANT_DISABLED403Tenant is disabled
ENTITLEMENT_REQUIRED403Tenant cannot use the API
MISSING_USER_EMAIL400User header required
USER_NOT_FOUND404Email not in this tenant
USER_DISABLED403User is disabled

On this page