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

# SIP transfer

> Initiates a SIP REFER transfer for a participant in a LiveKit room.
The transfer moves an ongoing SIP call to a different phone number.

# Arguments
* `state` - Shared application state containing LiveKit handlers
* `auth` - Authentication context for room metadata authorization
* `request` - Transfer request with room name, participant identity, and destination

# Returns
* `Response` - JSON response with transfer status or error

# Errors
* 400 Bad Request - Invalid phone number format or empty fields
* 404 Not Found - Room not found, not accessible, or participant not found
* 500 Internal Server Error - LiveKit not configured or transfer operation failed

# Flow
1. Validate the phone number format
2. Check LiveKit handlers are configured
3. Check room access via metadata auth_id
4. Verify the participant exists and is a SIP participant
5. Execute the SIP transfer
6. Return success or appropriate error

Initiates a SIP REFER transfer for a participant in a LiveKit room. The transfer moves an ongoing SIP call to a different phone number.

## Authorization

Access is controlled via room metadata:

| Mode                               | Behavior                                      |
| ---------------------------------- | --------------------------------------------- |
| Authenticated (`auth.id` present)  | Requires `room.metadata.auth_id == auth.id`.  |
| Unauthenticated (`auth.id` absent) | Access is allowed (backward-compatible mode). |

<Note>
  Room names are used exactly as provided. No prefixing or modification is applied.
</Note>

## Request

Requires:

* `room_name` - The LiveKit room where the SIP participant is connected
* `participant_identity` - The identity of the SIP participant to transfer
* `transfer_to` - The destination phone number

Phone numbers support international format (`+1234567890`), national format (`07123456789`), or internal extensions (`1234`).

## Response

Returns `status` of `initiated` once the transfer request is accepted. A successful response indicates the transfer has been initiated, not that it has completed.

## Error responses

| Status                      | Condition                                                                      |
| --------------------------- | ------------------------------------------------------------------------------ |
| `400 Bad Request`           | Invalid phone number format or empty required fields.                          |
| `404 Not Found`             | Room not found, access denied, or participant not found/not a SIP participant. |
| `500 Internal Server Error` | LiveKit not configured or transfer operation failed.                           |

<Tip>
  Only SIP participants can be transferred. Use `GET /livekit/rooms/{room_name}` to check if a participant has `kind: "SIP"` before attempting a transfer.
</Tip>


## OpenAPI

````yaml POST /sip/transfer
openapi: 3.1.0
info:
  title: Sayna API
  description: >-
    Real-time voice processing server with Speech-to-Text (STT) and
    Text-to-Speech (TTS) services
  contact:
    name: Sayna
    url: https://api.sayna.ai
  license:
    name: Apache-2.0
    identifier: Apache-2.0
  version: 0.1.0
servers:
  - url: https://api.sayna.ai
    description: Production API
  - url: http://localhost:3001
    description: Local development
security: []
tags:
  - name: health
    description: Health check endpoints
  - name: voices
    description: TTS voice management
  - name: tts
    description: Text-to-speech synthesis
  - name: livekit
    description: LiveKit room and token management
  - name: recordings
    description: Recording download operations
  - name: sip
    description: SIP webhook configuration management
  - name: websocket
    description: WebSocket API for real-time communication
paths:
  /sip/transfer:
    post:
      tags:
        - sip
      summary: Handler for POST /sip/transfer endpoint
      description: >-
        Initiates a SIP REFER transfer for a participant in a LiveKit room.

        The transfer moves an ongoing SIP call to a different phone number.


        # Arguments

        * `state` - Shared application state containing LiveKit handlers

        * `auth` - Authentication context for room metadata authorization

        * `request` - Transfer request with room name, participant identity, and
        destination


        # Returns

        * `Response` - JSON response with transfer status or error


        # Errors

        * 400 Bad Request - Invalid phone number format or empty fields

        * 404 Not Found - Room not found, not accessible, or participant not
        found

        * 500 Internal Server Error - LiveKit not configured or transfer
        operation failed


        # Flow

        1. Validate the phone number format

        2. Check LiveKit handlers are configured

        3. Check room access via metadata auth_id

        4. Verify the participant exists and is a SIP participant

        5. Execute the SIP transfer

        6. Return success or appropriate error
      operationId: sip_transfer
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SIPTransferRequest'
        required: true
      responses:
        '200':
          description: Transfer initiated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SIPTransferResponse'
        '400':
          description: Invalid request (bad phone number or empty fields)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SIPTransferErrorResponse'
        '404':
          description: Room not found, not accessible, or participant not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SIPTransferErrorResponse'
        '500':
          description: LiveKit not configured or transfer failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SIPTransferErrorResponse'
      security:
        - auth: []
components:
  schemas:
    SIPTransferRequest:
      type: object
      description: |-
        Request body for initiating a SIP call transfer

        # Example
        ```json
        {
          "room_name": "call-room-123",
          "participant_identity": "sip_participant_456",
          "transfer_to": "+15551234567"
        }
        ```
      required:
        - room_name
        - participant_identity
        - transfer_to
      properties:
        participant_identity:
          type: string
          description: >-
            The identity of the SIP participant to transfer.

            This can be obtained by listing participants in the room via LiveKit
            API.
          example: sip_participant_456
        room_name:
          type: string
          description: The LiveKit room name where the SIP participant is connected
          example: call-room-123
        transfer_to:
          type: string
          description: >-
            The phone number to transfer the call to.

            Supports international format (+1234567890), national format
            (07123456789),

            or internal extensions (1234).
          example: '+15551234567'
    SIPTransferResponse:
      type: object
      description: |-
        Response for a successful SIP transfer initiation

        Note: A successful response indicates the transfer has been initiated,
        not that it has completed. The actual transfer may take several seconds.

        # Example
        ```json
        {
          "status": "initiated",
          "room_name": "call-room-123",
          "participant_identity": "sip_participant_456",
          "transfer_to": "tel:+15551234567"
        }
        ```
      required:
        - status
        - room_name
        - participant_identity
        - transfer_to
      properties:
        participant_identity:
          type: string
          description: The identity of the participant being transferred
          example: sip_participant_456
        room_name:
          type: string
          description: The room name where the transfer was initiated
          example: call-room-123
        status:
          type: string
          description: Status of the transfer request ("initiated" or "completed")
          example: initiated
        transfer_to:
          type: string
          description: 'The normalized phone number with tel: prefix'
          example: tel:+15551234567
    SIPTransferErrorResponse:
      type: object
      description: |-
        Error response for SIP transfer failures

        # Example
        ```json
        {
          "error": "Participant 'sip_123' not found or is not a SIP participant",
          "code": "PARTICIPANT_NOT_FOUND"
        }
        ```
      required:
        - error
        - code
      properties:
        code:
          type: string
          description: Machine-readable error code
          example: PARTICIPANT_NOT_FOUND
        error:
          type: string
          description: Human-readable error message
          example: Participant not found or is not a SIP participant
  securitySchemes:
    auth:
      type: http
      scheme: bearer
      bearerFormat: Token
      description: >-
        Authentication token for protected endpoints. Can be provided as
        `Authorization: Bearer <token>` or `?api_key=<token>`. Required when
        AUTH_REQUIRED is enabled.

````