Authentication and API keys¶
Every call to the Clix API carries an API key as a bearer token:
There is no X-API-Key header and no cookie-based access for integrations. A key sent in a cookie is deliberately rejected — that would be forgeable from a browser.
What a key looks like¶
The 12-character prefix — clix_ plus a 7-character public id — is the key's public name. It identifies the key in listings and is what you pass when revoking. It shares no bytes with the secret, so it is safe to log and to put in a ticket.
Clix stores only a SHA-256 hash of the whole key. The full key is shown once, at creation. If you lose it, revoke it and issue another; nobody can recover it for you.
Issuing a key¶
Keys are created in the app, not through the API — a key cannot mint another key.
Who. An organisation Admin, under API Keys.
The create call returns the plaintext exactly once:
{
"key_prefix_hint": "clix_A7bQ2xK",
"name": "warehouse-sync",
"role": "CreateInvoice",
"scopes": [],
"is_active": true,
"created_at": "2026-09-27T09:00:00Z",
"last_used_at": null,
"revoked_at": null,
"key": "clix_A7bQ2xK_…"
}
Afterwards, listings return only key_prefix_hint, created_at and last_used_at.
Roles a key may hold¶
A key carries exactly one role, and it is always less than an administrator:
| Role | A key with it can |
|---|---|
ViewInvoice |
Read invoices, clients, items, devices |
CreateInvoice |
The above, plus create invoices, notes, clients and items |
Accountant |
The above |
Admin cannot be given to a key. That is enforced at issuance, not by convention — so a leaked key can never manage users, devices, billing or other keys.
Scopes¶
Scopes narrow a key below its role; they never widen it. A key with role CreateInvoice and scopes ["invoice.get", "invoice.create"] can do those two things and nothing else the role would otherwise permit.
Give each integration the narrowest role and scope set that lets it do its job.
Reference-data endpoints ignore scopes
The code lists (/api/invoices/vat-categories/ and friends) are available to any authenticated caller. A narrowly-scoped key can still read them. They contain no customer data.
Revoking¶
Revoke by key_prefix_hint in the app. There is no cache in front of key resolution, so revocation takes effect on the very next request — no propagation delay.
Invoices already issued with a revoked key are unaffected. They are real invoices and stay cleared.
Two ways a valid key still gets refused¶
| Response | Cause |
|---|---|
401 {"status": "false", "message": "Invalid or revoked API key"} |
Unknown, revoked, or belonging to a deactivated organisation |
403 {"status": "false", "message": "API access is not included in your current plan."} |
The organisation's plan does not include API access |
The second is checked on every request, not only at issuance. If a plan changes, existing keys stop working immediately without being revoked.
Handling keys safely¶
- Store the key in a secret manager, never in a repository or a ticket.
- One key per system, so one can be revoked without stopping the others.
- Name keys for where they run —
warehouse-sync, notkey 1. last_used_atis stamped at most once a minute; use it to find keys nothing uses any more.
Related¶
- Quickstart
- Errors and rate limits
- API keys — the screen in the app