Credential verification
GET /realtime/verify — the REST call that checks a realtime credential without starting a session.
GET /api/v1/external/realtime/verify checks the credential in the Authorization header without starting a session — no room, no agent, no charge. A 200 means the credential authenticated; the fields say what it can do from here. The SDKs call it as client.verify() (TypeScript / Python) and RealtimeClient.verify() (Swift), and cosmo whoami runs the same check against the stored credential.
This is the introspection endpoint for realtime credentials — GET /api/v1/external/whoami is its counterpart for user access tokens.
Schema and try-it: this endpoint in the API explorer.
Authentication
Bearer token in the Authorization header — a workspace API key or a minted end-user JWT. No scope is required: an under-scoped key gets a 200 with can_start_sessions: false rather than a 403 indistinguishable from a bad key. The call is not metered.
Request
GET /api/v1/external/realtime/verify
Authorization: Bearer cosmo_...No path, query, or body parameters — the only input is the credential itself.
Response
200 OK
{
"credential": "api_key",
"workspace": { "name": "Acme Support", "slug": "acme-support" },
"scopes": ["realtime:delete", "realtime:dial", "realtime:logs", "realtime:read", "realtime:start", "realtime:use", "support:write"],
"can_start_sessions": true,
"realtime_voice_available": true,
"external_user_id": null
}| Field | Type | Description |
|---|---|---|
credential | "api_key" | "user_token" | Which of the two realtime credentials the server saw. |
workspace | object | null | { name, slug } for an API key, which the workspace's own developer holds; null for a minted token, which is held by an end user. |
scopes | string[] | Scopes granted to this credential, reported after hierarchy expansion: a credential holding the deprecated realtime:use umbrella lists it alongside the child scopes it implies. See Scopes. |
can_start_sessions | bool | Whether the credential carries realtime:start — the scope a session start needs. false means valid but under-scoped. |
realtime_voice_available | bool | Whether this deployment has the default voice stack configured. A floor, not a per-session guarantee: a session that requests an opt-in provider is checked against that provider instead, so a start can still return 503 when this is true. |
external_user_id | string | null | The end user a minted token is bound to; null for an API key. |
Errors
| Status | Cause |
|---|---|
| 401 | Missing, invalid, expired, or revoked bearer credential. |
| 401 | The credential's workspace is not served on this host — "No access to workspace '<id>' from this host". A workspace credential works only against the Cosmo host its workspace was created on. |
| 403 | An acts-as-user token was presented; those are not realtime credentials — use an API key or a minted session token. |
Error bodies use the standard envelope — see POST /session/start for its shape.
Example — curl
curl https://platform.askcosmo.ai/api/v1/external/realtime/verify \
-H "Authorization: Bearer cosmo_..."