Administration
API keys
Lunax has two kinds of key and they are not interchangeable. One is designed for the browser; the other must never reach it. Both are per app.
The two kinds of key
| Widget key | Secret API key | |
|---|---|---|
| Looks like | lx_w_… | lx_live_… |
| Safe in the browser | Yes — that's its job | Never |
| How many | Exactly one per app | As many as you like |
| Can do | Create tickets and feedback for its app | Create tickets and feedback for its app |
| Rate limited | Yes — 8 and 10 per minute | No |
| Revocable from the UI | No — disable the widget instead | Yes |
| Shown again after creation | Yes, on the keys page | No — copy it once |
Both live under Admin → Apps → Keys & widget for each app.
Widget keys
Every app gets one automatically. It identifies which app a widget submission belongs to, and it's built to be published — think of it like a Stripe publishable key. It appears in your page source, and that's fine.
- It can only create tickets and feedback posts for its own app.
- It cannot read anything — not tickets, not users, not other apps.
- Submissions through it are rate limited per app and IP address.
- To turn it off, disable the widget for that app.
data-user-email pre-fills the form; it does not prove anything. A visitor can type any address, and Lunax will create a confirmed account for it. Never treat the email on a widget-created ticket as authenticated. If you need certainty, use proxy mode and stamp the email server-side from your own session.Secret API keys
Secret keys authenticate server-to-server calls — filing a ticket when a background job fails, or when a payment bounces. They belong in your backend's secret store and nowhere else.
- Scoped to one app. The app is derived from the key, so you never pass an app ID.
- No scopes or granular permissions exist — every key can create tickets and feedback for its app, and nothing more.
- Stored hashed. Lunax cannot show you the value again, and neither can support.
- Not rate limited, unlike widget keys.
Create a secret key
- Open Admin → Apps and choose Keys & widget on the app.
- Name the key after where it will live —
production-api,billing-worker. The name is only a label for you. - Create it, then copy the full value immediately.
- Store it in your secret manager and reload the page.
curl -X POST https://YOUR_LUNAX_HOST/api/v1/tickets \
-H "Authorization: Bearer lx_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"subject": "Nightly export failed",
"description": "Job 4417 exited non-zero. Stack trace attached in logs.",
"requester_email": "ops@acme.com",
"priority": "high",
"category": "bug"
}'Full request and response details are in the REST API reference.
Revoking a key
Press Revoke next to a key. It stops working immediately and every request using it gets a 401. The row stays in the list marked Revoked, so the history is preserved.
The list also shows when each key was last used — the fastest way to spot a key nothing needs any more, and to confirm a rotation actually took effect.
- Revoking is permanent; a revoked key can't be restored.
- To rotate without downtime: create the new key, deploy it, confirm the old key's last-used time stops advancing, then revoke it.
Handling keys safely
- Never put a
lx_live_key in frontend code, aNEXT_PUBLIC_variable, a mobile app, or a public repository. - Use one key per deployment target so you can revoke one without disturbing the rest.
- Anyone holding a secret key can create tickets attributed to any email address, which also creates accounts. Treat it as a privileged credential.
- Rotate on any suspicion of exposure, and whenever someone with access leaves.
- If a widget key is being abused, disable the widget for that app.