Cerberus
Privacy notice
Last updated 19 August 2026
This is a statement of what Cerberus receives, what it does with it, and what it cannot do. It is not a contract and nothing here asks you to agree to anything. Every claim below is true of the code running today — where something is planned rather than shipped, it says so.
1What Cerberus is
Cerberus watches API key usage metadata for companies that issue API keys to their own customers. It looks for one specific pattern: a key that starts being used from many places at once, each doing very little, which is the signature of a credential that has been shared or stolen. When that pattern holds, it sends one Slack message.
It sits beside your API, not in front of it. It never sees a request before you serve it, and it cannot block, delay, or reject anything.
2The twelve fields, and nothing else
Cerberus receives exactly twelve fields per request. The ingest endpoint rejects any field not on this list, by name, so the list is enforced in code rather than promised in prose.
| Field | What it is |
|---|---|
| ts | When the request happened, ISO 8601. |
| key_fp | HMAC-SHA256 of the API key under your own salt, truncated to 128 bits and hex-encoded. |
| endpoint | Which route was called. |
| tokens_in | Prompt tokens. |
| tokens_out | Completion tokens. |
| latency_ms | How long the request took. |
| status | The HTTP status you returned. |
| ip_fp | Fingerprint of the caller's IP address, same construction as key_fp. |
| ip_net_fp | Fingerprint of the surrounding network — /24 for IPv4, /64 for IPv6. |
| ip_block_fp | Fingerprint of the wider block — /16 for IPv4, /48 for IPv6. |
| ip_family | Either "v4" or "v6". |
| costoptional | What the request cost you, if you want to send it. |
There is no field for a prompt, a response, an API key, an IP address, a user identifier, an account name, or an email address. None of those can be sent, because the validator rejects anything it does not recognise.
Token counts are counts, never content. tokens_in: 1180 says the prompt was 1,180 tokens. It says nothing about what the prompt was, and there is no field on the list that could carry it.
3Fingerprints, and why they cannot be reversed
The API key and the IP address never leave your infrastructure. Before anything is transmitted, the SDK computes an HMAC-SHA256 of each value under a secret salt that you generate, that stays in your own secret manager, and that Cerberus never receives.
This matters more than a promise not to look. Without the salt, a fingerprint cannot be reversed — not by us, not by anyone who breaches us, and not by anyone who compels us. We do not hold the thing that would make reversal possible.
A plain hash would not achieve this: the IPv4 address space is small enough that a complete lookup table can be built in minutes. The secret salt is what makes the construction meaningful.
Salts are per-customer. The same IP address hitting two different Cerberus customers produces two unrelated fingerprints. Correlating activity across customers is not something we decline to do; it is something we are structurally unable to do.
4The endpoint field, and what we ask of you
endpoint is the one field that could carry personal data if sent incorrectly, and it is worth being explicit about.
Cerberus expects a route template — /v1/orgs/{org_id}/chat — not the live path a user actually hit. Live paths routinely contain identifiers: email addresses, account IDs, order numbers.
The validator rejects values it can recognise as live paths: anything containing an @, a UUID, a run of six or more digits, or a run of sixteen or more hex characters. These checks do not catch everything. A path like /v1/orgs/acme-corp/chat contains no pattern the validator can detect, and it would be accepted.
So this is a shared responsibility, stated plainly rather than buried: send templates. If you send live paths, Cerberus will store whatever is in them, and our validator cannot promise to catch it.
5What we do with what we receive
Events are aggregated hourly into per-key, per-address, per-hour buckets: how many requests, how many tokens, what they cost. From those buckets, each key gets a baseline describing its ordinary week — how many distinct addresses use it in an hour, and how much each of them does.
The rule compares the current hour to that baseline. If a key shows a sharp rise in distinct addresses, a collapse in requests per address, at least ten distinct addresses, dispersion across unrelated networks, and all of that holding for three consecutive hours, one Slack message is sent to you.
That is the entirety of the processing. There is no profiling of your customers, no scoring of individuals, no model trained across accounts, and no analysis beyond the rule described above.
6Who else sees it
Nobody, with three infrastructure exceptions. Data is not sold, rented, shared with partners, or used for advertising. There is no advertising.
- Vercel hosts the application.
- Supabase hosts the database.
- Slack receives your alerts, because you asked it to. An alert contains a key fingerprint, counts, the window it covers, and a link to silence it — nothing that identifies a person, and no endpoint values.
These are processors acting on our instruction, not recipients with independent use of the data.
On legal compulsion. If we were served a valid legal demand, we would produce what we hold. What we hold is fingerprints under a salt we do not have, request counts, and timestamps. We could not identify a person from it, because we lack the input that would make identification possible.
7How long it is kept
Raw events are deleted thirty days after we receive them. Hourly aggregates are kept for ninety days, because those are what the detection actually reads and a shorter window would blind it. Both are deleted automatically, on a schedule, without anyone asking.
Thirty days runs from when we received the data, not from the timestamp on the event. If you upload three months of history, that history is kept for thirty days from the upload — not deleted immediately for being old.
Deletion on request is available today and is described below. It is manual, and it is done when you ask.
8Deleting your data
Two operations exist and they are different on purpose.
Deactivation stops ingest and stops evaluation immediately. Your data stays, so you can come back without starting a new baseline from zero.
Purge removes everything: raw events, hourly aggregates, baselines, alerts, and suppressions. It is irreversible and it leaves nothing behind.
Ask for either and it is done. Purge is verified against the database schema itself — a test enumerates every table referencing an account and fails if any is missing from the purge, so a future change cannot silently leave data behind while reporting success.
9What this is not
Not a security certification. Cerberus has no SOC 2, no ISO 27001, and no third-party audit. Rather than imply compliance we do not have, the architecture is built so that a breach of Cerberus yields fingerprints nobody can reverse. That is a design decision, not a substitute for an audit, and it is stated here so you can weigh it yourself.
Not a guarantee of detection. Cerberus is deliberately conservative, and there are documented cases it does not catch. Those are published under Known limits on the main page rather than hidden here.
10Changes
Material changes will be communicated directly to active accounts, not published silently with a new date at the top.
11Contact
Questions about anything above, including a request to see or delete what we hold: hello@cerberushq.dev.
This notice describes the state of the system as of the date above. Section 7 records something the system does not yet do, and will be corrected the day it does.