> ## Documentation Index
> Fetch the complete documentation index at: https://developer.kallglot.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Session

> Create a new real-time voice session

Create a new session to start real-time voice processing. The session establishes a WebSocket connection for streaming audio and receiving transcripts/translations.

<Warning>
  **Do not send a top-level `provider` object on create.** Specify telephony with **`routing`** only (for example `routing.phone_number` or `routing.connection_id`). A top-level **`provider`** string on the **response** indicates the resolved carrier (`twilio`, `telnyx`, `sip`, etc.) and must not be confused with request fields.
</Warning>

## Request Body

<ParamField body="mode" type="string" required>
  The session mode:

  * `bidirectional_translation` - Both parties hear translated speech
  * `assistive_translation` - Agent hears original, customer hears translation
  * `ai_agent` - AI-powered voice agent handles the conversation
  * `help_chat_voice` - Voice-enabled help desk assistant
</ParamField>

<ParamField body="source_language" type="string">
  Language code for Party A (e.g., `en`, `es`, `de`). Optional - if omitted, language is auto-detected.
</ParamField>

<ParamField body="target_language" type="string">
  Language code for Party B (e.g., `en`, `es`, `de`). Optional - if omitted, language is auto-detected.
</ParamField>

<ParamField body="routing" type="object">
  Telephony routing. Omit to use your organization's default route.

  Exactly **one** routing method should be supplied (phone number, SIP, connection, or inherited default).

  <Expandable title="routing options">
    <ParamField body="phone_number" type="string">
      Kallglot-managed phone number in E.164 format (e.g., `+14155551234`). Implies phone-number routing.
    </ParamField>

    <ParamField body="connection_id" type="string">
      External provider connection (`pcon_...`). See [Choose your telephony integration](/guides/choose-telephony-integration) (external connections).
    </ParamField>

    <ParamField body="type" type="string">
      Set to `sip` for SIP trunk calls (see [SIP Integration](/guides/sip)). For managed numbers or `connection_id`, omit `type` and use `phone_number` or `connection_id` alone.
    </ParamField>

    <ParamField body="sip" type="object">
      Optional SIP payload when `type` is `sip`. Example: `{ "sip": { "from_uri": "sip:alice@example.com" } }`.

      <Expandable title="sip properties">
        <ParamField body="from_uri" type="string">SIP From URI when known at creation time.</ParamField>
        <ParamField body="to_uri" type="string">SIP To URI when known.</ParamField>

        <ParamField body="headers" type="object">
          Map of arbitrary SIP `X-` headers attached to the dialog.
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="direction" type="string">
      Optional call direction hint: `inbound` or `outbound`.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="audio" type="object">
  Optional audio transport hints (encoding, sample rate, channels). Omit unless your telephony path needs non-default values.

  <Expandable title="audio properties">
    <ParamField body="sample_rate_hz" type="integer">Sample rate in Hz (default `8000`).</ParamField>
    <ParamField body="encoding" type="string">Encoding hint such as `mulaw` (default).</ParamField>
    <ParamField body="channels" type="integer">Audio channels (default `1`).</ParamField>
  </Expandable>
</ParamField>

<ParamField body="voice" type="object">
  Voice synthesis hints for translated audio.

  <Expandable title="voice properties">
    <ParamField body="voice_id" type="string">Kallglot voice identifier.</ParamField>
    <ParamField body="stability" type="number">TTS stability (`0`–`1`, default `0.5`).</ParamField>
    <ParamField body="similarity_boost" type="number">Similarity boost (`0`–`1`, default `0.75`).</ParamField>
    <ParamField body="speed" type="number">Playback speed multiplier (`0.5`–`2`, default `1`).</ParamField>
  </Expandable>
</ParamField>

<ParamField body="recording" type="object">
  <Expandable title="recording options">
    <ParamField body="enabled" type="boolean" default={false}>
      Enable call recording.
    </ParamField>

    <ParamField body="mode" type="string">
      Recording mix mode (default `dual_channel`).
    </ParamField>

    <ParamField body="consent_required" type="boolean">
      When `true`, recording downloads require a granted consent state.
    </ParamField>

    <ParamField body="consent_status" type="string">
      Current consent state such as `granted`, `denied`, or `not_required`.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="ai_agent" type="object">
  **Only for `ai_agent` mode.** Omit for translation modes.

  <Expandable title="ai_agent options">
    <ParamField body="id" type="string" required>
      Agent id from `GET /v1/agents` (for example `agt_01HXYZ`). Configure prompts and tools via the Agents API—sessions only **reference** an agent.
    </ParamField>

    <ParamField body="overrides" type="object">
      Optional per-session overrides allowed by your organization policy.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="metadata" type="object">
  Custom key-value pairs to attach to the session (e.g., `{"customer_id": "123"}`).
</ParamField>

## Response

<ResponseField name="id" type="string">
  Session identifier (e.g., `sess_01HXYZ123456789`).
</ResponseField>

<ResponseField name="object" type="string">
  Always `session`.
</ResponseField>

<ResponseField name="status" type="string">
  `created`, `active`, or `ended`.
</ResponseField>

<ResponseField name="mode" type="string">
  The session mode.
</ResponseField>

<ResponseField name="configuration_mode" type="string">
  Echoed field on the session object. You do not need to set or interpret it for a standard integration.
</ResponseField>

<ResponseField name="source_language" type="string">
  Resolved source language. `null` if using auto-detection.
</ResponseField>

<ResponseField name="target_language" type="string">
  Resolved target language. `null` if using auto-detection.
</ResponseField>

<ResponseField name="stream" type="object">
  WebSocket connection details.

  <Expandable title="stream properties">
    <ResponseField name="url" type="string">
      WebSocket URL for real-time streaming.
    </ResponseField>

    <ResponseField name="token" type="string">
      Authentication token for the WebSocket.
    </ResponseField>

    <ResponseField name="expires_at" type="string">
      Token expiration (ISO 8601).
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="provider" type="string">
  **Response only** — resolved telephony carrier: `twilio`, `telnyx`, `sip`, or `webrtc` when applicable. This is not a request field; select routes with **`routing`** on create.
</ResponseField>

<ResponseField name="phone_number" type="string">
  Phone number for this session (if applicable).
</ResponseField>

<ResponseField name="call" type="object">
  Optional linked telephony reference when present (`id`, `object`, `provider`, and provider-specific identifiers such as carrier call IDs).
</ResponseField>

<ResponseField name="recording" type="object">
  <Expandable title="recording properties">
    <ResponseField name="enabled" type="boolean">
      Whether recording is enabled.
    </ResponseField>

    <ResponseField name="mode" type="string">
      Recording mix mode.
    </ResponseField>

    <ResponseField name="consent_required" type="boolean">
      Whether explicit consent is required before playback.
    </ResponseField>

    <ResponseField name="consent_status" type="string">
      Resolved consent flag.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="metadata" type="object">
  Custom metadata attached to the session.
</ResponseField>

<ResponseField name="created_at" type="string">
  Creation timestamp (ISO 8601).
</ResponseField>

<Note>
  **Samples below:** The minimal cURL uses **default org routing** (no `routing` in the body). The second cURL adds **`routing.phone_number`** to match [Quick Start](/quickstart). For production, send **`Idempotency-Key`** on every create (see [Idempotency](/concepts/idempotency)).
</Note>

<RequestExample>
  ```bash cURL (auto-detect) theme={null}
  curl -X POST https://api.kallglot.com/v1/sessions \
    -H "Authorization: Bearer sk_live_your_api_key" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: $(uuidgen)" \
    -d '{"mode": "bidirectional_translation"}'
  ```

  ```bash cURL (explicit languages + managed number) theme={null}
  curl -X POST https://api.kallglot.com/v1/sessions \
    -H "Authorization: Bearer sk_live_your_api_key" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: $(uuidgen)" \
    -d '{
      "mode": "bidirectional_translation",
      "source_language": "de",
      "target_language": "en",
      "routing": {
        "phone_number": "+14155551234"
      }
    }'
  ```

  ```python Python theme={null}
  import os
  import uuid
  import requests

  API_KEY = os.environ.get('KALLGLOT_API_KEY')

  response = requests.post(
      'https://api.kallglot.com/v1/sessions',
      headers={
          'Authorization': f'Bearer {API_KEY}',
          'Content-Type': 'application/json',
          'Idempotency-Key': str(uuid.uuid4())
      },
      json={
          'mode': 'bidirectional_translation',
          # Languages optional - omit for auto-detection
          'source_language': 'de',
          'target_language': 'en'
      }
  )

  if response.status_code == 201:
      session = response.json()
      print(f"Session ID: {session['id']}")
      print(f"WebSocket URL: {session['stream']['url']}")
      print(f"Token: {session['stream']['token']}")
  else:
      error = response.json()
      print(f"Error: {error['error']['message']}")
  ```

  ```javascript JavaScript theme={null}
  const API_KEY = process.env.KALLGLOT_API_KEY;

  const response = await fetch('https://api.kallglot.com/v1/sessions', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
      'Idempotency-Key': crypto.randomUUID()
    },
    body: JSON.stringify({
      mode: 'bidirectional_translation',
      // Languages optional - omit for auto-detection
      source_language: 'de',
      target_language: 'en'
    })
  });

  const data = await response.json();

  if (response.ok) {
    console.log('Session ID:', data.id);
    console.log('WebSocket URL:', data.stream.url);
    console.log('Token:', data.stream.token);
  } else {
    console.error('Error:', data.error.message);
  }
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'json'
  require 'securerandom'

  uri = URI('https://api.kallglot.com/v1/sessions')
  request = Net::HTTP::Post.new(uri)
  request['Authorization'] = "Bearer #{ENV['KALLGLOT_API_KEY']}"
  request['Content-Type'] = 'application/json'
  request['Idempotency-Key'] = SecureRandom.uuid
  request.body = {
    mode: 'bidirectional_translation',
    source_language: 'de',
    target_language: 'en'
  }.to_json

  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(request) }
  session = JSON.parse(response.body)
  puts session['stream']['url']
  ```

  ```go Go theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "net/http"
      "os"

      "github.com/google/uuid"
  )

  func main() {
      payload := map[string]string{
          "mode": "bidirectional_translation",
          // Languages optional - omit for auto-detection
          "source_language": "de",
          "target_language": "en",
      }
      body, _ := json.Marshal(payload)

      req, _ := http.NewRequest("POST", "https://api.kallglot.com/v1/sessions", bytes.NewBuffer(body))
      req.Header.Set("Authorization", "Bearer "+os.Getenv("KALLGLOT_API_KEY"))
      req.Header.Set("Content-Type", "application/json")
      req.Header.Set("Idempotency-Key", uuid.NewString())

      resp, err := http.DefaultClient.Do(req)
      if err != nil {
          fmt.Printf("Request failed: %v\n", err)
          return
      }
      defer resp.Body.Close()

      var result map[string]any
      json.NewDecoder(resp.Body).Decode(&result)

      if resp.StatusCode == 201 {
          stream := result["stream"].(map[string]any)
          fmt.Printf("Session ID: %s\n", result["id"])
          fmt.Printf("WebSocket URL: %s\n", stream["url"])
      } else {
          errObj := result["error"].(map[string]any)
          fmt.Printf("Error: %s\n", errObj["message"])
      }
  }
  ```
</RequestExample>

<ResponseExample>
  ```json 201 Auto-detect theme={null}
  {
    "id": "sess_01HXYZ123456789",
    "object": "session",
    "status": "created",
    "mode": "bidirectional_translation",
    "provider": "twilio",
    "phone_number": "+14155551234",
    "source_language": null,
    "target_language": null,
    "stream": {
      "url": "wss://api.kallglot.com/v1/sessions/sess_01HXYZ123456789/connect",
      "token": "kst_live_xxxxxxxxxxxxxxxx",
      "expires_at": "2026-03-26T12:00:00Z"
    },
    "recording": {
      "enabled": false
    },
    "metadata": null,
    "created_at": "2026-03-26T11:00:00Z"
  }
  ```

  ```json 201 Explicit languages theme={null}
  {
    "id": "sess_01HXYZ123456789",
    "object": "session",
    "status": "created",
    "mode": "bidirectional_translation",
    "provider": "twilio",
    "phone_number": "+14155551234",
    "source_language": "de",
    "target_language": "en",
    "stream": {
      "url": "wss://api.kallglot.com/v1/sessions/sess_01HXYZ123456789/connect",
      "token": "kst_live_xxxxxxxxxxxxxxxx",
      "expires_at": "2026-03-26T12:00:00Z"
    },
    "recording": {
      "enabled": false
    },
    "metadata": null,
    "created_at": "2026-03-26T11:00:00Z"
  }
  ```

  ```json 401 Unauthorized theme={null}
  {
    "error": {
      "code": "api_key_invalid",
      "message": "Invalid API key",
      "type": "authentication_error"
    }
  }
  ```

  ```json 402 Payment Required theme={null}
  {
    "error": {
      "code": "insufficient_api_credits",
      "message": "API credits exhausted. Purchase more credits to continue.",
      "type": "payment_error"
    }
  }
  ```

  ```json 422 Validation Error theme={null}
  {
    "error": {
      "code": "invalid_request",
      "message": "source_language must be a valid ISO 639-1 code",
      "type": "validation_error",
      "param": "source_language"
    }
  }
  ```
</ResponseExample>
