Skip to content

Authentication

The API uses two different kinds of credentials, scoped very differently on purpose.

Secret keyParticipant token
Formatsk_...participant_token returned by POST /v1/sessions
Lives inYour server onlyYour client (browser / mobile / desktop)
ScopeFull account accessOne LiveKit room, until expiry
Used forEvery REST call (Authorization: Bearer sk_...)Joining the session’s LiveKit room
Can create sessions?YesNo
Can spend money?YesNo

Your secret key authenticates every REST call:

Terminal window
curl https://api.2wai.ai/v1/sessions \
-H "Authorization: Bearer sk_live_..."

Keys come in two prefixes:

  • sk_test_... — test mode. Canned responses on some endpoints; useful for integration tests without burning real pipeline minutes.
  • sk_live_... — real pipeline runs, metered against your account.

Keys are issued when your account is provisioned. See 2wai.ai/developers for the current enrollment + key-issuance flow. Rotating or revoking a key today is a contact-your-account-rep operation; self-serve rotation lives on the developer portal roadmap.

Participant tokens (the mint-proxy pattern)

Section titled “Participant tokens (the mint-proxy pattern)”

A participant_token is minted per-session by POST /v1/sessions and is only useful for joining that one session’s LiveKit room. It can’t call any REST endpoint. That’s what makes it safe to hand to a client:

{
"session_id": "ses_4e1f9a2b8c3d",
"transport": "livekit",
"livekit_url": "wss://2wai.livekit.cloud",
"participant_token": "eyJhbGciOi...",
"room_name": "ses_4e1f9a2b8c3d",
"agent_identity": "livealman-agent-xyz"
}

Your client passes livekit_url + participant_token to the LiveKit client SDK to join the room. From there the agent appears as another participant and streams its video + audio tracks.

The pattern is called a “mint proxy.” Your server exchanges your sk_ for a participant_token and hands only the token to the client. Every 2wai SDK (Flutter, Web/TypeScript, iOS native) expects a mint-proxy URL as its primary credential — pass the URL, the SDK calls it on connect + reconnect. See Streaming into your app for the shape.

Participant tokens expire (default: a few minutes beyond the session lifetime). The LiveKit SDKs handle reconnect; your mint proxy is called again on reconnect to issue a fresh token.

  1. Client asks your backend (your own API, not a 2wai endpoint) for a session.
  2. Your backend calls POST /v1/sessions with Authorization: Bearer sk_....
  3. Your backend returns livekit_url + participant_token + room_name to the client.
  4. Client joins the LiveKit room directly. No further REST calls needed from the client.
  5. Your backend drives the conversation (/speak, /interrupt) using the secret key, in response to whatever your app logic decides.

Next: Concepts for the vocabulary this builds on, or jump to Sessions for the full lifecycle.