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

# Endpoints de webhook

> Administra varias URL de webhook con secretos por endpoint y filtros de eventos.

El sistema de webhooks basado en endpoints te permite registrar **múltiples**
destinos por organización, cada uno con su propio secreto, su propio
estado y su propia suscripción a un subconjunto de tipos de eventos. Este es
el modelo recomendado para todas las integraciones nuevas.

Compáralo con el [webhook heredado de URL única](/api-reference/organizations#legacy-single-url-webhook),
que se conserva para mantener la compatibilidad con versiones anteriores, pero solo admite una URL por
organización.

## Endpoints

| Método   | Ruta                                                 | Rol requerido | Descripción                                  |
| -------- | ---------------------------------------------------- | ------------- | -------------------------------------------- |
| `GET`    | `/v1/developer/webhook-endpoints`                    | `admin+`      | Listar endpoints                             |
| `POST`   | `/v1/developer/webhook-endpoints`                    | `admin+`      | Crear un endpoint                            |
| `PATCH`  | `/v1/developer/webhook-endpoints/{endpoint_id}`      | `admin+`      | Actualizar etiqueta / URL / eventos / estado |
| `DELETE` | `/v1/developer/webhook-endpoints/{endpoint_id}`      | `admin+`      | Eliminar un endpoint                         |
| `POST`   | `/v1/developer/webhook-endpoints/{endpoint_id}/test` | `admin+`      | Enviar una entrega de prueba firmada         |

## Objeto endpoint

```json theme={null}
{
  "id": "c4d5e6f7-...",
  "label": "Production — Call events",
  "url": "https://example.com/thunderphone/hook",
  "events": ["telephony.incoming", "telephony.complete"],
  "status": "active",
  "secret_hint": "a1b2…9f0e",
  "created_at": "2026-04-20T18:24:10.113Z",
  "updated_at": "2026-04-20T18:24:10.113Z"
}
```

| Campo                      | Tipo            | Descripción                                                                                                                                                                               |
| -------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                       | UUID            | ID del endpoint                                                                                                                                                                           |
| `label`                    | string          | Nombre visible, de 1 a 120 caracteres                                                                                                                                                     |
| `url`                      | string          | URL HTTPS; se permite `http://localhost` para desarrollo                                                                                                                                  |
| `events`                   | array of string | Tipos de eventos suscritos (consulta los [valores válidos](#valid-event-types)). Un arreglo vacío se suscribe a todos los eventos                                                         |
| `status`                   | string          | `active`, `disabled` (pausado manualmente) o `failing` (se establece automáticamente cuando una entrega agota su programación de reintentos de 24 h sin un solo 2xx)                      |
| `secret_hint`              | string          | Primeros 4 y últimos 4 caracteres del secreto de firma con puntos suspensivos (`a1b2…9f0e`), suficientes para verificar el secreto que guardaste localmente sin exponer el valor completo |
| `created_at`, `updated_at` | timestamp       |                                                                                                                                                                                           |

<Note>
  El `secret` completo del endpoint se devuelve **una sola vez** al crearlo y
  nunca más. Guárdalo de forma segura: si lo pierdes, elimina el endpoint
  y créalo de nuevo.
</Note>

### Tipos de eventos válidos

`events` se valida con este conjunto exacto; los valores fuera de la lista
devuelven `400`. Consulta el [catálogo de eventos](/es/webhooks/events) para ver la
estructura de la carga útil de cada tipo.

* `telephony.incoming`, `telephony.complete`, `telephony.tool`
* `web.incoming`, `web.complete`, `web.tool`
* `call.graded`
* `issue.reported`
* `test-call.completed`
* `alert.triggered`

### Estados del endpoint

* `active` — las entregas fluyen normalmente.
* `disabled` — pausado manualmente mediante `PATCH`. No se envían solicitudes. Nunca
  cambiamos el estado de un endpoint `disabled`; volver a cambiarlo a
  `active` siempre es tu decisión.
* `failing` — se establece automáticamente cuando una entrega al endpoint agota
  toda su programación de reintentos (8 intentos durante 24 horas) sin
  obtener nunca un 2xx. Un endpoint con error no recibe más tráfico.
  Una vez que corrijas el endpoint, aplica `PATCH` a su estado para volver a `active`;
  las entregas cuya programación de reintentos aún no haya terminado se reanudarán donde
  quedaron.

***

## Listar endpoints

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.thunderphone.com/v1/developer/webhook-endpoints \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY"
  ```
</CodeGroup>

Devuelve un arreglo de [objetos endpoint](#endpoint-object).

***

## Crea un endpoint

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "label":  "Production — Call events",
      "url":    "https://example.com/thunderphone/hook",
      "events": ["telephony.incoming", "telephony.complete"]
    }'
  ```

  ```python Python theme={null}
  result = requests.post(
      "https://api.thunderphone.com/v1/developer/webhook-endpoints",
      headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
      json={
          "label":  "Production — Call events",
          "url":    "https://example.com/thunderphone/hook",
          "events": ["telephony.incoming", "telephony.complete"],
      },
  ).json()
  secret = result["secret"]
  endpoint_id = result["id"]
  ```
</CodeGroup>

### Campos de la solicitud

| Campo    | Tipo    | Obligatorio | Descripción                                                                                                                                                     |
| -------- | ------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `label`  | cadena  | sí          | 1–120 caracteres                                                                                                                                                |
| `url`    | cadena  | sí          | URL HTTPS (`http` permitido solo para `localhost` / `127.0.0.1`)                                                                                                |
| `events` | arreglo | no          | Vacío u omitido se suscribe a todos los eventos. Debe usar los valores enumerados en [Tipos de eventos válidos](#valid-event-types); se eliminan los duplicados |

Devuelve `201 Created` con el [objeto de endpoint](#endpoint-object) más
un campo `secret` adicional de nivel superior que contiene la clave de firma sin procesar: una
cadena hexadecimal de 48 caracteres:

```json theme={null}
{
  "id": "c4d5e6f7-…",
  "label": "Production — Call events",
  "url": "https://example.com/thunderphone/hook",
  "events": ["telephony.incoming", "telephony.complete"],
  "status": "active",
  "secret_hint": "a1b2…9f0e",
  "created_at": "2026-04-20T18:24:10.113Z",
  "updated_at": "2026-04-20T18:24:10.113Z",
  "secret": "a1b2c37e08d94f5b16a2c8d90e7f3a4b5c6d7e8f90a19f0e"
}
```

<Warning>
  `secret` se devuelve **solo al crearlo**. Las respuestas `GET` posteriores
  incluyen solo `secret_hint`. Copia el valor completo en tu gestor de
  secretos antes de descartar la respuesta.
</Warning>

***

## Actualiza un endpoint

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PATCH https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-... \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "label":  "Production — Call + Grade events",
      "events": ["telephony.incoming", "telephony.complete", "call.graded"]
    }'
  ```
</CodeGroup>

| Campo    | Tipo    | Descripción                                                                                                        |
| -------- | ------- | ------------------------------------------------------------------------------------------------------------------ |
| `label`  | cadena  |                                                                                                                    |
| `url`    | cadena  |                                                                                                                    |
| `events` | arreglo |                                                                                                                    |
| `status` | cadena  | `active` o `disabled`. Establece `active` para volver a habilitar un endpoint que el servidor marcó como `failing` |

Devuelve `200 OK` con el [objeto de endpoint](#endpoint-object) actualizado.

***

## Envía una entrega de prueba

Envía un evento sintético `webhook.test` a un endpoint mediante el flujo de
entrega normal, incluida la serialización JSON canónica,
`X-ThunderPhone-Signature`, el registro de entregas y el seguimiento de
reintentos. La prueba se dirige al endpoint seleccionado independientemente de su filtro `events`.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-.../test \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY"
  ```
</CodeGroup>

El endpoint recibe un sobre como este:

```json theme={null}
{
  "data": {
    "message": "ThunderPhone webhook test",
    "sent_at": "2026-07-17T20:12:34.567890+00:00"
  },
  "event_id": "2ad6507c-7d19-4498-9b2d-7e8f944ab5a1",
  "type": "webhook.test"
}
```

La API devuelve `200 OK` después del primer intento, incluso si el destino
devuelve un error. Revisa `success`, `status`, `response_code` y `error`
para conocer el resultado de la entrega:

```json theme={null}
{
  "success": true,
  "event_id": "2ad6507c-7d19-4498-9b2d-7e8f944ab5a1",
  "event_type": "webhook.test",
  "status": "delivered",
  "response_code": 204,
  "error": ""
}
```

`webhook.test` es sintético y no se puede agregar a la suscripción `events`
de un endpoint. Si el primer intento falla, la entrega sigue el mismo
calendario de reintentos que las entregas de eventos normales.

***

## Eliminar un endpoint

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-... \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY"
  ```
</CodeGroup>

Devuelve `204 No Content`. La entrega a la URL se detiene de inmediato;
se abandonan los reintentos en curso.

***

## Relacionado

<CardGroup cols={2}>
  <Card title="Catálogo de eventos" icon="list" href="/es/webhooks/events">
    La lista completa de valores de `events` a los que puedes suscribirte.
  </Card>

  <Card title="Descripción general de webhooks" icon="bolt" href="/es/webhooks/overview">
    Verificación de firmas y semántica de entrega.
  </Card>
</CardGroup>
