Agent-readable docs index: /llms.txt. Full docs in one file: /llms-full.txt. Download /docs.zip to grep all markdown files locally.

API keys

Every API request authenticates with a bearer of the form:
mk_live_<prefix>_<secret>
prefix is 8 hex characters and is the key's public identity: it appears in the dashboard, in logs, and in usage rows, and is safe to log. secret is a base62-encoded 32-byte random value, shown once at mint time and stored server-side only as a hash. If you lose it, revoke the key and mint a new one; there is no recovery.
The full bearer string is also the decryption root: /mask envelopes are encrypted under a key derived from it (KEK = HKDF(bearer)). Revoking a key therefore makes every outstanding envelope it produced permanently undecryptable. This is by design; treat revocation as cryptographic shredding, and decrypt anything you still need before revoking. (BYOK envelopes are unaffected; they are encrypted under your supplied key.)

Endpoints

All routes accept a browser session or a Bearer key; scope is always the calling user. A key id you don't own returns 404 (never 403).
MethodPathPurpose
POST/v1/keysMint a key. Returns 201 with the full bearer, once.
GET/v1/keysList your keys (metadata only, never secrets).
POST/v1/keys/{key_id}/revokeRevoke. Idempotent.
GET/v1/keys/{key_id}/usageTime-bucketed usage (from/to window, bucket=hour|day).
GET/v1/keys/{key_id}/entitiesRead the key's entity-toggle override.
PUT/v1/keys/{key_id}/entitiesSet or clear ("override": null) that override.

Mint

POST /v1/keys:
FieldTypeDefaultDescription
labelstring | nullnullFree-text label shown in the dashboard.
rate_limit_rpminteger60 (30 for playground)Requests per minute, 1 to 100,000.
is_playgroundbooleanfalsePlayground keys skip billing. Mintable only from a browser session; a Bearer caller requesting one gets 403.
Response (201): key_id, prefix, key (the full bearer, only time it is ever returned), is_playground.

List

Each row: id, prefix, label, rate_limit_rpm, is_playground, created_at, last_used_at, revoked_at (null while active).

Rate limiting

Each key carries its own rate_limit_rpm, enforced as a sliding 60-second window on the masking endpoints; over-limit requests get 429 with a Retry-After header. Details in Rate limits.

Revocation semantics

Revocation is a soft delete (revoked_at is set); the key row and its usage history remain listable. Two things to plan around:
  • Propagation: auth results are cached in-process for up to 60 seconds, so a revoked key may keep working for up to a minute.
  • Envelopes: every envelope minted under the key becomes undecryptable, per the warning above.

Per-key attributes beyond CRUD

AttributeSet viaMeaning
entity_togglesPUT /v1/keys/{key_id}/entitiesPer-key enabled-entity override; null inherits the account set.
is_playgroundat mint onlyRequests skip billing; meant for the dashboard playground and test harnesses, not production traffic.
judge_allowedoperator-onlyGates the per-request LLM-judge opt-in (use_judge). Default off; opt-in on a non-allowed key is silently ignored (the request still succeeds, without the judge). Contact support to have it enabled.

Handling keys safely

  • Read the bearer from an environment variable (KINDI_API_KEY by convention); never commit it. It grants billing-affecting access and decrypts every envelope it produced.
  • Log only the prefix (or key_id), never the full bearer.
  • Mint one key per deployment/environment so revocation has a small blast radius, and remember each key's envelopes die with it.
Keys are managed interactively at dashboard.kindi.me/dashboard/keys.