Authentication¶
Every request to the Kreuzberg Cloud API carries an API key as a bearer token. There are two flavours:
| Tier | Prefix | How you get one | Limits |
|---|---|---|---|
| Live | kz_ |
Dashboard → API keys | Project quota + plan limits |
| Sandbox | sk_sandbox_ |
POST /v1/sandbox/key (no auth, IP-rate-limited) |
50 pages, 24 h, IP-bound |
Live keys are 32 characters (kz_ + 29 Base62) and scoped to a single
project. The plaintext is shown once at creation — store it somewhere safe.
Use the key¶
All SDKs read the key from a constructor argument. Keep it out of source via an env var:
Python
import os
from kreuzberg_cloud import KreuzbergCloud
with KreuzbergCloud(api_key=os.environ["KREUZBERG_API_KEY"]) as client:
...
curl
curl -H "Authorization: Bearer $KREUZBERG_API_KEY" \
https://api.kreuzberg.dev/v1/extract \
-F file=@invoice.pdf \
-F 'webhook={"url":""}'
How it works¶
- The bearer token is SHA-256 hashed in transit and compared against the
api_keystable. - A two-tier cache (NATS KV
configbucket → PostgreSQL) keeps validation sub-millisecond on the hot path. - Each authenticated request resolves to a
project_id. PostgreSQL Row-Level Security restricts every query to that project — there is no cross-tenant data leak surface.
Failure modes¶
401 Unauthorized— the bearer token is missing, malformed, or doesn't match any active key.403 Forbidden— the key is valid but the project doesn't own the requested resource (e.g. someone else'sjob_id).429 Too Many Requests— the project (or sandbox IP) is over its rate or page quota.
Sandbox keys¶
The anonymous sandbox issues short-lived sk_sandbox_ keys via
POST /v1/sandbox/key. They're meant for unauthenticated trial use from the
docs and the landing page — don't ship them in production code.