Skip to content

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#

GET/v1/keys
GET/v1/keys/usage
POST/v1/keys
PATCH/v1/keys/{id}
DELETE/v1/keys/{id}

Create a new key with POST /v1/keys. All body fields are optional; omitted fields fall back to their defaults.

ParameterTypeRequiredDescription
namestring | nullOptionalKey name. Defaults to "Default".
allowed_modelsstring[] | nullOptionalAllowlist of model IDs this key may call. Empty or null allows all models.
monthly_budget_krwinteger | nullOptionalMonthly spend cap in KRW. null means unlimited.
monthly_token_limitinteger | nullOptionalMonthly cap on combined input+output tokens. null means unlimited. Exceeding returns 402.
expires_atdatetime | nullOptionalKey expiry time (ISO 8601). null means no expiry.
pii_masking_enabledbooleanOptionalWhether outbound PII masking is applied. Defaults to true.
response_cache_modestringOptionaloff | exact | semantic. Defaults to off. See "Key scopes" below.
scopesstring[] | nullOptionalPermission scopes. Any combination of "chat" and "usage:read"; other values return 422. See "Key scopes" below.
ip_allowliststring[] | nullOptionalAllowed IP/CIDR list (e.g. 203.0.113.0/24). null means no restriction. Invalid entries return 422.
create key
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.

201 Created
{
  "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"
}
Regulated-industry accounts (finance, healthcare, government) cannot create a key with 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.

ParameterTypeRequiredDescription
scopesstring[] | nullOptional["chat"] · ["usage:read"] · both. null = legacy (model calls only).
ip_allowliststring[] | nullOptionalRestricts key usage to these IP/CIDR ranges. Enforced at every key auth point; null means no restriction.
response_cache_modestringOptionaloff (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#

GET/v1/management-keys
POST/v1/management-keys
DELETE/v1/management-keys/{id}

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.

GET/v1/provisioning/keys
POST/v1/provisioning/keys
DELETE/v1/provisioning/keys/{id}

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.

provision child key
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.