# Server-side ingest keys

> Create, rotate and revoke the secret ingest key that authenticates server-side events, keep it out of browser code, and see how it differs from an API token.

An ingest key (`pik_…`) lets a server send events for **one site**. Unlike
the public site id, it's a **secret**: anyone with it can send data to
your site.

## Create or rotate

**Site settings → Tracking → Server ingest key → Create key.** The key is
shown **once**. Copy it into your secret store (environment variable,
secrets manager). We only keep a SHA-256 digest and a short prefix so you
can recognize it.

Creating a key again **rotates** it: the new key works immediately and the
old one stops working. To rotate without downtime, deploy the new key
right after creating it. Events sent with the old key in between get
`401`.

**Revoke** removes the key, and server-side events are rejected until you
create a new one.

Both are also [API operations](/docs/api) (`sites.manage` permission), so
you can rotate keys from your infrastructure tooling.

## Keep it secret

- Never put an ingest key in browser code, mobile apps or public
  repositories. For browsers, the public site id and `/api/event` are the
  right tool.
- Store it in an environment variable, e.g. `PRIVATUS_INGEST_KEY`.
- The WordPress plugin can read it from `wp-config.php`
  (`define( 'PRIVATUS_INGEST_KEY', 'pik_…' );`).

## Ingest keys vs API tokens

| | Ingest key `pik_…` | API token `pat_…` |
|---|---|---|
| Scope | One site | A member's workspace access, narrowed by permissions and sites |
| Can | Send events | Read stats, manage settings, everything in the [API](/docs/api) |
| Used at | `POST /api/events` | Every `.json` endpoint and `/mcp` |

An API token can't send events and an ingest key can't read data.
