Skip to main content

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>

Role System (RBAC)​

API Keys include a role field that controls permissions across all platform endpoints — both REST API and MCP Server.

RoleREST PermissionsMCP ToolsDescription
ownerFull access (*:*)96 (all)Tenant owner
adminFull access (resource wildcards)96 (all)Administrators, integrators. Default for new keys.
editorRead + create/update (no delete, publish, versioning, secrets, members, billing, denylist, session control, manual messaging, cancel)52 (consumer + consumer-profile + builder-read)Operators, builders
memberagents:read, agents:chat, sessions:read, sessions:create only5 (consumer)End-user access

RBAC is enforced universally — the same permission check applies to both JWT and API Key authentication.

Consumer Ops require admin/owner

Tenant-wide operational actions — denylisting a consumer (telemetry:write), suspending/resuming/handing off a session, sending manual messages, or cancelling an in-progress turn (sessions:update on session-control endpoints) — require owner or admin. editor cannot perform these even though it has sessions:update for regular operations.

info

Role defaults to admin for backwards compatibility. All existing keys automatically have role: admin.

Anti-escalation

You cannot create an API Key with a role higher than your own. For example, an editor cannot create an admin key. Attempting to do so returns HTTP 403 ROLE_ESCALATION_DENIED.


Tier System​

The tier is automatically calculated based on the configured RPM (requests per minute):

RPM ConfiguredCalculated TierApplied Rate Limit
1-10default10 req/min
11-50basic50 req/min
51-200premium200 req/min
201+enterprise1000 req/min

Limits by Plan​

PlanMax RPMRPM TiersModel Tiers
free10defaulteconomical
basic50default, basiceconomical, premium
pro200default, basic, premiumeconomical, premium, flagship
enterprise1000allall
Model Tier Enforcement

Your plan also restricts which LLM models you can use. See Models — Model Tiers for details. Requesting a model outside your tier returns HTTP 403 MODEL_TIER_RESTRICTED.


POST /api/keys​

Create a new API Key.

Request Body:

{
"name": "My API Key",
"description": "Optional description",
"prefix": "zhn_live_",
"role": "admin",
"rateLimitPerMinute": 30,
"quotaLimit": 100000,
"expiresInDays": 365
}
FieldTypeRequiredDefaultDescription
namestringYes-Key name
descriptionstringNonullOptional description
prefixstringNozhn_live_zhn_live_, zhn_test_, or zhn_dev_
rateLimitPerMinutenumberNoplan maxRPM limit
quotaLimitnumberNonullTotal request quota (null = unlimited)
rolestringNoadminMCP role: admin, editor, or member
expiresInDaysnumberNonullDays 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",
"role": "admin",
"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",
"role": "admin",
"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",
"role": "admin",
"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​

CodeHTTPDescription
invalid_input400Missing or invalid field
not_found404API Key not found
forbidden403Access denied
plan_limit_exceeded403RPM exceeds plan limit
MODEL_TIER_RESTRICTED403Model tier not allowed for plan
ROLE_ESCALATION_DENIED403Cannot create key with role higher than caller
creation_failed500Failed to create key
revocation_failed400Failed to revoke key