---
title: "Create a meeting session"
method: POST
path: "/meeting_sessions"
tags: ["Meeting Sessions"]
---

# Create a meeting session

`POST /meeting_sessions`

Creates a new meeting session. When an idempotency_key is supplied in the request body, replay lookup is scoped to the authenticated account and compares only the key; the request payload is not fingerprinted or compared. If a session with that key already exists for the account, the existing session is replayed (200); otherwise a new session is created (201). Supports bring-your-own-key (BYOK) configuration. The session may enter asynchronous states (e.g. joining, waiting_for_admission) before becoming active. Optional `camera_image` input is write-only and applies only when no Avatar or Assistant webpage output takes precedence. An ignored URL is not fetched. An effective URL source is resolved before bot creation; neither the source URL nor image bytes are persisted, returned, or logged. Treat signed URLs as credentials.

## Request body

- CreateMeetingSessionRequest — Request body for creating a new meeting session. Cross-field rules: - Neither `avatar` nor `assistant` can be combined with `join_at`; both are available only for sessions that join immediately. - `assistant` cannot be combined with `barge_in: true`. - The `avatar` and `assistant` options take effect at session creation and cannot be modified later. - An effective Avatar or Assistant webpage output takes precedence over `camera_image`; the static image is ignored and a URL source is not fetched.
  - `meeting_url` string, uri, required — The meeting URL the bot should join.
  - `bot_name` string — Display name for the bot in the meeting. Defaults to "Meeting Bot".
  - `join_at` string, date-time — ISO-8601 timestamp in the future at which the bot should join. If omitted, the bot joins immediately.
  - `voice` string — Session-default voice identifier used for `speak_on_enter` and ordinary speak actions. A voice supplied on an individual speak action overrides this default for that utterance.
  - `speak_on_enter` string — Text the bot speaks when it enters the meeting. **Not spoken when an `assistant` is attached**: the value is accepted and echoed back on the session, but the assistant owns the voice and the line is never delivered, with no event reporting the omission. Use `chat_on_enter` to announce an assistant-backed bot.
  - `chat_on_enter` string — A message the bot posts to the meeting's chat as soon as it becomes active — typically a recording disclosure. Delivered at most once. Independent of `speak_on_enter`: both may be set, and the chat message posts first because it does not wait for text-to-speech or avatar startup. Rejected with 422 `unsupported_capability` on platforms without meeting chat.
  - `barge_in` boolean — When enabled, a human participant `speech_on` event interrupts and stops the current bot audio; it does not bypass admission or initiate speech. Assistant sessions reject `barge_in: true`.
  - `summarize_on_end` boolean — If true, generate a summary artifact when the session ends.
  - `camera_image` union — Write-only static camera-tile image for this session, not a native account or participant profile photo. Supply exactly one JPEG source. When effective, the image is used as the bot's static camera/video output; presentation varies by meeting platform and recording configuration and is not guaranteed in recordings. An effective Avatar or Assistant webpage output takes precedence, so this input is ignored and a URL source is not fetched.
    - object
      - `format` 'jpeg', required — Only JPEG images are accepted.
      - `base64_data` string, required — Canonical plain RFC 4648 Base64 for a valid decoded JPEG. Data URIs, whitespace, and the URL-safe alphabet are rejected. The encoded value is limited to 1,835,008 characters and the decoded JPEG to 1,363,148 bytes. The JPEG is limited to 4,096 pixels per dimension, 4 megapixels, and 128 MB of decoder memory. The image bytes are not persisted, returned, or logged.
    - object
      - `format` 'jpeg', required — Only JPEG images are accepted.
      - `url` string, uri, required — Public HTTPS JPEG URL with at most 2,048 characters and no credentials, fragment, surrounding whitespace, raw control characters, or explicit non-default port. Signed queries are allowed but must be treated as credentials. Fetching is limited to public network destinations, a five-second timeout, no redirects, a 2xx image/jpeg response with identity or no content encoding, and a 1,363,148-byte limit enforced against both declared and streamed content. The service resolves the URL before bot creation and does not persist, return, or log the URL or image bytes.
  - `webhook_url` string, uri — HTTPS endpoint to receive session lifecycle callbacks. Static validation requires HTTPS, rejects embedded credentials and blocked hosts, and enforces egress policy. Validation makes no network request to the endpoint.
  - `metadata` object — Arbitrary key-value metadata attached to the session. The serialized JSON representation must not exceed 16384 characters at runtime.
  - `idempotency_key` string — Client-supplied idempotency key to safely retry creation requests without duplicating sessions. Lookup is scoped to the authenticated account and compares the key only; the request payload is not fingerprinted or compared.
  - `avatar` MeetingSessionAvatarRequest — Request options for attaching a bring-your-own-key avatar to the session.
    - `provider` 'anam', required — Avatar provider identifier. Currently only "anam" is supported.
    - `avatar_id` string, required — Identifier of the avatar to use.
    - `api_key` string, required — Bring-your-own-key API key for the avatar provider. The key is never stored or returned by the API.
  - `assistant` MeetingSessionAssistantRequest — Attach a Telnyx AI Assistant to the session. Supply the Assistant's ID; the Meeting service connects it to the meeting directly. The Call Control connection, caller ID and loopback SIP URI previously required here have been removed and are now rejected as unknown fields.
    - `id` string, required — Identifier of the assistant to attach.
    - `audio_gate` 'half_duplex' | 'full_duplex' — Audio gating strategy for the assistant call leg. `half_duplex` (default) sends the assistant a single mixed meeting stream and mutes it while the assistant speaks, so the assistant cannot hear itself and cannot be interrupted. `full_duplex` sends a separate stream per participant, which allows barge-in and removes self-hearing, and COSTS SIGNIFICANTLY MORE: per-participant streams multiply the per-minute cost by the number of participants.
    - `dynamic_variables` object — Per-conversation values for the [dynamic variables](/docs/inference/ai-assistants/dynamic-variables) used in the Assistant's instructions, greeting, or tools. Delivered before the Assistant's first utterance, so they resolve for the opening line as well as the rest of the conversation. At most 63 entries; keys 1-128 characters; values must be strings. The map is budgeted in aggregate at 1,047,552 bytes (1023 KiB) rather than capped per value. `streaming_audio`, `ai_assistant_streaming_audio` and `meeting_session_id` are reserved and rejected with `400 invalid_request` -- they toggle provider infrastructure or are set by the service rather than fill a prompt template.
    - `leave_on_end` boolean — Leave the meeting when the Assistant's conversation reaches a terminal state -- `ended` **or** `failed`. Off by default, which leaves the bot in the meeting after the Assistant stops. Fires once: a second terminal transition does not leave twice, and a leave the provider refuses is logged without changing how the session settles.

## Response `200`

Replayed existing meeting session matching the account-scoped idempotency_key. Replay is key-only; the request payload is not fingerprinted or compared.

- MeetingSessionResponse
  - `data` MeetingSession, required — Represents a meeting session. All serializer fields are present and required; nullable fields use null when absent. No actor, provider-bot, idempotency, routing, key, or internal fields are exposed.
    - `id` string, required — Unique identifier for the meeting session.
    - `account_id` string, required — Identifier of the owning account.
    - `provider` string, required — Provider handling the meeting session.
    - `status` 'scheduled' | 'joining' | 'waiting_for_admission' | 'active' | 'leaving' | 'ended' | 'failed' | 'admission_denied', required — Lifecycle status. `waiting_for_admission` means the bot reached the meeting lobby and may require host approval. `active` means the bot entered the meeting/media path. `ended` alone does not prove attendance; use non-null `joined_at` as positive evidence that the session became active. `admission_denied` is reserved for an explicit provider denial, while cancellation or another termination can end a never-admitted session as `ended`.
    - `status_detail` string, nullable, required — Additional human-readable detail about the status, or null.
    - `recording` boolean, required — Whether the session is being recorded.
    - `meeting_url` string, uri, required — The meeting URL the bot joins.
    - `platform` 'zoom' | 'google_meet' | 'teams' | 'webex' | 'unknown', required — Detected meeting platform.
    - `bot_name` string, required — Display name of the bot in the meeting.
    - `config` MeetingSessionConfig, required
      - `voice` string, nullable, required — Configured voice identifier, or null if not set.
      - `speak_on_enter` string, nullable, required — Text spoken on meeting entry, or null if not set.
      - `chat_on_enter` string, nullable, required — The message posted to chat on join, or null when unset.
      - `barge_in` boolean, required — When enabled, a human participant `speech_on` event interrupts and stops the current bot audio; it does not bypass admission or initiate speech. Assistant sessions reject `barge_in: true`.
      - `summarize_on_end` boolean, required — Whether a summary artifact is generated on session end.
    - `avatar` MeetingSessionAvatar, required
      - `provider` 'anam', required — Avatar provider identifier.
      - `avatar_id` string, required — Identifier of the avatar.
    - `avatar_state` 'starting' | 'connected' | 'degraded' | 'disconnected' | 'null', nullable, required — Current state of the avatar connection, or null if no avatar is attached.
    - `avatar_state_changed_at` string, date-time, nullable, required — Timestamp of the last avatar state change, or null.
    - `assistant` MeetingSessionAssistant, required
      - `id` string, required — Identifier of the assistant.
      - `audio_gate` 'half_duplex' | 'full_duplex', required — Audio gating strategy in force for the assistant call leg.
      - `dynamic_variables` object, nullable, required — The dynamic variables in force for this session, or null when none were supplied.
      - `leave_on_end` boolean, required — Whether the bot leaves when the Assistant's conversation ends or fails.
    - `assistant_state` 'starting' | 'connected' | 'failed' | 'ended' | 'null', nullable, required — Current state of the assistant, or null if no assistant is attached.
    - `assistant_state_changed_at` string, date-time, nullable, required — Timestamp of the last assistant state change, or null.
    - `webhook_url` string, uri, nullable, required — Webhook endpoint for session lifecycle callbacks, or null if not configured.
    - `metadata` object, required — Arbitrary key-value metadata attached to the session.
    - `failure_reason` string, nullable, required — Human-readable failure reason if the session failed, or null.
    - `created_at` string, date-time, required — Timestamp when the session was created.
    - `join_at` string, date-time, nullable, required — Scheduled join time, or null for immediate join.
    - `joined_at` string, date-time, nullable, required — Timestamp when the session first became `active`, or null if it never became active. This remains positive admission evidence after terminal transitions.
    - `ended_at` string, date-time, nullable, required — Timestamp when the session ended, or null if ongoing.
    - `updated_at` string, date-time, required — Timestamp of the last update to the session.

## Other responses

- `201` — New meeting session created.
- `400` — Bad Request
- `401` — Unauthorized. On api.telnyx.com, authentication is enforced by the API gateway before the request reaches the Meeting service, so a missing or invalid API key returns the standard Telnyx error envelope (`{"errors": [{"code": "10009", ...}]}`) rather than the single-`error` shape below.
- `403` — The authenticated credential is not permitted to perform this operation.
- `413` — Payload Too Large
- `422` — Unprocessable Entity, including an unsupported capability
- `429` — Authentication is temporarily overloaded. Retry after the number of seconds in `Retry-After`.
- `500` — Internal Server Error
- `502` — The meeting provider rejected bot creation.
- `503` — A required feature or dependency is not configured or authentication is unavailable.

## Changes

> 99 revisions in range; 1 not diffed.

- **2026-09-23** `cdb64ddf086f` — 1 breaking, 5 warning, 13 info
  - removed the enum value `none` of the request property `assistant/audio_gate`
  - removed the request property `assistant/call_control_connection_id`
  - removed the request property `assistant/from`
  - removed the request property `assistant/loopback_sip_uri`
  - …15 more
- **2026-08-17** `1571b0380bd7` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/team-telnyx/apis/telnyx-api-2/changes/meeting_sessions/post.md)

---

[API](https://skmtc.dev/team-telnyx/apis/telnyx-api-2.md) · [All operations](https://skmtc.dev/team-telnyx/apis/telnyx-api-2/llms.txt) · [OpenAPI document](https://skmtc.dev/team-telnyx/apis/telnyx-api-2/revisions/227c33b1ac9c?raw)
