Atmee.aiDocs
APIAPI referenceSpeech sessions

Start a speech-to-speech session (audio only, no video)

POST
/v1/speech_sessions

Reserves a speech session with an avatar: a realtime speech-to-speech conversation over a WebSocket, without video. The answer carries the WebSocket url and a short-lived token: connect to url within 60 seconds (tokenExpiresAt), presenting the token either as Authorization: Bearer <token> or as the WebSocket subprotocols atmee-live and atmee-token.<token>. The token only admits the connection. The session ends at its endsAt (the reservation plus actualDurationSeconds), whenever the connection opened. The first connection holds the session for good: no other connection can use it, so a client that lost its connection starts a new session.

avatarId is required: the conversation uses that avatar's persona (name, personality, facts, self-introduction) and always its voice; an avatar without a voice answers 422 avatar_has_no_voice.

settings pins session.start fields from your backend: the speech server applies them over the client's, refuses a client session.start / session.update that sets a pinned field (naming it), and leaves them out of the session it echoes. Unpinned fields stay the client's to set. Pinned persona fields override the avatar's. Appends (session.instructions.append and the like) stay allowed: they add to the pinned instructions, never replace them.

Billing runs by the minute from the speech server's first usage report (within 30 s of the connection) until the session ends, at the plan's speech rate. A session nobody connects to costs nothing and is closed (failed, no_user_joined) by the first read, or start of the account, 30 seconds after its token expired, otherwise by the stale-session cleanup: 120 seconds without a heartbeat (the reservation sets the first), checked every minute.

Who pays. Always the account that owns the avatar:

  • API key (X-Api-Key) — your backend, billed to the key's account. Requires the sessions scope; an avatar-scoped key may only start sessions on its avatar (it must name it).
  • The owner's login (Authorization: Bearer <jwt>, where the deployment accepts user tokens) — billed to the account the user acts for (X-Account-Id when there are several). An avatar of another account answers 403 avatar_not_allowed.
  • No credential — 401. There is no anonymous or visitor-paid speech session.

With both an API key and a bearer token, the key's start applies, as on POST /v1/sessions. Read and end a session with either credential of its account.

Authorization

headerX-Api-Key<token>

Secret embed API key (sk_atmee_...; keys minted before 2026-09 carry sk_live_...), held by the customer's own backend and never sent to a browser. Format: X-Api-Key: sk_atmee_....

Request Body

application/json
  1. body
avatarId*string

An avatar of this account, with a voice, whose persona and voice the session uses (an avatar-scoped key's own avatar).

Formatuuid
maxDurationSeconds?integer

The session's length in seconds (default 600), counted from the reservation (this call), whenever the connection opens. Shortened when the balance or the plan allows less; the answer says what was granted (actualDurationSeconds).

Range60 <= value <= 3600
language?string

BCP 47 language of the conversation (e.g. en, fr-FR); passed to the speech server as given.

Match^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$
Length2 <= length <= 35
settings?

session.start fields pinned by your backend: the client cannot set them (see the operation).

Response Body

The session is reserved; connect to url with token.

application/json
  1. response
links?

Absent when this deployment does not know the website's address.

sessionId*string
Formatuuid
url*string

The WebSocket URL to connect to (wss://...).

token*string

Admits one connection to this session; valid for 60 seconds. Not a credential for anything else.

tokenExpiresAt*string
Formatdate-time
actualDurationSeconds*integer

The length granted by the key's, the plan's and the balance's limits, counted from the reservation (this call), whenever the connection opens; the session ends at the reservation plus this many seconds (endsAt on GET).

requestedDurationSeconds?integer

The maxDurationSeconds you sent; omitted when you sent none.

durationCapped*boolean

True when actualDurationSeconds is shorter than requestedDurationSeconds.

billingMode*string
Value in"reserve""metered"
Example Request
curl -X POST 'https://api.atmanity.us/v1/speech_sessions' \  -H 'Content-Type: application/json' \  -d '{  "avatarId": "ac572b6e-802b-4b9e-a602-0786d4441e67"}'
Example Response
{  "links": {    "chat": "http://example.com"  },  "sessionId": "f6567dd8-e069-418e-8893-7d22fcf12459",  "url": "string",  "token": "string",  "tokenExpiresAt": "2019-08-24T14:15:22Z",  "actualDurationSeconds": 0,  "requestedDurationSeconds": 0,  "durationCapped": true,  "billingMode": "reserve"}
Start a speech-to-speech session (audio only, no video) — Atmee Docs