Skip to main content

Authentication

How to send your API key, what a key may do, and how to tell a rejected key from one without permission.

Sending the key #

Send the key as a bearer token in the Authorization header. A missing or wrong key is 401. Browsers send it differently; see Browser credentials.

http
Authorization: Bearer <token>

Key format #

Keys have the form srk_<16>_<32>: a 16-character key id and a 32-character secret, both from the alphabet abcdefghijklmnopqrstuvwxyz234567.

text
srk_aaaaaaaaaaaaaaaa_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

A key is shown exactly once, when it is issued, and is never recoverable, because the service keeps only a salted SHA-256 verifier. If you lose a key, issue a new one and revoke the old.

Scopes #

Scopes limit what a key may do. An empty scope set means unrestricted. The asr scope covers creating sessions, streaming and transcribing; admin covers the operator routes. These scopes narrow which sessions a key may create:

  • mode_mt, mode_ts — only the modes named.
  • speakers_1 up to the engine's limit, speakers_8 on HEAT4 and speakers_4 on dicon — expected_num_speakers at most the smallest number the key carries; "auto" counts as the whole limit, eight speakers on HEAT4 and four on dicon. A scope above the engine's limit is refused, never ignored.
  • store_content — required to send store_content: true, even by a key with no other scopes.

They apply to POST /v1/sessions, WS /v1/stream and POST /v1/transcriptions. A refusal is 403 over HTTP. On WS /v1/stream it is an error event with code: "forbidden" followed by close 4400, because the mode and speaker count arrive in the first message, after the connection opens.

401 versus 403 #

text
401  we do not accept this credential      missing, wrong or expired
403  we accept it but it may not do this   valid, but outside its scopes

Expiry and revocation #

A key may carry an expiry, checked on every request; once it passes, the key is 401. Revocation is not instant: a revoked key stops working once the service's verification cache and storage catch up, not at the moment you revoke it.

Browser credentials #

A browser cannot set an Authorization header on a WebSocket, so /v1/stream also accepts the key in the Sec-WebSocket-Protocol header, as bearer.<token> next to dicon.v1:

javascript
const socket = new WebSocket(url, ["dicon.v1", `bearer.${token}`]);

If both forms are present, the Authorization header wins. The server selects dicon.v1 and never echoes the credential back. This keeps the key out of URLs and access logs, but a proxy that logs full request headers will still capture it.

A rejected key on a WebSocket upgrade gets a real HTTP response, 401, and the connection never opens.