Browser Sessions
POST /v1/browser-sessions
Called by the SDK for browser embeds when you
pass experienceId. Auth is the page Origin against your allowlist —
not an API key in the browser.
Request
POST https://api.liforma.ai/v1/browser-sessions
Origin: https://your-app.com
Idempotency-Key: optional-unique-key
Content-Type: application/json
{
"experienceId": "exp_t0i7acmq",
"locale": "en-GB",
"secondaryLocale": "fr-FR",
"mode": "conversation",
"speechInputMode": "auto",
"speechOnly": false
}Response 201
SessionLaunchResponse:
session plus opaque launch. Header:
Cache-Control: no-store, private. Dual sessions also echo
session.secondaryLocale when resolved.
Parameters
| Field | Required | Description |
|---|---|---|
experienceId | Yes | Experience to launch |
locale | No | Primary / user language (BCP 47). SDK defaults to
|
secondaryLocale | No* | Dual: paired / learning language (BCP 47). Required when the creator left the paired
axis as Match; ignored when Fixed. Non-dual: when conversation is Match, immerses the
session in this language (wins over browser/ |
learningLocale | No | Alias of |
mode | No | conversation or presenter |
speechInputMode | No | auto, manual, or off |
runtimeContext | No | Session JSON for |
speechOnly | No | When true, voice-only session without avatar/location assets |
- Language-learning apps can pass the same
learningLocale(orsecondaryLocale) for tutors and roleplay. Dual tutors use it as the learning axis (clip / v2a pipeline); non-dual roleplay immerses conversation and voice in that language when Studio left Match open (plain / v2b). Creator Fixed still wins.
Player chrome (startButton, closeButton, returnUrl,
fit) is configured via SDK attach / component props — not on this
request.
Checks
Originheader required- Browser embeds must be enabled for the project
- Origin must be on the project allowlist
- Experience must have a published revision
- Quota and rate limits apply
CORS
api.liforma.ai returns CORS headers for the requesting Origin, including
Idempotency-Key on preflight. CORS is not authorization — Origin allowlisting
happens on the POST. The SDK calls this endpoint directly from the browser.
Optional Idempotency-Key (max 256 characters; longer values →
400 IDEMPOTENCY_KEY_INVALID): same key + same body replays the prior launch; same
key + different body → 409 IDEMPOTENCY_CONFLICT; same key still pending →
409 IDEMPOTENCY_IN_PROGRESS with Retry-After: 1. Branch on
error.code, not HTTP 409 alone.
Machine-readable contract:
/openapi/sessions.json.
Example
curl -X POST https://api.liforma.ai/v1/browser-sessions \
-H "Origin: https://your-app.com" \
-H "Content-Type: application/json" \
-d '{"experienceId": "exp_t0i7acmq"}'