Authentication and source tokens
How a zona_live_ token identifies a source, where to keep it, and how to rotate, pause or revoke a key without losing the source's history.
/notify accepts exactly one credential: a source token sent with the Bearer scheme.
Authorization: Bearer zona_live_YOUR_SOURCE_TOKENThe server hashes the token, looks up the key, and derives the owning account and the source from it. Nothing in the request body can change which source an alert belongs to.
What not to send
Link to this sectionThe token is the whole credential. Do not send any of these to /notify, in headers, the body or
the URL:
- Any Supabase key, including a secret or
service_rolekey. - The Zona app user’s Supabase access token.
- A source name, source ID, user ID, hostname or sound name. The token already selects the source, and its name and sound are set in the app.
Never put the token or the Idempotency-Key in a query string. URLs end up in logs.
Keep the token secret
Link to this sectionTreat a source token like a password. It lets anyone who holds it put alerts in your inbox.
| Where it runs | Where to keep the token |
|---|---|
| Your own terminal | An environment variable for the session |
| A Windows PC | Windows Credential Manager, or a user environment variable set through System Properties |
| macOS or Linux | The system keychain or secret service, or a file only your user can read |
| CI | The provider’s encrypted secrets, such as GitHub Actions secrets |
| A server | Your platform’s secret manager, injected as an environment variable |
Keep it out of source control, URLs, logs, screenshots, and the alert itself. title, body,
data and images can all reach a phone’s lock screen, so they are no place for credentials.
# Fail early instead of sending "Bearer " with an empty token.
: "${ZONA_SOURCE_TOKEN:?Set ZONA_SOURCE_TOKEN first}"if ([string]::IsNullOrWhiteSpace($env:ZONA_SOURCE_TOKEN)) {
throw 'Set ZONA_SOURCE_TOKEN first.'
}import os
token = os.environ.get("ZONA_SOURCE_TOKEN")
if not token:
raise SystemExit("Set ZONA_SOURCE_TOKEN first.")const token = process.env.ZONA_SOURCE_TOKEN;
if (!token) throw new Error('Set ZONA_SOURCE_TOKEN first.');One source per sender
Link to this sectionCreate a separate source for each computer or application that should appear on its own in the inbox or play its own sound. A source keeps a permanent ID, a name, a sound and its history no matter how many keys it has used.
Keys and their lifecycle
Link to this sectionA source can hold several access keys, each with its own label. Zona keeps only safe metadata about each key; the token itself is never shown again.
| Field | What it tells you |
|---|---|
| Label | A name for this key, such as Old script or New agent. Renaming a key does not rename the source. |
| Key prefix | A short, non-secret identifier for telling keys apart. It cannot be used to authenticate. |
| Active | A reversible pause switch. A paused key gets 401 INVALID_TOKEN. |
| Last used | When this key last had a new alert accepted. An idempotent replay does not update it. |
| Expires | An optional expiry time. An expired key gets 401 INVALID_TOKEN. |
| Revoked | When the key was permanently revoked. A revoked key cannot be restored. |
Pausing or revoking one key never affects its sibling keys. Pausing or revoking the whole source applies to every key it holds.
Rotate a key
Link to this sectionRotation swaps the credential while the source, its sound, its filters and its history stay the same.
- In Sources, tap Manage access keys on the source and add a new key with a clear label.
- Copy the new token into the sender’s secret store. Zona shows it once.
- Send a test alert with the new token and confirm it lands under the same source.
- Revoke the old key.
When a token is lost or leaked
Link to this sectionRevoke the key in Sources straight away, then create a new key for the same source. Revocation
is permanent, and every later request with the old token returns 401 INVALID_TOKEN.
Keys are created, paused and revoked only in the Zona app, and /notify is the only endpoint a
sender ever calls. Never copy your Zona account session into a script or CI secret.
Plans limit how many sources and unrevoked keys you can have. The numbers are in Errors and limits.