انتقل إلى المحتوى

لم تُترجم هذه الصفحة بعد

تعرض هذه الصفحة النص الإنجليزي حتى تصدر ترجمتها.

Authentication and API keys

Every call to the Clix API carries an API key as a bearer token:

Authorization: Bearer clix_A7bQ2xK_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The key above is a placeholder. There is no X-API-Key header and no cookie-based access for integrations. A key sent in a cookie is deliberately rejected, because a browser attaches cookies to cross-site requests.

What a key looks like

clix_A7bQ2xK_<43 characters of secret>
└────┬────┘ └───────────┬───────────┘
  public id           secret

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 in the sidebar, on a plan that includes API access. On any other plan issuance is refused with 403 {"detail": "API access is not included in your current plan.", …}.

The Admin gives the key a name (at most 100 characters) and a role. The create call returns the plaintext exactly once, with 201:

{
  "key_prefix_hint": "clix_A7bQ2xK",
  "created_at": "2026-09-27T09:00:00+00:00",
  "last_used_at": null,
  "name": "warehouse-sync",
  "role": "CreateInvoice",
  "scopes": ["attachment.download", "attachment.get", "attachment.list", "…"],
  "is_active": true,
  "revoked_at": null,
  "key": "clix_A7bQ2xK_…"
}

scopes lists every permission id the role holds; it is shortened here. Afterwards, the list returns only key_prefix_hint, created_at and last_used_at for each key, and leaves revoked keys out.

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, notes, clients, items and devices; preview an invoice; fetch the PDF
CreateInvoice The above, plus create invoices, notes, clients and items, update clients and items, and retry a ZATCA submission
Accountant The same as CreateInvoice on the Integration API. Its extra permissions, bank statements and VAT reports, are not on the key surface

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.

Give each integration the narrowest role that lets it do its job. The per-endpoint role is in the API reference.

Some endpoints need no role

The code lists (/api/invoices/vat-categories/ and friends) and /api/usage/current/ check only that the key is valid. Any key, whatever its role, can read them. The code lists 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. Revoking an already-revoked key changes nothing and keeps its original revoked_at.

Invoices already issued with a revoked key are unaffected. They are real invoices and stay cleared.

When a key is refused

Response Cause
401 {"status": "false", "message": "Missing or invalid token (use Authorization: Bearer <token> or accessToken cookie)"} No Authorization: Bearer header
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 plan is checked on every request, not only at issuance. If a plan loses API access, existing keys stop working on the next request without being revoked; if access returns, the same keys work again.

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, not key 1.
  • last_used_at is stamped at most once a minute; use it to find keys nothing uses any more.