Agent-readable docs index: /llms.txt. Full docs in one file: /llms-full.txt. Download /docs.zip to grep all markdown files locally.
By default the masking response is encrypted under a KEK derived from your bearer string. BYOK lets you supply a per-request AES-256 key that pins the encryption to a customer-managed value. Useful when your platform already has a KMS-backed key your team controls.

How it differs from the default flow

  • Send the request field key — standard-base64 of exactly 32 raw bytes (an AES-256 key). The field is named key, nothing else; there is no byok_key_b64 field and an unknown field is silently ignored, so a typo here quietly falls back to envelope mode.
  • The response has wrapped_dek and nonce_dek set to null; the ciphertext is encrypted directly under your supplied key, no per-request DEK to unwrap.
  • Decrypt with AESGCM(your key) against nonce_payload + ciphertext.

Rejections

The key is validated before any masking work happens, so a bad key costs you nothing. Both failures are 400 Bad Request with a detail string:
detailCause
"key must be valid base64"The value isn't strict standard base64. Use standard base64 (+, /, =), not base64URL, and don't strip padding.
"key must decode to 32 bytes (256 bits), got {n}"It decoded, but to the wrong length. {n} is the actual byte count; a common cause is base64-ing a 64-char hex string (decodes to 64 bytes) instead of the 32 raw bytes.

The call

import base64, os, requests from cryptography.hazmat.primitives.ciphers.aead import AESGCM byok_key = os.urandom(32) resp = requests.post( "https://api.kindi.me/api/v1/mask", headers={"Authorization": "Bearer mk_live_..."}, json={ "text": "Patient John Doe, MRN H123456", "key": base64.b64encode(byok_key).decode(), }, ).json() # No DEK to unwrap; decrypt the payload directly. assert resp["wrapped_dek"] is None assert resp["nonce_dek"] is None plain = AESGCM(byok_key).decrypt( base64.b64decode(resp["nonce_payload"]), base64.b64decode(resp["ciphertext"]), None, ) print(plain.decode())
BYOK keys are never persisted; KINDI uses them once to encrypt the response payload and then forgets them. If you lose the key, the envelope is unrecoverable.