Cosmo Realtime SDK
Auth

API keys

Creating, rotating, and securing Cosmo Realtime API keys.

API keys

API keys authenticate external SDK requests to the Cosmo Realtime API. Each key carries one or more scopes that determine which endpoints it can access.


Creating a key

  1. Open the Cosmo web app.
  2. Navigate to Developer platform → API keys (/<workspace>/developer/api-keys).
  3. Click New API key.
  4. Give the key a descriptive name (e.g. voice-app-production).
  5. Select the realtime:use scope. This is the only scope required for realtime sessions.
  6. Click Create.
  7. Copy the key immediately — it is shown only once.
cosmo_...

Keys begin with cosmo_. Store the value in a secret manager or environment variable — never in source code.


Using a key

Pass the key as a Bearer token on the Authorization header:

Authorization: Bearer cosmo_...

In the TypeScript SDK:

const client = new RealtimeClient({
  baseUrl: 'https://app.askcosmo.ai',
  apiKey: process.env.COSMO_API_KEY,
});

In the Python SDK:

client = CosmoRealtime(api_key=os.environ["COSMO_API_KEY"])

In the Swift SDK the credential is passed to RealtimeSession.start, not to a long-lived client object:

let session = try await RealtimeSession.start(
    .init(
        apiKey: ProcessInfo.processInfo.environment["COSMO_API_KEY"]!,
        baseURL: URL(string: "https://app.askcosmo.ai")!
    )
)

An API key is workspace-scoped and server-side only. For browsers and distributed apps, mint a short-lived per-user token on your backend with mintToken(externalUserId:) and pass that instead — token in TypeScript, .token(jwt) in Swift.


Verifying a key

GET /api/v1/external/realtime/verify checks a credential without starting a session — no room, no agent, no charge. Use it as a startup check, after a rotation, or as a CI smoke test.

const info = await client.verify();

info.workspace?.slug;         // which workspace — confirms you hit the environment you meant
info.scopes;                  // ['realtime:use']
info.canStartSessions;        // false -> valid key, missing realtime:use
info.realtimeVoiceAvailable;  // false -> no default voice stack configured here
info = await client.verify()
info.workspace, info.scopes, info.can_start_sessions, info.realtime_voice_available
let info = try await RealtimeClient(options).verify()
info.workspace?.slug, info.scopes, info.canStartSessions, info.realtimeVoiceAvailable

A rejected credential raises (RealtimeVerifyError / VerifyError); a valid but under-scoped one does not — that is a field on the result, so the two are never confused.

Minted end-user tokens can call it too. They report the external_user_id they are bound to, and workspace comes back null: a token runs on someone else's device, so it is told what it may do without being told whose workspace it belongs to.


Rotating a key

  1. Create a new key in the dashboard with the same scopes.
  2. Update your deployment to use the new key (environment variable or secret manager).
  3. Verify the new key is working.
  4. Revoke the old key in the dashboard.

The session-start endpoint returns a short-lived LiveKit room token. Revoking an API key invalidates future session-start calls but does not terminate active in-flight sessions.


Security practices

  • Never commit API keys to source control. Use environment variables or a secrets manager.
  • Restrict scope to what you need. The realtime:use scope is sufficient for realtime sessions.
  • Rotate keys on team member departure or suspected exposure.
  • Use separate keys per environment. Keep production and staging keys independent.

On this page