Quickstart (5 min)
Option A — MiniShell (fastest, no account needed)
Run the one-liner installer. No account, no credit card, no dependencies. You get $2 of credit immediately — enough for hundreds of Haiku calls. ECDSA-P256 signed receipt on every call. Sign up later and we keep whatever balance is left for you.
macOS / Linux:
curl -fsSL https://cloakapi.io/install.sh | shWindows (PowerShell 5.1+):
irm https://cloakapi.io/install.ps1 | iexVerify the sha256 before running: install.sh.sha256 · install.ps1.sha256
Once installed:
cloakapi chat "What is CloakAPI?"The response prints a Receipt JTI. Verify it:
curl -X POST https://api.cloakapi.io/api/v1/receipts/verify \ -H 'Content-Type: application/json' \ -d '{"jti":"<jti from output above>"}'Option B — Use your existing OpenAI SDK
Sign up at app.cloakapi.io and create a key under Integration → API keys. If you still had anonymous balance left when you signed up, it migrates to your account automatically.
Use any standard OpenAI or Anthropic client — only base_url changes:
pip install openai# ornpm install openai2. Point it at the gateway
from openai import OpenAI
client = OpenAI( base_url="https://api.cloakapi.io/api/v1", api_key="cloak_…",)
resp = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "Summarise the attached email"}],)print(resp.choices[0].message.content)Server-side only. SDK calls use bearer-token auth, which browsers won’t expose cross-origin from
docs.cloakapi.ioor arbitrary pages. If you need browser-side calls, run them fromhttps://app.cloakapi.io(which is on the CORS credentialed allowlist) or proxy through your own backend. Direct fetches from the docs page itself are blocked by our CSP — paste the snippet into your own dev environment.
3. Verify the receipt
Every response includes an X-CloakAPI-Receipt-V2 response header
containing a base64url-encoded JSON OpenReceipt envelope. To verify
it without an account, pass the header value verbatim:
# $RECEIPT = the entire X-CloakAPI-Receipt-V2 header valuecurl -X POST https://api.cloakapi.io/api/v1/receipts/verify \ -H 'Content-Type: application/json' \ -d "{\"receipt\": \"$RECEIPT\"}"The gateway accepts three payload shapes:
- Header value (base64url string) —
{"receipt": "<header>"}(recommended; least typing) - Decoded envelope object —
{"receipt": {"v":2,"alg":"ES256",...}} - JTI lookup —
{"jti": "<jti>"}(requires authentication)
Or paste the envelope into the browser-based verifier at app.cloakapi.io/receipt-verifier.
A valid: true response means:
- the schema is intact,
- the signature was made by a key listed in the public JWKS
(
https://api.cloakapi.io/api/.well-known/cloakapi-receipt-pubkeys.jwks), - the chain
prev_hashlinks into the previous receipt for the same tenant.
Offline verification (no gateway round-trip)
The envelope is independently verifiable. Decode the base64url header,
canonicalise the JSON (sort keys, no whitespace), drop the signature
field, SHA-256 it, then ECDSA-P256 verify with the public key whose
kid matches envelope.kid in the JWKS. Both openai-python and
openai-js SDKs return the receipt header directly via
response.headers["x-cloakapi-receipt-v2"].
A reference Python verifier in 30 lines (uses cryptography):
import base64, json, hashlib, urllib.requestfrom cryptography.hazmat.primitives.asymmetric import ecfrom cryptography.hazmat.primitives.asymmetric.utils import encode_dss_signaturefrom cryptography.hazmat.primitives import hashes
def b64u(s): return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
env = json.loads(b64u(receipt_header_value))jwks = json.loads(urllib.request.urlopen( "https://api.cloakapi.io/api/.well-known/cloakapi-receipt-pubkeys.jwks").read())key = next(k for k in jwks["keys"] if k["kid"] == env["kid"])
sig = b64u(env.pop("signature"))canonical = json.dumps(env, sort_keys=True, separators=(",", ":")).encode()
pub = ec.EllipticCurvePublicNumbers( int.from_bytes(b64u(key["x"]), "big"), int.from_bytes(b64u(key["y"]), "big"), ec.SECP256R1(),).public_key()
pub.verify( encode_dss_signature(int.from_bytes(sig[:32], "big"), int.from_bytes(sig[32:], "big")), canonical, ec.ECDSA(hashes.SHA256()),)print("PASS")That’s it — you’re now sending traffic through a gateway that produces audit-grade evidence on every call.
Where does tokenisation happen on this path? Nowhere — with a bare SDK pointed at
api.cloakapi.io, the gateway is a blind relay: it forwards your request exactly as your client sent it and never inspects, detects, or tokenises content on our servers. To have your PII tokenised, it must happen on your own machine — use Option C below (local proxy), or one of the other client-side ways (browser chat, desktop app, browser extension).
Option C — client-side drop-in (local proxy)
Run the CloakAPI local proxy on your own machine and point any OpenAI/Anthropic client at it. The proxy tokenises on your machine, then forwards only tokens through the CloakAPI gateway to your provider — personal data never leaves your machine, and the gateway stays a blind relay (it sees only tokens) while it meters the call, signs the receipt, and bills the markup. Your provider, model and BYOK key choice are configured in your CloakAPI account — the proxy itself accepts no provider URL (it is gateway-locked by design, so every call gets a signed receipt).
from openai import OpenAI
client = OpenAI( base_url="http://localhost:8799/v1", api_key="unused", # the proxy holds your CloakAPI key; provider keys live in your account)
resp = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "Summarise the email from Alice."}],)print(resp.choices[0].message.content)Configure the proxy with your CloakAPI keys by path (never on the command line):
CLOAK_API_KEY_FILE=/path/to/your/cloakapi-key # your CloakAPI tenant API keyCLOAK_TENANT_HMAC_KEY_FILE=/path/to/your/trust-key # per-tenant pre-tokenised trust key# upstream is always the CloakAPI gateway (https://api.cloakapi.io/api/v1) —# there is no provider-URL setting; BYOK provider keys live in your account.# default listen address: 127.0.0.1:8799 (chosen to dodge RStudio/Jupyter/Dask)# port taken? set CLOAK_PROXY_LISTEN=127.0.0.1:<free-port> and use the SAME# port in your base_url above — the proxy never silently rebinds.What’s covered. Structured PII — emails, phones, cards, national IDs, IBANs, IP addresses (~10 types) — is tokenised deterministically with no model, always on. Free-form personal names are protected by an optional on-device mini-AI (Ollama + Phi by default); with it running, names are tokenised on your machine, and by default, if it is unreachable the proxy fails closed rather than let a name leak.
Limits (honest).
- Streaming is not yet supported —
"stream": truereturns HTTP 501 (planned for Phase 2).- The proxy is stateless per request — it only detokenises tokens whose originals were in that same request (fine for normal chat, which re-sends history).
/v1/modelsand/healthzare available.
Round-trip a file
You’re not limited to text in, text out. Attach a document to any call (see
File attachments) and the model’s response can be
rebuilt into a real file — .docx, .pdf, .xlsx, and 13 other formats — via
POST /v1/reconstruct. Full request/response contract, format list, SDK snippets,
and error codes: File rebuild (round-trip).