Every request carries an API key. Browsers never see the key: they get a single-use ticket from your server instead.

API keys

Create a key in the console under Developer → API keys. The full secret is shown once, so store it right away. If you lose it, create a new key and archive the old one. Send the key as a bearer token:
X-API-Key: sk-eesi-... works too, for clients that use Authorization for something else. A key belongs to your organization. It can reach everything your organization owns and nothing else. Creating keys and anything that spends money need a person signed in to the console, so a leaked key cannot mint a replacement or buy credits.

Good habits

  • Use one key per environment, so revoking one leaves the others working.
  • Keep keys on servers. Never put one in frontend code, a mobile app bundle or a repository.
  • Rotate by creating a new key, deploying it, then archiving the old one. Both work during the switch, and the old one stops the moment you archive it.

Browsers and mobile apps

A browser cannot keep a secret, so it connects with something your server gives it.

WebSocket: a ticket

Your server mints a ticket with its key, and the browser opens the socket with it. A ticket starts with rt_, works once, and expires after 30 seconds, so mint one per connection.

WebRTC: relay the offer

The browser creates its WebRTC offer and posts it to your server, which forwards it to POST /v1/realtime/calls with the key and returns the answer. Nur has the full example.

Errors

Errors use the OpenAI error envelope:
On a WebSocket the same refusals close the socket with code 1008 and the reason.