{
  "$schema": "https://ckrets.ai/schemas/well-known-ckrets.v1.json",
  "name": "ckrets",
  "version": "0.9.0",
  "status": "beta",
  "statusPage": "https://ckrets.ai/status (planned, not yet published)",
  "description": "Secret tokens for agents, handed over once, to a named recipient, with a receipt.",
  "api": {
    "base": "https://ckrets.ai/v1",
    "live": true,
    "describes": "the production deployment at https://ckrets.ai; a staging copy serves this file unchanged, so read stage in GET /v1/limits to know which deployment answered (prod is production)",
    "openapi": "https://ckrets.ai/openapi.json",
    "stages": {
      "beta": "live in 0.9: launch set, with requests (POST /v1/requests, GET and DELETE /v1/requests/{requestId}, GET /v1/requests/{requestId}/public, POST /v1/requests/{requestId}/answer; the page /q/{requestId}; the MCP tools request_secret and get_request)",
      "preview": "live but opt-in: none yet",
      "planned": "specified, not built (501 not-in-v1): batches (POST /v1/batches, GET and DELETE /v1/batches/{batchId}), domain verification (POST /v1/me/domain, POST /v1/me/domain/verify), webhooks (POST /v1/me/webhooks, DELETE /v1/me/webhooks/{webhookId}), the signed-agent tier; delegation (POST /v1/me/key/delegate)"
    },
    "contractVersion": {
      "header": "Ckrets-Version",
      "current": "2026-11-06",
      "supported": [
        "2026-11-06"
      ],
      "missing": "the original contract",
      "rule": "a new date only for a breaking change; an old date is served for at least 12 months after the next; announced in /changelog.md",
      "launched": "2026-11-06, the beta launch date: the first contract"
    }
  },
  "mcp": {
    "url": "https://ckrets.ai/mcp",
    "transport": "streamable-http",
    "stdio": "npx -y @ckrets/mcp@0.9.0",
    "stance": "create-but-never-read",
    "tools": [
      "create_secret",
      "get_secret_status",
      "revoke_secret",
      "get_limits",
      "get_public_view",
      "verify_receipt",
      "deliver_secret",
      "reveal_secret",
      "request_secret",
      "get_request"
    ],
    "availability": {
      "remote_v1": [
        "create_secret",
        "get_secret_status",
        "revoke_secret",
        "get_limits",
        "get_public_view",
        "verify_receipt",
        "request_secret",
        "get_request"
      ],
      "stdio_only": [
        "deliver_secret",
        "reveal_secret"
      ]
    },
    "toolNotes": {
      "deliver_secret": "stdio server only: the remote server does not list it",
      "reveal_secret": "stdio server only, off unless its operator enables it; the remote server has none",
      "request_secret": "returns the page's url to show the user: credentials never go through the chat"
    }
  },
  "docs": {
    "llms": "https://ckrets.ai/llms.txt",
    "llmsFull": "https://ckrets.ai/llms-full.txt",
    "skill": "https://ckrets.ai/SKILL.md"
  },
  "auth": {
    "anonymous": true,
    "ciOidc": {
      "create": true,
      "audience": "https://ckrets.ai",
      "limits": "free key, per repository",
      "note": "a CI pipeline should hold no ckrets key"
    },
    "httpMessageSignatures": {
      "rfc": 9421,
      "tier": "signed",
      "directory": "the caller's /.well-known/http-message-signatures-directory",
      "stage": "planned"
    },
    "apiKey": {
      "header": "Authorization",
      "scheme": "Bearer",
      "keyFormat": "ck_live_…",
      "keyIdFormat": "key_…",
      "mint": "POST https://ckrets.ai/v1/keys",
      "leaseHours": 24,
      "leaseMaxDays": 7,
      "oneHeader": "Authorization: Bearer carries every credential; the kind is read from the prefix: ck_live_ (key or lease), ckm_ (manage token), cka_ (account session), a JWT (CI OIDC); a first-party app's layer holds none and signs its private-API calls with SigV4"
    },
    "anonymousProof": {
      "header": "Ckrets-Proof",
      "kinds": [
        "stamp",
        "session"
      ]
    }
  },
  "audience": {
    "types": [
      "key",
      "oidc",
      "httpsig",
      "publicKey"
    ],
    "oidcAudience": "https://ckrets.ai",
    "stages": {
      "httpsig": "planned"
    }
  },
  "limits": {
    "url": "https://ckrets.ai/v1/limits",
    "headers": [
      "RateLimit-Limit",
      "RateLimit-Remaining",
      "RateLimit-Reset",
      "Ckrets-Tier",
      "Ckrets-App"
    ],
    "retry": {
      "rate-limited": "Retry-After present, retryable true",
      "quota-exhausted": "no Retry-After, retryable false, resetsAt",
      "tier-budget-exhausted": "503, retryable false, Retry-After = seconds until 00:00 UTC",
      "temporarily-unavailable": "503, Retry-After 1, retryable true; with outcome unknown, retryable false: read check first",
      "rule": "retryable appears on every 429 and 503 and on 409 idempotency-in-progress and idempotency-key-retired; absent, the answer is final for that request. After three rate-limited answers in a row, stop and read /v1/limits",
      "idempotency-in-progress": "409, Retry-After 1, retryable true: send the same request again; it then gets the first answer",
      "idempotency-key-retired": "409, retryable false: use a new key",
      "retryableOn": [
        "429",
        "503",
        "409 idempotency-in-progress",
        "409 idempotency-key-retired"
      ]
    },
    "tiers": {
      "anonymous": {
        "valueBytes": 1024,
        "ttlDefault": "P7D",
        "ttlMax": "P7D",
        "revealsMax": 1,
        "createsPerHour": 60,
        "createsPerDay": 300,
        "revealAttempts": 5,
        "proofOfWork": true,
        "audience": true,
        "batches": false,
        "requests": false,
        "webhooks": false,
        "netCreatesPerHour": 240,
        "netCreatesPerDay": 1200,
        "network": "IPv4 /24, IPv6 /48: every address in it shares these"
      },
      "signed": {
        "valueBytes": 4096,
        "ttlDefault": "P7D",
        "ttlMax": "P7D",
        "revealsMax": 3,
        "createsPerHour": 300,
        "createsPerDay": 3000,
        "revealAttempts": 5,
        "audience": true,
        "batchMax": 20,
        "requests": true,
        "webhooks": "signing directory host",
        "stage": "planned"
      },
      "free": {
        "valueBytes": 65536,
        "ttlDefault": "P7D",
        "ttlMax": "P365D",
        "revealsMax": 10,
        "createsPerDay": 1000,
        "revealAttempts": 10,
        "audience": true,
        "batchMax": 100,
        "requests": true,
        "webhooks": "verified domain"
      }
    },
    "stamp": {
      "defaultDifficulty": 11,
      "challengeIn428Body": true,
      "when": "anonymous tier under distributed load"
    },
    "requests": {
      "who": "a ckrets key (a free key or lease, or a paid key once paid keys exist)",
      "free": {
        "perHour": 5,
        "perDay": 20,
        "pendingAtOnce": 3
      },
      "paid": {
        "perHour": 20,
        "perDay": 100,
        "pendingAtOnce": 5
      },
      "ttlMax": "PT1H",
      "ttlDefault": "PT10M",
      "promptMax": 140,
      "answersPerAddressHour": 10,
      "wrongShapesBeforeClose": 3,
      "answerCost": "one create from the asking key's daily creates",
      "secretTtl": "PT1H",
      "reportsToHold": 2
    }
  },
  "encryption": {
    "default": "server-side under the agent tenant key; the platform can read the value",
    "clientEncrypted": {
      "flag": "clientEncrypted",
      "scheme": "AES-256-GCM value; data key wrapped by HPKE, carried in the URL fragment, or derived from a passphrase",
      "spec": "https://ckrets.ai/docs/client-encryption.md"
    }
  },
  "receipts": {
    "alg": "ES256",
    "jwks": "https://ckrets.ai/.well-known/jwks.json",
    "verify": "https://ckrets.ai/docs/receipts.md",
    "signingProfile": "https://ckrets.ai/docs/signing.md",
    "offlineVerification": true,
    "claims": [
      "iss",
      "iat",
      "jti",
      "typ",
      "ver",
      "tok",
      "dig",
      "pol",
      "aud",
      "cre",
      "spo",
      "rcp",
      "pur",
      "exp",
      "siz",
      "app",
      "ce"
    ],
    "iss": "the issuing environment's origin; https://ckrets.ai in production",
    "digest": "hmac-sha256 with a per-secret digestKey returned to the creator and the recipient only",
    "ver": 1
  },
  "webhooks": {
    "stage": "planned: POST /v1/me/webhooks and DELETE /v1/me/webhooks/{webhookId} answer 501 today, and no event is sent yet; a key's webhooks are listed in GET /v1/me/key",
    "signing": "same JWKS as receipts",
    "hostRule": "the key's verified domain or the signing directory's host only",
    "events": [
      "secret.created",
      "secret.revealed",
      "secret.reveal_denied",
      "secret.consumed_attempt",
      "secret.expired_unrevealed",
      "secret.revoked",
      "batch.completed",
      "request.fulfilled",
      "request.expired",
      "lease.renewed",
      "lease.revoked"
    ]
  },
  "retention": {
    "valueAfterLastReveal": "none",
    "metadataMonths": 13,
    "accessRecordDays": {
      "api": 30,
      "puzzlebox": 90
    },
    "accessRecordReportedOrPreservedDays": {
      "puzzlebox": 365
    },
    "backupDays": 7,
    "deletion": "a revoked or last-revealed value is unreadable at once and leaves backups within backupDays; an account's data key, deleted at contract end, stops working within the key cache's lifetime (about 5 minutes for ckrets custody, about 60 seconds for customer custody)"
  },
  "noModelRunsHere": true,
  "report": {
    "method": "POST",
    "url": "https://ckrets.ai/v1/report",
    "body": "{token (or the share url), reason}",
    "answer": "202 with a case id, the same whether or not the token exists"
  },
  "securityTxt": "https://ckrets.ai/.well-known/security.txt (planned, not yet published)",
  "legal": { "terms": "https://ckrets.ai/docs/terms", "privacy": "https://ckrets.ai/docs/privacy", "contacts": "the DSA and OSA points of contact are not published yet; until they are, POST /v1/report" },
  "tokens": {
    "format": "ck_ + 26 Crockford base32 characters",
    "entropyBits": 130,
    "timeOrdered": false
  },
  "platform": {
    "role": "the unlock service under every ckrets product",
    "templates": [
      "onetime",
      "puzzle"
    ],
    "apps": {
      "api": "agents, CI, people at ckrets.ai",
      "puzzlebox": "pleaseunbox.com"
    },
    "limitsPer": "(app, tier)",
    "cors": "first-party app origins only",
    "publicMetadata": "GET /v1/secrets/{token}/public",
    "attempts": "POST /v1/secrets/{token}/attempts",
    "policyChanges": "PATCH /v1/secrets/{token}/policy, tightening only"
  },
  "compatibility": {
    "majorInPath": "/v1",
    "stages": "x-ckrets-stage beta (live), preview (live, opt-in) and planned (not built) mark maturity inside major version 1; the path never changes",
    "withinAMajor": "additions only: fields, response enum values, audience and proof kinds, templates, endpoints, events, problem types, receipt claims",
    "clientsMust": "ignore unknown fields; accept unknown values of state, tier and typ",
    "deprecation": "Deprecation and Sunset headers on affected responses, a row in deprecations below, a line in /llms.txt, at least six months, then 410 feature-sunset",
    "newMajor": "only for changes that cannot be additive; the previous major runs at least twelve months more",
    "grandfathering": "a feature a stored secret depends on (a proof kind, a template, a wrapped-key format name, a receipt claim) is grandfathered per record until that record expires; a sunset never breaks a reveal",
    "limits": "policy, not contract: sizes, TTLs, counts, cooldowns and budgets change at /limits.md and GET /v1/limits with 30 days' notice, abuse response excepted",
    "scope": "the agent API, first-party app routes and the puzzle layer's browser-facing routes alike, with the common headers",
    "reviewed": "2026-10-26"
  },
  "deprecations": []
}
