# Authentication Cognau uses four credentials, and exactly one of them belongs on your server. Confusing them is the most common integration mistake, so it is worth two minutes. | Credential | Looks like | Lives | Grants | |---|---|---|---| | **API key** | `cgn_sk_live_…` / `cgn_sk_test_…` | your server, only | full account access | | **Session token** | `cgn_st_…` | the browser | one WebSocket, once | | **Document token** | returned beside it | the browser | upload to one session | | **Link token** | `cgn_vl_…` | an email or URL | one session, then spent | ## API keys Send as a bearer token: ```bash curl https://machine.cognau.com/api/v1/cockpit/sessions \ -H "Authorization: Bearer cgn_sk_live_…" ``` The key decides both **who** you are and **which environment** you are in. A test key cannot create live sessions and a live key cannot create sandbox ones, so a misconfigured deployment fails loudly instead of quietly billing you. **Never put an API key in a browser.** It grants read access to every session on your account. Only the hash is stored on our side, so a key is shown in full exactly once, at creation; if you lose it, issue another and revoke the old one. Multiple active keys per environment are allowed on purpose, so rotation is create → deploy → revoke, with no window where your integration is down. ## There is no publishable key If you have integrated Stripe or a similar SDK you will go looking for a `cgn_pk_…` to put in your frontend. There isn't one, and you don't need one. A publishable key exists so a browser can *start* something before any server object exists. Here the session already exists before the browser is involved, so the session token covers it — and it is strictly narrower than a publishable key: | | a publishable key | our session token | |---|---|---| | Scope | the whole account | one session | | Lifetime | until you rotate it | expires with the session | | If leaked | works until you notice | already spent | So **no account-level credential of any kind reaches the browser**. The only thing your page ever holds is a token for the single verification it is running. Controlling *where* the widget may be embedded is a separate, server-side setting: see [restricting who can embed you](/docs/embedding#restricting-who-can-embed-you). ## Session tokens Returned by `POST /session/create` and handed to the browser. A session token authorizes exactly one WebSocket connection and nothing else. It is single-use: once a socket opens, the token is spent, which is why a dropped connection ends the session rather than resuming it. A session that also collects a document returns a second token, `documentToken`. The session token is spent the moment the liveness socket opens, so it is gone before the document screens are reached, and a capture is inherently several calls: front, back, a retake. The document token can do exactly one thing, submit a document side to that one session, and there is no read path that accepts it. Pass the whole session object to the widget and it uses both. ## Link tokens The credential inside a verification URL. Weaker than an API key by construction: it can create the one session it is scoped to, and cannot read verdicts, list sessions, or see anything about your account. Treat the URL itself as the secret. Anyone holding it can run one verification that you are billed for, which is why links default to a single use, always expire, and can be revoked instantly.