Ingestion
API keys
Every key is a pair — a secret half for shippers and a public half for clients that carry their credentials in a URL.
Fill this page in with a real API key
The samples below carry a placeholder key and an example host. Log in or create an account to issue one and have them rewritten in place.
Or hand it to a coding agent
Copy this prompt into Claude Code — or any agent that can read a URL — and let it do the setup against the current version of this page.
Set up Bilis — self-hosted log and trace storage — in this project, following its "API keys" guide: https://bilis.app/docs/ingestion/api-keys.md Bilis endpoint: https://bilis.app API key: bilis_YOUR_API_KEY Read the guide first, then make the changes it describes. Keep the API key in the environment rather than in a file that gets committed, and finish by sending one record and confirming it arrives.
An API key belongs to one project, and the project it belongs to is the only one it can ever write to. Issue keys from Projects → your project → New API key.
Each key is one credential with two halves. They are issued together, they are revoked together, and they share a rate limit.
| Half | Looks like | Visibility | Used by |
|---|---|---|---|
| Secret | bilis_… |
Shown once, then only a hash is stored | Collectors, shippers, anything that can send a header |
| Public | bilis_pk_… |
Always visible on the project page | Clients configured with a URL instead of a header |
The secret half
This is the one to reach for. Send it as a bearer token, or in X-Bilis-Key if
the client cannot set an Authorization header:
-H "Authorization: Bearer bilis_YOUR_API_KEY"
# or
-H "X-Bilis-Key: bilis_YOUR_API_KEY"
Bilis stores only a sha256 of it, so the plaintext is shown exactly once, when the key is created. Lose it and you issue a new one — there is no way to read it back, by design.
The public half
Some clients are not configured with a header at all. They are handed a single URL that carries the credential inside it, and they build their own requests from it — the Sentry SDKs are the case Bilis supports today, through a Sentry-compatible endpoint.
A credential in a URL is a credential that travels: into a deploy config, into a container environment, and — for anything running in a browser — into the page source. So the public half is stored in plaintext and stays readable on the project page forever. Hashing it would make the URL unrecoverable without buying any secrecy, because the URL itself is the disclosure.
What it can do
Both halves authorise exactly one thing: writing logs into their own project. Neither can read logs, list projects, or touch anything else, so a public key that leaks costs you junk in one project's log stream — not access to your data.
That is still worth acting on. Revoke the key and issue a new one; the shippers using the secret half get the same treatment, which is the trade for keeping one credential with two halves rather than two credentials to track.
For anything running in a browser there is a second lock, and it is not on the key: a page may only post from an origin listed on the project. See Browser origins.
Rate limits
Requests are counted per credential, not per project, so one noisy client cannot
starve another. Over the limit is a 429 with Retry-After, which every
exporter and SDK already treats as retryable. See
Limits and behavior.
Revoking
Revoking removes both halves at once. Anything still using either one starts
getting 401 immediately — there is no grace period, so issue the replacement
first if you cannot afford the gap.