# Endpoints de webhooks

> Las operaciones de Endpoints de webhooks de la API de Trevol: parámetros, cuerpo, respuestas y ejemplos de código.

Fuente: https://platform.trevol.si/docs/api/webhook-endpoints

Endpoints que reciben avisos firmados (Standard Webhooks) cuando un documento cambia.

Los ejemplos son peticiones con cURL. La llave va en `TREVOL_API_KEY`; los cuerpos de ejemplo son los de la especificación. Los errores comunes están en [Errores](/docs/errores).

## Crear un endpoint de webhooks (máximo 5 por empresa y ambiente)

`POST /v1/webhook_endpoints` · `createWebhookEndpoint`

El `secret` (whsec_…) viene SOLO en esta respuesta. Cada entrega lleva `webhook-id` (el mismo en cada reintento: deduplica con él), `webhook-timestamp` y `webhook-signature`: `v1,` + base64(HMAC-SHA256(clave, `{webhook-id}.{webhook-timestamp}.{cuerpo}`)), con la clave de los 32 bytes que siguen a `whsec_`. No usa Idempotency-Key: la respuesta lleva el secreto y no se guarda.

**Cuerpo** ([WebhookEndpointInput](/docs/api/objetos#WebhookEndpointInput), obligatorio)

| Campo | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `url` | texto | sí | https:// con un nombre de dominio (no una IP), sin usuario ni clave, puerto 443 o 1024–65535. En cada intento se resuelve el nombre y se rechaza toda dirección privada o local. |
| `description` | texto (puede ser null) |  |  |
| `events` | lista de `*` \| `invoice.accepted` \| `invoice.rejected` \| `invoice.error` \| `invoice.delivered` \| `invoice.email_bounced` \| `invoice.email_failed` \| `credit_note.accepted` \| `credit_note.rejected` \| `credit_note.error` \| `credit_note.delivered` \| `credit_note.email_bounced` \| `credit_note.email_failed` \| `debit_note.accepted` \| `debit_note.rejected` \| `debit_note.error` \| `debit_note.delivered` \| `debit_note.email_bounced` \| `debit_note.email_failed` \| `balance.low` \| `numbering.low` \| `numbering.expiring` \| `certificate.expiring` \| `support_document.accepted` \| `support_document.rejected` \| `support_document.error` \| `support_document_adjustment.accepted` \| `support_document_adjustment.rejected` \| `support_document_adjustment.error` \| `equivalent_document.accepted` \| `equivalent_document.rejected` \| `equivalent_document.error` \| `equivalent_document.delivered` \| `equivalent_document.email_bounced` \| `equivalent_document.email_failed` \| `equivalent_document_adjustment.accepted` \| `equivalent_document_adjustment.rejected` \| `equivalent_document_adjustment.error` \| `equivalent_document_adjustment.delivered` \| `equivalent_document_adjustment.email_bounced` \| `equivalent_document_adjustment.email_failed` \| `payroll.accepted` \| `payroll.rejected` \| `payroll.error` \| `payroll_adjustment.accepted` \| `payroll_adjustment.rejected` \| `payroll_adjustment.error` \| `radian_event.accepted` \| `radian_event.rejected` \| `radian_event.error` | sí | Eventos del catálogo (49 tipos, hasta 60 en la lista), o ["*"] para todos (no se mezcla). `balance.low`, `numbering.low` y `numbering.expiring` solo existen en producción (llaves live). `webhook.test` no se suscribe. Máximo 60. |

**Respuestas**

| Estado | Qué pasó |
| --- | --- |
| 201 | El endpoint, con su `secret` ([WebhookEndpoint](/docs/api/objetos#WebhookEndpoint)) |
| 409 | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |
| 422 | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |
| Error | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |

`POST /v1/webhook_endpoints` (`createWebhookEndpoint`)

#### cURL

```bash
curl -X POST "https://api.trevol.si/v1/webhook_endpoints" \
  -H "Authorization: Bearer $TREVOL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://tu-servidor.co/webhooks/trevol",
  "description": "Producción: facturación",
  "events": [
    "invoice.accepted",
    "invoice.rejected",
    "credit_note.accepted"
  ]
}'
```

[Se administra en Webhooks](https://platform.trevol.si/webhooks)

## Mandar un evento `webhook.test` solo a este endpoint (debe estar activo)

`POST /v1/webhook_endpoints/{id}/test` · `testWebhookEndpoint`

Encola una entrega manual de prueba (3 intentos) y despierta el envío: en segundos llega a tu servidor con la firma de siempre. Hasta 60 por hora. Mira cómo salió en …/deliveries.

**Respuestas**

| Estado | Qué pasó |
| --- | --- |
| 202 | La entrega encolada ([WebhookDelivery](/docs/api/objetos#WebhookDelivery)) |
| 409 | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |
| 429 | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |
| Error | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |

`POST /v1/webhook_endpoints/{id}/test` (`testWebhookEndpoint`)

#### cURL

```bash
curl -X POST "https://api.trevol.si/v1/webhook_endpoints/we_3f0c1a2b3f0c1a2b3f0c1a2b3f0c1a2b/test" \
  -H "Authorization: Bearer $TREVOL_API_KEY"
```

[Probar en el Playground](https://platform.trevol.si/playground?op=testWebhookEndpoint)

## Rotar el secreto

`POST /v1/webhook_endpoints/{id}/rotate_secret` · `rotateWebhookEndpointSecret`

El `secret` (whsec_…) viene SOLO en esta respuesta. Cada entrega lleva `webhook-id` (el mismo en cada reintento: deduplica con él), `webhook-timestamp` y `webhook-signature`: `v1,` + base64(HMAC-SHA256(clave, `{webhook-id}.{webhook-timestamp}.{cuerpo}`)), con la clave de los 32 bytes que siguen a `whsec_`. El secreto anterior sigue firmando `grace_period_hours` (0 a 72; 24 por defecto): durante la gracia cada entrega lleva las dos firmas, separadas por un espacio.

**Cuerpo** (objeto)

| Campo | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `grace_period_hours` | entero |  |  |

**Respuestas**

| Estado | Qué pasó |
| --- | --- |
| 200 | El endpoint, con el `secret` nuevo ([WebhookEndpoint](/docs/api/objetos#WebhookEndpoint)) |
| 422 | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |
| Error | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |

`POST /v1/webhook_endpoints/{id}/rotate_secret` (`rotateWebhookEndpointSecret`)

#### cURL

```bash
curl -X POST "https://api.trevol.si/v1/webhook_endpoints/we_3f0c1a2b3f0c1a2b3f0c1a2b3f0c1a2b/rotate_secret" \
  -H "Authorization: Bearer $TREVOL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "grace_period_hours": 24
}'
```

[Se administra en Webhooks](https://platform.trevol.si/webhooks)

## Los endpoints de webhooks de la empresa y el ambiente

`GET /v1/webhook_endpoints` · `listWebhookEndpoints`

Los de la empresa y el ambiente de la llave (máximo 5). Las llaves de lectura ven el esquema y el host de la `url`, con el camino enmascarado («https://tu-servidor.co/…»): a veces es un secreto. Las de escritura la ven completa.

**Respuestas**

| Estado | Qué pasó |
| --- | --- |
| 200 | {object: list, data, has_more, next_cursor} (objeto) |
| Error | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |

`GET /v1/webhook_endpoints` (`listWebhookEndpoints`)

#### cURL

```bash
curl "https://api.trevol.si/v1/webhook_endpoints" \
  -H "Authorization: Bearer $TREVOL_API_KEY"
```

[Probar en el Playground](https://platform.trevol.si/playground?op=listWebhookEndpoints)

## Un endpoint

`GET /v1/webhook_endpoints/{id}` · `retrieveWebhookEndpoint`

El endpoint (nunca el secreto: solo se muestra al crear o rotar). Un id de otra empresa o de otro ambiente es 404.

**Respuestas**

| Estado | Qué pasó |
| --- | --- |
| 200 | El recurso ([WebhookEndpoint](/docs/api/objetos#WebhookEndpoint)) |
| Error | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |

`GET /v1/webhook_endpoints/{id}` (`retrieveWebhookEndpoint`)

#### cURL

```bash
curl "https://api.trevol.si/v1/webhook_endpoints/we_3f0c1a2b3f0c1a2b3f0c1a2b3f0c1a2b" \
  -H "Authorization: Bearer $TREVOL_API_KEY"
```

[Probar en el Playground](https://platform.trevol.si/playground?op=retrieveWebhookEndpoint)

## Las entregas de este endpoint, de la más nueva a la más vieja

`GET /v1/webhook_endpoints/{id}/deliveries` · `listWebhookEndpointDeliveries`

Cada intento con su estado HTTP, su error (`timeout`, `http_5xx`, `blocked_address`…) y su duración. Nunca guardamos la respuesta de tu servidor. Se conservan 30 días.

**Parámetros**

| Nombre | En | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- | --- |
| `limit` | consulta | entero |  |  |
| `starting_after` | consulta | texto |  |  |
| `status` | consulta | `pending` \| `sending` \| `succeeded` \| `failed` \| `canceled` |  |  |

**Respuestas**

| Estado | Qué pasó |
| --- | --- |
| 200 | {object: list, data, has_more, next_cursor} (objeto) |
| Error | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |

`GET /v1/webhook_endpoints/{id}/deliveries` (`listWebhookEndpointDeliveries`)

#### cURL

```bash
curl "https://api.trevol.si/v1/webhook_endpoints/we_3f0c1a2b3f0c1a2b3f0c1a2b3f0c1a2b/deliveries?limit=100" \
  -H "Authorization: Bearer $TREVOL_API_KEY"
```

[Probar en el Playground](https://platform.trevol.si/playground?op=listWebhookEndpointDeliveries)

## Cambiar la URL, la descripción, los eventos o pausar y reactivar

`PATCH /v1/webhook_endpoints/{id}` · `updateWebhookEndpoint`

Solo cambia lo que mandes. `status: paused` cancela las entregas pendientes; `status: enabled` reactiva el endpoint (también uno que Trevol desactivó por fallos sostenidos) y pone en cero el contador de fallos. `disabled` no se puede pedir.

**Cuerpo** ([WebhookEndpointUpdate](/docs/api/objetos#WebhookEndpointUpdate), obligatorio)

| Campo | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `url` | texto |  | https:// con un nombre de dominio (no una IP), sin usuario ni clave, puerto 443 o 1024–65535. En cada intento se resuelve el nombre y se rechaza toda dirección privada o local. |
| `description` | texto (puede ser null) |  |  |
| `events` | lista de `*` \| `invoice.accepted` \| `invoice.rejected` \| `invoice.error` \| `invoice.delivered` \| `invoice.email_bounced` \| `invoice.email_failed` \| `credit_note.accepted` \| `credit_note.rejected` \| `credit_note.error` \| `credit_note.delivered` \| `credit_note.email_bounced` \| `credit_note.email_failed` \| `debit_note.accepted` \| `debit_note.rejected` \| `debit_note.error` \| `debit_note.delivered` \| `debit_note.email_bounced` \| `debit_note.email_failed` \| `balance.low` \| `numbering.low` \| `numbering.expiring` \| `certificate.expiring` \| `support_document.accepted` \| `support_document.rejected` \| `support_document.error` \| `support_document_adjustment.accepted` \| `support_document_adjustment.rejected` \| `support_document_adjustment.error` \| `equivalent_document.accepted` \| `equivalent_document.rejected` \| `equivalent_document.error` \| `equivalent_document.delivered` \| `equivalent_document.email_bounced` \| `equivalent_document.email_failed` \| `equivalent_document_adjustment.accepted` \| `equivalent_document_adjustment.rejected` \| `equivalent_document_adjustment.error` \| `equivalent_document_adjustment.delivered` \| `equivalent_document_adjustment.email_bounced` \| `equivalent_document_adjustment.email_failed` \| `payroll.accepted` \| `payroll.rejected` \| `payroll.error` \| `payroll_adjustment.accepted` \| `payroll_adjustment.rejected` \| `payroll_adjustment.error` \| `radian_event.accepted` \| `radian_event.rejected` \| `radian_event.error` |  | Eventos del catálogo (49 tipos, hasta 60 en la lista), o ["*"] para todos (no se mezcla). `balance.low`, `numbering.low` y `numbering.expiring` solo existen en producción (llaves live). `webhook.test` no se suscribe. Máximo 60. |
| `status` | `enabled` \| `paused` |  | enabled reactiva (también uno desactivado por Trevol) y pone en cero el contador de fallos. |

**Respuestas**

| Estado | Qué pasó |
| --- | --- |
| 200 | El recurso ([WebhookEndpoint](/docs/api/objetos#WebhookEndpoint)) |
| 422 | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |
| Error | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |

`PATCH /v1/webhook_endpoints/{id}` (`updateWebhookEndpoint`)

#### cURL

```bash
curl -X PATCH "https://api.trevol.si/v1/webhook_endpoints/we_3f0c1a2b3f0c1a2b3f0c1a2b3f0c1a2b" \
  -H "Authorization: Bearer $TREVOL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "description": "Pausado mientras migramos el servidor",
  "status": "paused"
}'
```

[Se administra en Webhooks](https://platform.trevol.si/webhooks)

## Borrar el endpoint (con sus entregas)

`DELETE /v1/webhook_endpoints/{id}` · `deleteWebhookEndpoint`

Tu servidor deja de recibir avisos de inmediato. No se puede deshacer; si solo quieres detenerlo un rato, pausa el endpoint.

**Respuestas**

| Estado | Qué pasó |
| --- | --- |
| 200 | {id, object: webhook_endpoint, deleted: true} ([DeletedObject](/docs/api/objetos#DeletedObject)) |
| Error | Error (application/problem+json) ([Problem](/docs/api/objetos#Problem)) |

`DELETE /v1/webhook_endpoints/{id}` (`deleteWebhookEndpoint`)

#### cURL

```bash
curl -X DELETE "https://api.trevol.si/v1/webhook_endpoints/we_3f0c1a2b3f0c1a2b3f0c1a2b3f0c1a2b" \
  -H "Authorization: Bearer $TREVOL_API_KEY"
```

[Se administra en Webhooks](https://platform.trevol.si/webhooks)
