API Keys
Manage API Keys for external integrations. API Keys authenticate calls to LLM, agent, and webhook endpoints.
Authentication
All API Key management endpoints require JWT authentication:
Authorization: Bearer <jwt-token>
x-tenant-id: <uuid>
Tier System
The tier is automatically calculated based on the configured RPM (requests per minute):
| RPM Configured | Calculated Tier | Applied Rate Limit |
|---|---|---|
| 1-10 | default | 10 req/min |
| 11-50 | basic | 50 req/min |
| 51-200 | premium | 200 req/min |
| 201+ | enterprise | 1000 req/min |
Limits by Plan
| Plan | Max RPM | Available Tiers |
|---|---|---|
free | 10 | default |
basic | 50 | default, basic |
pro | 200 | default, basic, premium |
enterprise | 1000 | all |
POST /api/keys
Create a new API Key.
Request Body:
{
"name": "My API Key",
"description": "Optional description",
"prefix": "zhn_live_",
"rateLimitPerMinute": 30,
"quotaLimit": 100000,
"expiresInDays": 365
}
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | - | Key name |
description | string | No | null | Optional description |
prefix | string | No | zhn_live_ | zhn_live_, zhn_test_, or zhn_dev_ |
rateLimitPerMinute | number | No | plan max | RPM limit |
quotaLimit | number | No | null | Total request quota (null = unlimited) |
expiresInDays | number | No | null | Days until expiration (null = never) |
Response (201):
{
"success": true,
"data": {
"id": "uuid",
"api_key": "zhn_live_abc123def456...",
"prefix": "zhn_live_",
"suffix": "...xyz",
"name": "My API Key",
"rate_limit_per_minute": 30,
"calculated_tier": "basic",
"expires_at": "2027-01-16T00:00:00Z"
},
"warning": "Store this API Key securely. It cannot be retrieved later."
}
caution
The full API Key is shown only once at creation time.
GET /api/keys
List all API Keys for the tenant.
Response:
{
"success": true,
"data": [
{
"id": "uuid",
"name": "Production API Key",
"prefix": "zhn_live_",
"suffix": "...abc",
"status": "active",
"rate_limit_per_minute": 50,
"last_used_at": "2026-01-16T10:00:00Z"
}
],
"count": 1
}
GET /api/keys/stats
API Key usage statistics.
Response:
{
"success": true,
"data": {
"total": 5,
"active": 3,
"revoked": 1,
"expired": 1,
"total_requests": 15000
}
}
GET /api/keys/:keyId
Get details of a specific API Key.
Response:
{
"success": true,
"data": {
"id": "uuid",
"name": "My API Key",
"prefix": "zhn_live_",
"suffix": "...xyz",
"status": "active",
"rate_limit_per_minute": 50,
"calculated_tier": "basic",
"expires_at": "2027-01-16T00:00:00Z",
"total_requests": 150,
"tenant": {
"id": "uuid",
"name": "My Company"
}
}
}
PATCH /api/keys/:keyId/rpm
Update the RPM of an existing API Key.
Request Body:
{
"rateLimitPerMinute": 40
}
Response:
{
"success": true,
"data": {
"key_id": "uuid",
"old_rpm": 50,
"new_rpm": 40,
"calculated_tier": "basic"
}
}
DELETE /api/keys/:keyId
Revoke an API Key permanently.
Response:
{
"success": true,
"message": "API Key revoked successfully",
"revoked_at": "2026-01-16T12:00:00Z"
}
Using API Keys
After creating an API Key, use it to authenticate external calls:
curl -X POST "https://llm.zihin.ai/api/v3/llm/public/call" \
-H "X-Api-Key: zhn_live_abc123def456..." \
-H "Content-Type: application/json" \
-d '{"prompt": "Hello!", "model": "auto"}'
Error Codes
| Code | HTTP | Description |
|---|---|---|
invalid_input | 400 | Missing or invalid field |
not_found | 404 | API Key not found |
forbidden | 403 | Access denied |
plan_limit_exceeded | 403 | RPM exceeds plan limit |
creation_failed | 500 | Failed to create key |
revocation_failed | 400 | Failed to revoke key |