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.
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.
{
"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.
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
Access request fields
/api/v1/auth/request-accessorganizationcontact_namecontact_emailuse_casewebsiterequested_roleThe diagnostics API differs slightly
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.
| Capability | client | admin |
|---|---|---|
| Call /api/v1/chat and conversations | Yes | Yes |
| Rotate or revoke its own key | Yes | Yes |
| Review the access-request queue | No | Yes |
| Mint a key for someone else | No | Yes |
| Rotate or revoke any key by key_id | No | Yes |
There is no separate admin credential or header. An admin key travels in the same X-API-Key. Check what you are holding:
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
/api/v1/auth/keys/rotateRotation 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.
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
Errors and limits
| Status | Meaning |
|---|---|
| 401 | Invalid, revoked or expired key. |
| 403 | Role or scope insufficient, for example a client key calling an admin endpoint. |
| 404 | Unknown resource, or one that does not belong to your key. |
| 409 | State conflict: a request already reviewed, or a duplicate submission. |
| 422 | Validation error. The response names the offending field. |
| 429 | Rate 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.
