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

# Configurar webhook

> Crea un webhook permitiendo asociar opcionalmente un agente y reutilizar URLs existentes.

<Note>
  Crea un webhook para recibir eventos de telefonía como
  <code>call.status.updated</code>, <code>call.completed</code> y
  <code>call.error</code>. La URL debe aceptar peticiones HTTPS.
</Note>

<Info>
  Incluye <code>X-API-Key</code> y el header <code>X-Workspace-Id</code> al
  crear el webhook. El servicio puede firmar cada evento con
  <code>X-Supervisor-Signature</code> si proporcionas un <code>secret</code>.
</Info>

## Crear un webhook

<CodeGroup>
  ```ts theme={null}
  import { createClient } from "@getsupervisor/agents-studio-sdk";

  const client = createClient({
  baseUrl: process.env.API_BASE_URL!,
  workspaceId: process.env.WORKSPACE_ID!,
  apiKey: process.env.API_KEY!,
  });

  const webhook = await client.webhooks.create({
  url: "https://miapp.com/webhooks/supervisor",
  description: "Actualiza el CRM con el estado de la llamada",
  headers: {
  "X-Custom-Signature": "allowed",
  },
  isActive: true,
  });

  console.log(webhook.id, webhook.secretPreview);

  ```

  ```bash theme={null}
  curl --request POST \
    --url "$API_BASE_URL/v1/webhooks" \
    --header "X-API-Key: $API_KEY" \
    --header "X-Workspace-Id: $WORKSPACE_ID" \
    --header "Content-Type: application/json" \
    --data '{
      "url": "https://miapp.com/webhooks/supervisor",
      "description": "Actualiza el CRM con el estado de la llamada",
      "headers": {
        "X-Custom-Signature": "allowed"
      },
      "isActive": true
    }'
  ```
</CodeGroup>

**Respuesta 201 Created**

```json theme={null}
{
  "id": "wh_01J8XW1N9P2Q3R4S5T6U",
  "agentId": null,
  "url": "https://miapp.com/webhooks/supervisor",
  "description": "Actualiza el CRM con el estado de la llamada",
  "isActive": true,
  "secretPreview": "whsec_********************",
  "createdAt": "2025-08-19T16:00:00.000Z",
  "updatedAt": "2025-08-19T16:00:00.000Z",
  "lastDeliveryAt": null,
  "headers": {
    "X-Custom-Signature": "allowed"
  },
  "successCount": 0,
  "failureCount": 0
}
```

<Info>
  Si no envías <code>secret</code>, generaremos uno aleatorio de 32 caracteres.
  Para asociar el webhook a un agente de voz agrega <code>agentId</code> en el
  cuerpo.
</Info>

## Suscribirse a eventos

Una vez creado el webhook tienes que registrar las suscripciones que definen qué
eventos se entregarán. Usa el endpoint <code>POST /v1/webhooks/{webhookId}/subscriptions</code>
con las claves del catálogo de eventos (por ejemplo

<code>call.status.updated</code>, <code>call.completed</code>,
<code>call.error</code>).

<CodeGroup>
  ```ts theme={null}
  import { createClient } from "@getsupervisor/agents-studio-sdk";

  const client = createClient({
  baseUrl: process.env.API_BASE_URL!,
  workspaceId: process.env.WORKSPACE_ID!,
  apiKey: process.env.API_KEY!,
  });

  const subscription = await client.webhooks.createSubscription(
  "wh_01J8XW1N9P2Q3R4S5T6U",
  {
  eventKey: "call.status.updated",
  isActive: true,
  }
  );

  console.log(subscription.id, subscription.eventKey);

  ```

  ```bash theme={null}
  curl --request POST \
    --url "$API_BASE_URL/v1/webhooks/wh_01J8XW1N9P2Q3R4S5T6U/subscriptions" \
    --header "X-API-Key: $API_KEY" \
    --header "X-Workspace-Id: $WORKSPACE_ID" \
    --header "Content-Type: application/json" \
    --data '{
      "eventKey": "call.status.updated",
      "isActive": true
    }'
  ```
</CodeGroup>

**Respuesta 201 Created**

```json theme={null}
{
  "id": "sub_01J8XY7Z8A9B0C1D2E3F",
  "eventKey": "call.status.updated",
  "isActive": true,
  "webhookId": "wh_01J8XW1N9P2Q3R4S5T6U",
  "createdAt": "2025-08-19T16:00:05.000Z",
  "updatedAt": "2025-08-19T16:00:05.000Z"
}
```

<Info>
  Puedes crear varias suscripciones por webhook, una por <code>eventKey</code>.
  Si envías una clave no registrada en el catálogo recibirás <code>400</code>.
  Usa <code>GET /v1/webhooks/{webhookId}/subscriptions</code> para listar las
  suscripciones activas.
</Info>

## Notificaciones que enviaremos

Publicaremos eventos a tu URL en formato JSON. Incluimos ejemplos típicos:

### call.status.updated — registrada

```json theme={null}
{
  "id": "evt_01J7W8A4XK0N5Y6Z7Q8P",
  "type": "call.status.updated",
  "created_at": "2025-08-19T16:01:00.000Z",
  "data": {
    "call_id": "Jabr9TXYYJHfvl6Syypi88rdAHYHmcq6",
    "call_status": "registered",
    "direction": "outbound",
    "to_number": "+525538808448"
  }
}
```

### call.status.updated — en curso

```json theme={null}
{
  "id": "evt_01J7W8A5A1B2C3D4E5F6",
  "type": "call.status.updated",
  "created_at": "2025-08-19T16:01:10.000Z",
  "data": {
    "call_id": "Jabr9TXYYJHfvl6Syypi88rdAHYHmcq6",
    "call_status": "ongoing",
    "from_number": "+12137771234",
    "to_number": "+525538808448",
    "agent_id": "oBeDLoLOeuAbiuaMFXRtDOLriTJ5tSxD"
  }
}
```

### call.status.updated — finalizada

```json theme={null}
{
  "id": "evt_01J7W8A6G7H8I9J0K1L2",
  "type": "call.status.updated",
  "created_at": "2025-08-19T16:05:00.000Z",
  "data": {
    "call_id": "Jabr9TXYYJHfvl6Syypi88rdAHYHmcq6",
    "call_status": "ended",
    "disconnection_reason": "agent_hangup",
    "duration_ms": 10000,
    "recording_url": "https://example.com/recording.wav",
    "public_log_url": "https://example.com/public_log.txt"
  }
}
```

### call.status.updated — error

```json theme={null}
{
  "id": "evt_01J7W8A7M8N9O0P1Q2R3",
  "type": "call.status.updated",
  "created_at": "2025-08-19T16:02:00.000Z",
  "data": {
    "call_id": "Jabr9TXYYJHfvl6Syypi88rdAHYHmcq6",
    "call_status": "error",
    "error_code": "telephony_provider_unavailable",
    "error_message": "Carrier unavailable"
  }
}
```

## Validación de firmas (opcional)

Si configuras <code>secret</code>, firmaremos cada notificación con HMAC-SHA256 en el header <code>X-Supervisor-Signature</code> usando el formato <code>sha256=HEX</code>.

## Reintentos y respuestas

* Esperamos 2xx de tu servidor. Si no, reintentaremos con backoff.
* Responde 200 OK lo antes posible (procesa de forma asíncrona si es necesario).

## Buenas prácticas

* Usa colas para procesar eventos.
* Idempotencia: guarda <code>id</code> del evento para evitar duplicados.
* Verifica la firma si definiste <code>secret</code>.


## OpenAPI

````yaml POST /v1/webhooks
openapi: 3.1.0
info:
  title: Agents Studio API
  version: 1.0.0
  description: >
    API del backend de Agents Studio. Expone servicios multi-tenant para
    gestionar agentes

    (texto y voz), catálogo de herramientas, habilitación de workspaces y
    operaciones de

    telefonía. Todos los endpoints requieren autenticación Bearer y respetan los
    contratos

    documentados en `docs/modules`.
  license:
    name: Proprietary
    url: https://getsupervisor.ai/legal/terms
servers:
  - url: https://api-prod.studio.getsupervisor.ai
    description: Producción
  - url: https://sandbox.agents.studio.getsupervisor.ai
    description: Sandbox
security:
  - BearerAuth: []
tags:
  - name: Agents
    description: >
      Gestión general de agentes y sus metadatos.

      Scopes requeridos: `agents:read` para consultas y `agents:write` para
      creación, actualización y operaciones sobre teléfonos.
  - name: Agent Versions
    description: Versionado y mantenimiento de versiones publicadas de los agentes.
  - name: Agent Schedules
    description: >-
      Configuración de horarios regulares y excepciones puntuales para controlar
      la disponibilidad de los agentes.
  - name: Agent Knowledge
    description: Uploads y sincronización de knowledge bases asociadas al agente.
  - name: Agent Tags
    description: Gestión de etiquetas asociadas a agentes.
  - name: Campaigns
    description: >
      Gestión de campañas masivas basadas en CSV para ejecutar agentes de forma
      batch.

      Scopes requeridos: `campaigns:read` para consultas y `campaigns:write`
      para creación.
  - name: Calls
    description: |
      Consultas de llamadas (Speech Analytics) disponibles para el workspace.
      Scopes requeridos: `calls:read`.
  - name: Knowledge
    description: Gestión de recursos de conocimiento asociados a tools.
  - name: Agent Instructions
    description: >
      Operaciones sobre instrucciones (prompt) gestionadas por los usuarios
      finales para

      guiar y corregir el comportamiento del agente. Las instrucciones se
      aplican a la

      versión activa del agente, se mantienen como texto libre sin formato (1 a
      500

      caracteres) y su prioridad se controla mediante el campo `order`.

      Scopes requeridos: `agent-instructions:read` para consultas y
      `agent-instructions:write` para creación o edición.
  - name: Voices
    description: Catálogo consolidado de voces provenientes de proveedores externos.
  - name: Catalogs
    description: >
      Gestión centralizada de catálogos (idiomas, tonos, voces, etiquetas) con
      alcance global o

      específico por workspace. Scopes requeridos: `catalogs:read` para
      consultas y

      `catalogs:write` para creación y modificaciones.
  - name: Agent Phones
    description: Conexión y desconexión de teléfonos asignados a agentes.
  - name: API Keys
    description: Gestión de credenciales de acceso programático y sus permisos.
  - name: Agent Blueprints
    description: >
      Gestión del blueprint (personalidad) asociado a cada versión de agente.

      Scopes requeridos: `agent-blueprints:read` para lectura y
      `agent-blueprints:write` para cambios en blueprint.
  - name: Agent Stages
    description: >
      Autoría de stages del blueprint del agente, abarcando orden, prompts y
      validaciones previas a la publicación.

      Scopes requeridos: `stages:read` para consultas y `stages:write` para
      creación y edición. La validación se ejecuta automáticamente en cada
      mutación y la sincronización con proveedores sucede mediante jobs internos
      tras los cambios.
  - name: Stage Triggers
    description: >
      Gestión detallada de triggers que conectan stages dentro del blueprint y
      definen las transiciones conversacionales.

      Scopes requeridos: `stage-triggers:*` (o políticas equivalentes bajo
      `stages:*`).
  - name: Workspaces
    description: Gestión multi-tenant y habilitación de credenciales por workspace.
  - name: Tools
    description: >
      Catálogo y ejecución de tools disponibles para los agentes.

      Scopes requeridos: `tools:read` para listar y `tools:execute` para
      ejecutar tools.
  - name: Webhooks
    description: >
      Gestión de webhooks por workspace para suscribirse a eventos del dominio y
      recibir notificaciones HTTP.

      Scopes requeridos: `webhooks:read` para consultas y `webhooks:write` para
      crear, actualizar o eliminar webhooks y suscripciones.
paths:
  /v1/webhooks:
    post:
      tags:
        - Webhooks
      summary: Crear webhook
      description: >-
        Crea un webhook permitiendo asociar opcionalmente un agente y reutilizar
        URLs existentes.
      operationId: createWebhook
      parameters:
        - $ref: '#/components/parameters/XWorkspaceId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateWebhookRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookDetail'
        '400':
          description: Bad Request
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
        '500':
          description: Internal Server Error
components:
  parameters:
    XWorkspaceId:
      name: x-workspace-id
      in: header
      required: true
      description: Identificador del workspace multi-tenant.
      schema:
        type: string
        format: uuid
  schemas:
    CreateWebhookRequest:
      type: object
      properties:
        url:
          type: string
          format: uri
          description: Debe ser https.
        agentId:
          type:
            - string
            - 'null'
          format: uuid
          description: Identificador del agente asociado cuando aplica.
        description:
          type:
            - string
            - 'null'
          maxLength: 500
        isActive:
          type: boolean
          default: true
        headers:
          type: object
          additionalProperties:
            type: string
        secret:
          type: string
          description: >-
            Secreto HMAC opcional proporcionado por el cliente. Si se omite, el
            backend genera uno.
        method:
          type: string
          enum:
            - GET
            - POST
          default: POST
          description: Método HTTP para entregar eventos del webhook
      required:
        - url
      additionalProperties: false
    WebhookDetail:
      allOf:
        - $ref: '#/components/schemas/WebhookSummary'
        - type: object
          properties:
            headers:
              type: object
              additionalProperties:
                type: string
              description: Headers permitidos (allowlist). Nunca incluir Authorization.
            successCount:
              type: integer
              format: int32
              minimum: 0
            failureCount:
              type: integer
              format: int32
              minimum: 0
    WebhookSummary:
      type: object
      properties:
        id:
          type: string
          format: uuid
        url:
          type: string
          format: uri
          description: Debe ser https.
        agentId:
          type:
            - string
            - 'null'
          format: uuid
          description: Identificador del agente asociado cuando aplica.
        description:
          type:
            - string
            - 'null'
          maxLength: 500
        method:
          type: string
          enum:
            - GET
            - POST
          default: POST
          description: Método HTTP para entregar eventos del webhook
        isActive:
          type: boolean
        secretPreview:
          type:
            - string
            - 'null'
          description: Vista previa enmascarada del secreto (prefix...suffix).
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        lastDeliveryAt:
          type:
            - string
            - 'null'
          format: date-time
      required:
        - id
        - url
        - isActive
        - createdAt
        - updatedAt
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````