API Keys & Provisioning
Issue and manage plm_ API keys, and provision child keys with a management key for automation.
The endpoints on this page are for dashboard managementand authenticate with your logged-in session's JWT access token (Authorization: Bearer <JWT access token>). They cannot be called with a plm_ key or an SDK-compatible token. The plm_ keys you create here are what you then use for OpenAI / Anthropic SDK calls.
Personal keys#
Create a new key with POST /v1/keys. All body fields are optional; omitted fields fall back to their defaults.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | null | Optional | Key name. Defaults to "Default". |
| allowed_models | string[] | null | Optional | Allowlist of model IDs this key may call. Empty or null allows all models. |
| monthly_budget_krw | integer | null | Optional | Monthly spend cap in KRW. null means unlimited. |
| monthly_token_limit | integer | null | Optional | Monthly cap on combined input+output tokens. null means unlimited. Exceeding returns 402. |
| expires_at | datetime | null | Optional | Key expiry time (ISO 8601). null means no expiry. |
| pii_masking_enabled | boolean | Optional | Whether outbound PII masking is applied. Defaults to true. |
| response_cache_mode | string | Optional | off | exact | semantic. Defaults to off. See "Key scopes" below. |
| scopes | string[] | null | Optional | Permission scopes. Any combination of "chat" and "usage:read"; other values return 422. See "Key scopes" below. |
| ip_allowlist | string[] | null | Optional | Allowed IP/CIDR list (e.g. 203.0.113.0/24). null means no restriction. Invalid entries return 422. |
curl https://apirouter.pleum.ai/v1/keys \
-H "Authorization: Bearer <JWT access token>" \
-H "Content-Type: application/json" \
-d '{
"name": "production",
"allowed_models": ["gpt-4o", "claude-sonnet-4-6"],
"monthly_budget_krw": 50000,
"expires_at": "2026-12-31T23:59:59Z",
"pii_masking_enabled": true,
"response_cache_mode": "off",
"scopes": ["chat"],
"ip_allowlist": ["203.0.113.0/24"]
}'The response includes the key metadata plus key (the full secret). The full key is shown only once at creation — afterward only the key_prefix (e.g. plm_a1b2) is retrievable. Store it somewhere safe right away.
{
"id": "k_a1b2c3d4",
"name": "production",
"key_prefix": "plm_a1b2",
"key": "plm_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"allowed_models": ["gpt-4o", "claude-sonnet-4-6"],
"monthly_budget_krw": 50000,
"is_active": true,
"pii_masking_enabled": true,
"response_cache_mode": "off",
"scopes": ["chat"],
"ip_allowlist": ["203.0.113.0/24"],
"created_at": "2026-06-27T09:00:00Z",
"expires_at": "2026-12-31T23:59:59Z"
}pii_masking_enabled=false, nor turn masking off — doing so returns a 403.Key scopes#
scopes limits which APIs a key may call. "chat" allows model calls (billed calls) and "usage:read" allows the read-only usage report (GET /v1/usage/report). null (the default) is the legacy behavior: model calls only. If you set scopes without "chat", billed calls are rejected with a 403 — letting you mint monitoring-only keys with no spend permission.
| Parameter | Type | Required | Description |
|---|---|---|---|
| scopes | string[] | null | Optional | ["chat"] · ["usage:read"] · both. null = legacy (model calls only). |
| ip_allowlist | string[] | null | Optional | Restricts key usage to these IP/CIDR ranges. Enforced at every key auth point; null means no restriction. |
| response_cache_mode | string | Optional | off (default) | exact (exact request match) | semantic (exact match + embedding similarity). On a cache hit the response is served without a provider call, nothing is billed, and the response carries "cached": true. |
Management & provisioning keys#
Issue a plmk_ management key with POST /v1/management-keys (body {name}). A management key is used to provision child keys, and the full key is shown only once at creation. It supports GET · POST (201) · DELETE.
The provisioning endpoint (/v1/provisioning/keys) authenticates with the plmk_ management key, not a JWT (Authorization: Bearer plmk_...). It is meant for CI / automation that needs to mint keys without a dashboard session. It supports GET(list the owner's keys) · POST (201, create a child key) · DELETE.
curl https://apirouter.pleum.ai/v1/provisioning/keys \
-H "Authorization: Bearer plmk_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "ci-runner",
"monthly_budget_krw": 20000
}'The child-key body (ProvisionKeyCreate) accepts only name and monthly_budget_krw — you cannot set allowed_models, pii_masking_enabled, or expires_at.