> ## 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.

# Update SIP hooks

> Adds or replaces SIP hooks in the cache. Hooks with matching hosts
(case-insensitive) will be replaced. Hosts defined in the application
configuration cannot be modified. The changes take effect immediately
and persist across server restarts.

**Note**: Secrets are NOT stored in the cache. Runtime-added hooks will
use the global `hook_secret` from the server configuration.

# Request Body
Array of hook entries with `host` and `url` fields.

# Returns
* `200 OK` - Updated list of SIP hooks
* `400 Bad Request` - If validation fails (e.g., duplicate hosts)
* `500 Internal Server Error` - If writing the cache fails

Adds or replaces SIP webhook forwarding entries at runtime. Changes take effect immediately and persist across server restarts.

## Request body

Array of hook entries with:

* `host` - Host pattern for matching SIP domains (case-insensitive)
* `url` - HTTPS URL to forward webhook events to
* `auth_id` - Tenant identifier for room ownership

<Note>
  The `auth_id` field is required when `AUTH_REQUIRED=true`. It determines which tenant owns rooms created from inbound SIP calls to this host.
</Note>

## Behavior

* Hooks with matching hosts (case-insensitive) are replaced; others are added.
* Hosts defined in the application configuration cannot be modified via this endpoint.
* Secrets are NOT stored in the cache. Runtime-added hooks use the global `hook_secret` from server configuration.

## Error responses

| Status                      | Condition                                                                             |
| --------------------------- | ------------------------------------------------------------------------------------- |
| `400 Bad Request`           | Validation failed (duplicate hosts, non-HTTPS URLs, missing `auth_id` when required). |
| `405 Method Not Allowed`    | Attempted to modify a host defined in application config.                             |
| `500 Internal Server Error` | Failed to write hooks cache.                                                          |


## OpenAPI

````yaml POST /sip/hooks
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/hooks:
    post:
      tags:
        - sip
      summary: Updates SIP hooks.
      description: |-
        Adds or replaces SIP hooks in the cache. Hooks with matching hosts
        (case-insensitive) will be replaced. Hosts defined in the application
        configuration cannot be modified. The changes take effect immediately
        and persist across server restarts.

        **Note**: Secrets are NOT stored in the cache. Runtime-added hooks will
        use the global `hook_secret` from the server configuration.

        # Request Body
        Array of hook entries with `host` and `url` fields.

        # Returns
        * `200 OK` - Updated list of SIP hooks
        * `400 Bad Request` - If validation fails (e.g., duplicate hosts)
        * `500 Internal Server Error` - If writing the cache fails
      operationId: update_sip_hooks
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SipHooksRequest'
        required: true
      responses:
        '200':
          description: Updated list of SIP hooks
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SipHooksResponse'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SipHooksErrorResponse'
        '405':
          description: Host defined in application config cannot be modified
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SipHooksErrorResponse'
        '500':
          description: Failed to write hooks cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SipHooksErrorResponse'
      security:
        - auth: []
components:
  schemas:
    SipHooksRequest:
      type: object
      description: |-
        Request body for updating SIP hooks.

        Contains a list of SIP webhook configurations to add or replace.
      properties:
        hooks:
          type: array
          items:
            $ref: '#/components/schemas/SipHookEntry'
          description: |-
            List of SIP hooks to add or replace.
            Hooks with matching hosts (case-insensitive) will be replaced.
    SipHooksResponse:
      type: object
      description: Response body for SIP hooks operations.
      required:
        - hooks
      properties:
        hooks:
          type: array
          items:
            $ref: '#/components/schemas/SipHookEntry'
          description: List of all configured SIP hooks
    SipHooksErrorResponse:
      type: object
      description: Error response for SIP hooks operations.
      required:
        - error
      properties:
        error:
          type: string
          description: Error message describing what went wrong
          example: 'Duplicate host detected: example.com'
    SipHookEntry:
      type: object
      description: >-
        A single SIP hook entry.


        Note: The `auth_id` field is conditionally required based on
        `AUTH_REQUIRED`:

        - When `AUTH_REQUIRED=true`: `auth_id` must be provided and cannot be
        empty

        - When `AUTH_REQUIRED=false`: `auth_id` may be empty (unauthenticated
        mode)
      required:
        - host
        - url
        - auth_id
      properties:
        auth_id:
          type: string
          description: >-
            Tenant identifier for this hook (written to LiveKit room metadata).

            Required when AUTH_REQUIRED=true; may be empty when
            AUTH_REQUIRED=false.

            When empty, room metadata updates are skipped.
          example: tenant-123
        host:
          type: string
          description: Host pattern for matching SIP domains (case-insensitive)
          example: example.com
        url:
          type: string
          description: HTTPS URL to forward webhook events to
          example: https://webhook.example.com/events
  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.

````