UC-014 — API Key Management
| Field | Value |
|---|---|
| ID | UC-014 |
| Goal | Create, inspect and revoke API Keys for your account |
| Channel | All |
| Complexity | Basic |
| Estimated time | 5 minutes |
| APIs involved | GET /api/partner-gateway/v1/authentication, GET /api/partner-gateway/v1/authentication/me, POST /api/partner-gateway/v1/authentication, DELETE /api/partner-gateway/v1/authentication/{id} |
Real-world scenarios
- Developer onboarding: The team lead creates a dedicated API Key for a new integration, scoped to only the operations that integration needs.
- Periodic key rotation: FinSecure rotates its API Keys every 90 days as required by internal security policy.
- Revoke a compromised key: A developer accidentally committed an API Key to a public repository and needs to revoke it immediately.
Management flow
The diagram shows the complete API Key lifecycle: scope check, creation, listing and revocation.
Prerequisites
- Active account on the Qlara platform
- At least one existing API Key to authenticate management calls
- The calling key must be authorized for the
AUTHENTICATIONoperation
Step 1 — Check what your current key can do
Before creating a key, inspect the one you are calling with. A new key can only be granted operations the calling key already holds, so this tells you the maximum scope available to you.
curl -X GET https://api.qlara.ai/api/partner-gateway/v1/authentication/me \
-H "X-Api-Key: YOUR_API_KEY"
Response — Current key
{
"id": 1,
"companyId": 100,
"userId": 42,
"username": "api-user",
"trafficType": 0,
"operations": ["SMS", "RCS", "WHATSAPP"],
"creationDate": "2025-03-10 14:30:00.000+0100",
"lastUpdateDate": "2025-03-10 14:30:00.000+0100"
}
The key is read from the X-Api-Key header, so this endpoint takes no parameters and never
echoes the key value back. It replaces the removed GET /authentication/{value}, which took a
raw key in the URL.
Step 2 — Create a new API Key
Call the creation endpoint to generate a new key.
curl -X POST https://api.qlara.ai/api/partner-gateway/v1/authentication \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"userId": 4618,
"trafficType": 0,
"operations": ["SMS", "RCS", "WHATSAPP"]
}'
| Field | Required | Description |
|---|---|---|
userId | Yes | ID of the user the key belongs to. Keys without a userId are orphan and cannot be deleted through this API. |
operations | Yes | Operations the key may perform. Must be a non-empty subset of the operations held by the calling key. |
trafficType | No | Traffic type identifier (0 = standard). Leave at 0 unless instructed otherwise. |
Allowed values for operations: CONTACTS, SOCIALS, INBOX, AUTOMATION, MEDIA,
MESSAGES, EMAIL, REPORT, CALENDAR, SUBSCRIPTION, AUTHENTICATION, RCS, WHATSAPP,
SMS, CAMPAIGNS, EXPORTS, WEBHOOKS.
Response — Key created
{
"id": 1,
"companyId": 100,
"apiKey": "ak_live_abc123def456",
"username": null,
"trafficType": 0,
"operations": ["SMS", "RCS", "WHATSAPP"],
"creationDate": "2025-03-10 14:30:00.000+0100"
}
The apiKey field is shown only at creation time. Copy it and store it in a secret manager
(e.g. Vault, AWS Secrets Manager). It cannot be retrieved again through any endpoint.
Keys created here are identified by their id and userId and carry no username, so username
in the response is always null. A username sent in the request body is ignored.
Behind the scenes — Key generation and scoping
- Authorization: The gateway resolves the calling key and checks it is authorized for the
AUTHENTICATIONoperation. - Scope check: The requested
operationsare compared against the calling key's own operations. Anything beyond them is refused with403— a key cannot grant privileges it does not have. - Generation: A key string is generated and returned once, in this response only.
- Association: The key is linked to the company of the calling key and to the
userIdyou supplied.
Step 3 — List existing keys
Retrieve the API Keys associated with your account. Add the optional userId query parameter to
filter by owner.
curl -X GET https://api.qlara.ai/api/partner-gateway/v1/authentication \
-H "X-Api-Key: YOUR_API_KEY"
Response — Key list
[
{
"id": 1,
"companyId": 100,
"userId": 4618,
"username": "api-user",
"trafficType": 0,
"operations": ["SMS", "RCS", "WHATSAPP"],
"creationDate": "2025-03-10 14:30:00.000+0100",
"lastUpdateDate": "2025-03-10 14:30:00.000+0100"
},
{
"id": 2,
"companyId": 100,
"userId": 5172,
"username": null,
"trafficType": 0,
"operations": ["CONTACTS", "CAMPAIGNS", "MESSAGES"],
"creationDate": "2026-01-15 09:00:00.000+0100",
"lastUpdateDate": "2026-01-15 09:00:00.000+0100"
}
]
The full key value is never returned by this endpoint — only its metadata.
Step 4 — Revoke a compromised key
Delete a key that should no longer be used. The key id goes in the path.
curl -X DELETE https://api.qlara.ai/api/partner-gateway/v1/authentication/1 \
-H "X-Api-Key: YOUR_API_KEY"
Response — Key revoked
204 No Content — the response has no body. A key that does not exist returns 404.
Behind the scenes — What happens after revocation
- Immediate invalidation: The key is removed from the Key Store. Subsequent requests using it receive
401 Unauthorized. - No rollback: Deletion is irreversible. To restore access, create a new key.
- Orphan keys: A key stored without a
userIdcannot be deleted through this API — this is whyuserIdis required at creation.
Expected result
| Step | Action | Result |
|---|---|---|
| 1 | GET /authentication/me | 200 OK with the calling key's operations |
| 2 | POST /authentication | 201 Created, full apiKey returned once |
| 3 | GET /authentication | 200 OK with the array of keys (no key values) |
| 4 | DELETE /authentication/{id} | 204 No Content |
Complete end-to-end example
Scenario FinSecure: quarterly key rotation.
BASE=https://api.qlara.ai/api/partner-gateway/v1
# 1. Check the scope available to the calling key
curl -s -X GET "$BASE/authentication/me" \
-H "X-Api-Key: $CURRENT_KEY" | jq '.operations'
# 2. Create the new key, scoped to the same operations
NEW_KEY=$(curl -s -X POST "$BASE/authentication" \
-H "Content-Type: application/json" \
-H "X-Api-Key: $CURRENT_KEY" \
-d '{
"userId": 4618,
"trafficType": 0,
"operations": ["SMS", "RCS", "WHATSAPP"]
}' | jq -r '.apiKey')
echo "New key: $NEW_KEY"
# 3. Verify the new key works and inspect its scope
curl -s -X GET "$BASE/authentication/me" \
-H "X-Api-Key: $NEW_KEY" | jq '{id, operations}'
# 4. Revoke the old key by its id
curl -s -o /dev/null -w "%{http_code}\n" \
-X DELETE "$BASE/authentication/$OLD_KEY_ID" \
-H "X-Api-Key: $NEW_KEY"
Variants
Create a least-privilege key per integration
Scope each key to the smallest set of operations that covers its job:
# Sender-only key
curl -X POST https://api.qlara.ai/api/partner-gateway/v1/authentication \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{"userId": 4618, "operations": ["SMS"]}'
# Marketing automation key
curl -X POST https://api.qlara.ai/api/partner-gateway/v1/authentication \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{"userId": 4618, "operations": ["CONTACTS", "CAMPAIGNS", "MESSAGES"]}'
Common errors
400 Bad Request — Missing or empty operations
{
"status": "fail",
"data": {
"operations": "operations is required: a key with no operations cannot authenticate any request"
}
}
Solution: Send a non-empty operations array. A key with no operations cannot authenticate anything.
401 Unauthorized — Invalid key
{
"error": "Invalid API Key"
}
Solution: Verify that the X-Api-Key header is present and that the key used to manage other keys is still active and authorized for the AUTHENTICATION operation.
403 Forbidden — Requested operations exceed your scope
{
"status": "fail",
"data": {
"operations": "Requested operations exceed the caller's own scope"
}
}
Solution: A key cannot grant privileges it does not have. Call GET /authentication/me to see what the calling key holds, then request a subset of those operations.
404 Not Found — Key does not exist
Solution: Check the id in the path against the list returned by GET /authentication. Keys stored without a userId cannot be deleted through this API.
Next steps
- UC-016 — Monitor Credit and Subscription: Check the status of your subscription and remaining credit
- UC-001 — Send Single SMS: Use your new key to send the first message
- Authentication Guide: Full details on API Key and Basic Auth