Skip to content

Authentication

Every call carries an API key in the Authorization header, as a bearer token.

Authorization: Bearer utt_live_8f3Kq2Vd0pLzR7nWx4YsBc1TmJhE6uAo

The same header is used on the WebSocket handshake. Nothing else authenticates a request: there is no query string key parameter and no cookie.

utt_live_<32 url-safe characters>
utt_test_<32 url-safe characters>
Prefix Use
utt_live_ production traffic, metered and debited from your credit balance
utt_test_ development and CI

When you create a key in the console, the plaintext appears exactly once, at creation. It is not recoverable afterwards. What the platform stores is a SHA-256 hash of the key, which is enough to verify an incoming key and not enough to reconstruct one. If you lose a key, create a new one and revoke the old one.

Store the value in a secret manager or an environment variable. Never ship it in a browser bundle, a mobile app binary, or a public repository. A browser that needs to stream should get a short lived connection from your own server rather than holding a utt_live_ key. See Streaming from a browser for the shape of that.

  1. Create a second key in the console.
  2. Deploy it, so both keys are valid while the rollout finishes.
  3. Confirm traffic has moved, using the per key usage view in the console.
  4. Revoke the old key.

Revoking is immediate. Requests presenting a revoked key fail with 401:

{
"error": {
"code": "invalid_api_key",
"message": "This API key is not valid or has been revoked.",
"request_id": "req_01JD4Z2Q8W6M"
}
}

A missing or malformed Authorization header also returns 401. See Errors for the full list.

GET /v1/tiers is authenticated, cheap and not metered, so it is a good probe:

Terminal window
curl https://api.utter.cc/v1/tiers \
-H "Authorization: Bearer $UTTER_API_KEY"