Skip to content

Access and API keys

Request access, get a key issued, and use it. The same flow covers both APIs.

Both APIs use the same credential model: a single X-API-Key header, issued through a reviewed access request. Keys are not self-serve, and the secret is shown exactly once.

The access flow

Submit an access request

Public, no authentication. Describe what you are building and roughly how much traffic you expect. You get back a request_id. Keep it, it is how you track the outcome.

bash
curl -X POST "https://api-seerahai.karmat-hq.com/api/v1/auth/request-access" \
  -H "Content-Type: application/json" \
  -d '{
    "organization": "Noor Learning",
    "contact_name": "Aisha Bello",
    "contact_email": "[email protected]",
    "use_case": "Answering student questions inside our mobile study app.",
    "website": "https://noorlearning.com"
  }'

An administrator reviews it

We read the queue and either approve or reject. Approval mints the key; rejection records a reason. Both are audit-logged.

Store the key immediately

The full secret appears once, in the approval response. It is stored only as a peppered hash and cannot be recovered. If you lose it, you rotate. There is no retrieval path.

json
{
  "api_key": "sk_live_a1b2c3d4_9f8e7d6c5b4a...",
  "key": {
    "key_id": "a1b2c3d4",
    "name": "Noor Learning",
    "role": "client",
    "status": "active"
  },
  "warning": "Store this key securely — it will not be shown again."
}

Call the API

Send the key in X-API-Key on every request to a /api/v1/** endpoint.

bash
curl -X POST "https://api-seerahai.karmat-hq.com/api/v1/chat" \
  -H "X-API-Key: $SEERAH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "What does the Quran say about patience?", "end_user_id": "user-8842"}'

Server-side only

An API key must never reach a browser, a mobile binary, or a public repository. Anything a user can open, a user can read. Proxy calls through your own backend and apply your own per-user limits there.

Access request fields

POST/api/v1/auth/request-access
organization
stringRequired
2 to 120 characters. The entity that will hold the key.
contact_name
stringRequired
Who we reply to.
contact_email
emailRequired
Where the approval decision is sent.
use_case
stringRequired
At least 10 characters. What the integration does and roughly how much traffic it expects. Vague requests get rejected; this is the field that decides.
website
string
Optional. Helps us place the request faster.
requested_role
client | admin= client
Seerah AI only. `client` is the normal integration role; `admin` needs manual review.

The diagnostics API differs slightly

Optical Diagnostics names the field purpose rather than use_case, and has no requested_role. Its administrative endpoints are gated by an x-admin-token header instead of an admin key.

Roles and scopes

Seerah AI keys carry a role. A client key is what an integration holds: it calls chat and the conversation endpoints, and can rotate or revoke its own key. An admin key additionally reviews requests and manages any key.

Capabilityclientadmin
Call /api/v1/chat and conversationsYesYes
Rotate or revoke its own keyYesYes
Review the access-request queueNoYes
Mint a key for someone elseNoYes
Rotate or revoke any key by key_idNoYes

There is no separate admin credential or header. An admin key travels in the same X-API-Key. Check what you are holding:

bash
curl "https://api-seerahai.karmat-hq.com/api/v1/auth/keys/me" \
  -H "X-API-Key: $SEERAH_API_KEY"

# An admin key reports "role": "admin" and "scopes": ["*"].

Diagnostics keys carry scopes rather than roles. The default set is inference:text, inference:image, inference:multimodal, uploads:read and uploads:write.

Rotating a key

POST/api/v1/auth/keys/rotate

Rotation issues a fresh secret and keeps the role, scopes and limits. On Seerah AI you can set grace_minutes to keep the old secret alive while a deployment rolls out, so there is no window where requests fail.

bash
curl -X POST "https://api-seerahai.karmat-hq.com/api/v1/auth/keys/rotate" \
  -H "X-API-Key: $SEERAH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"grace_minutes": 30}'

If a key leaks, revoke first

Revocation is instant, free and irreversible. Investigate afterwards. There is no un-revoke, so you issue a new key rather than restoring the old one. On Seerah AI, the last active admin key cannot be revoked.

Errors and limits

StatusMeaning
401Invalid, revoked or expired key.
403Role or scope insufficient, for example a client key calling an admin endpoint.
404Unknown resource, or one that does not belong to your key.
409State conflict: a request already reviewed, or a duplicate submission.
422Validation error. The response names the offending field.
429Rate limited. Read Retry-After and the X-RateLimit-* headers rather than backing off blindly.

Your per-minute limit is attached to the key and reported by GET /api/v1/status on Seerah AI, or GET /api/v1/analytics/usage on diagnostics.