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

# Webhooks

> Recibe notificaciones HTTP en tiempo real cuando se crean, comparten o aceptan propuestas, o cuando llegan leads a Quikly.

Los webhooks envían solicitudes HTTP POST a tu servidor cuando ocurren eventos específicos en Quikly. Úsalos para sincronizar con tu CRM, disparar flujos de n8n, enviar notificaciones a Slack o construir automatizaciones personalizadas.

## Crear un webhook

Puedes crear webhooks desde la interfaz de Quikly o a través de la API.

### Desde la interfaz

Ve a **Configuración → Webhooks** y haz clic en **Crear Webhook**. Ingresa un nombre, la URL de tu endpoint y selecciona los eventos a los que quieres suscribirte.

### Desde la API

```bash theme={null}
curl -X POST "https://api.getquikly.com/api/external/v1/webhooks" \
  -H "X-API-Key: qk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CRM sync",
    "url": "https://your-server.com/webhooks/quikly",
    "events": ["proposal.created", "proposal.shared", "proposal.accepted"]
  }'
```

<Warning>
  La respuesta incluye un campo `secret` que se muestra **solo una vez**. Guárdalo inmediatamente — lo necesitas para verificar las firmas de los webhooks.
</Warning>

## Eventos disponibles

| Evento                        | Se dispara cuando                                                                |
| ----------------------------- | -------------------------------------------------------------------------------- |
| `proposal.created`            | Se crea una nueva propuesta                                                      |
| `proposal.updated`            | Se modifica una propuesta (requerimientos, configuración, precios)               |
| `proposal.shared`             | Se comparte una propuesta con un cliente vía enlace                              |
| `proposal.accepted`           | Un cliente acepta una propuesta                                                  |
| `proposal.rejected`           | Un cliente rechaza una propuesta                                                 |
| `proposal.revision_requested` | Un cliente solicita cambios a una propuesta                                      |
| `lead_session.created`        | Se inicia una nueva sesión de lead (desde widget, Telegram o API)                |
| `lead_session.updated`        | Cambia el estado de una sesión de lead (ej., recopilando info → propuesta lista) |

Puedes suscribirte a eventos específicos o escuchar todos incluyendo cada evento en el array `events`.

## Formato del payload

Cada entrega de webhook envía un payload JSON con esta estructura:

```json theme={null}
{
  "event": "proposal.accepted",
  "timestamp": "2026-04-03T14:30:00Z",
  "webhook_id": "wh_abc123",
  "data": {
    "proposal_id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Cloud Migration - Acme Corp",
    "status": "accepted",
    "client_name": "John Smith",
    "total": 24500.00,
    "currency": "USD",
    "share_url": "https://app.getquikly.com/p/abc123token",
    "responded_at": "2026-04-03T14:30:00Z"
  }
}
```

Para eventos de `lead_session`, el objeto `data` contiene campos de la sesión como `channel`, `channel_id`, `client_name`, `brief` y `status`.

## Headers HTTP

Cada solicitud de webhook incluye estos headers:

| Header                | Descripción                                        |
| --------------------- | -------------------------------------------------- |
| `X-Quikly-Event`      | Tipo de evento (ej., `proposal.accepted`)          |
| `X-Quikly-Signature`  | Digest hex HMAC-SHA256 del cuerpo de la solicitud  |
| `X-Quikly-Timestamp`  | Marca de tiempo Unix de cuándo se envió el webhook |
| `X-Quikly-Webhook-Id` | ID de la configuración del webhook                 |
| `Content-Type`        | Siempre `application/json`                         |

## Verificar firmas

Cada webhook está firmado con el secret que recibiste al crearlo. Verifica el header `X-Quikly-Signature` para confirmar que la solicitud proviene de Quikly.

<CodeGroup>
  ```python Python theme={null}
  import hmac
  import hashlib

  def verify_webhook(payload_body: bytes, secret: str, signature: str) -> bool:
      expected = hmac.new(
          secret.encode("utf-8"),
          payload_body,
          hashlib.sha256,
      ).hexdigest()
      return hmac.compare_digest(expected, signature)
  ```

  ```javascript Node.js theme={null}
  const crypto = require("crypto");

  function verifyWebhook(payloadBody, secret, signature) {
    const expected = crypto
      .createHmac("sha256", secret)
      .update(payloadBody, "utf-8")
      .digest("hex");
    return crypto.timingSafeEqual(
      Buffer.from(expected),
      Buffer.from(signature)
    );
  }
  ```
</CodeGroup>

<Tip>
  Verifica siempre las firmas antes de procesar los payloads de webhooks. Esto evita que atacantes envíen eventos falsos a tu endpoint.
</Tip>

## Política de reintentos

Si tu endpoint devuelve un código de estado no-2xx o expira el tiempo (límite de 10 segundos), Quikly reintenta la entrega con backoff exponencial:

| Intento       | Demora      |
| ------------- | ----------- |
| 1er reintento | 30 segundos |
| 2do reintento | 2 minutos   |
| 3er reintento | 15 minutos  |
| 4to reintento | 1 hora      |
| 5to reintento | 4 horas     |

Después de 5 reintentos fallidos, la entrega se marca como fallida. Puedes ver todos los intentos en los logs de webhooks.

## Probar un webhook

Envía un evento de prueba para verificar que tu endpoint es accesible:

```bash theme={null}
curl -X POST "https://api.getquikly.com/api/external/v1/webhooks/{webhook_id}/test" \
  -H "X-API-Key: qk_your_api_key_here"
```

El payload de prueba usa el tipo de evento `test` y contiene datos de ejemplo. Tu endpoint debe devolver un código de estado 200.

## Ver logs de entrega

Consulta entregas recientes y depura fallos:

```bash theme={null}
curl "https://api.getquikly.com/api/external/v1/webhooks/{webhook_id}/logs" \
  -H "X-API-Key: qk_your_api_key_here"
```

Cada entrada del log incluye el código de estado HTTP, cuerpo de la respuesta, tiempo de respuesta y el payload completo que se envió.

También puedes ver los logs en la interfaz de Quikly en **Configuración → Webhooks → (seleccionar webhook) → Logs**.

## Gestión de webhooks

| Operación                 | Endpoint de API                                         | Ruta en la interfaz         |
| ------------------------- | ------------------------------------------------------- | --------------------------- |
| Listar todos los webhooks | `GET /webhooks`                                         | Configuración → Webhooks    |
| Actualizar eventos o URL  | `PUT /webhooks/{id}`                                    | Clic en webhook → Editar    |
| Pausar entregas           | `PUT /webhooks/{id}` con `is_active: false`             | Interruptor de toggle       |
| Eliminar                  | `DELETE /webhooks/{id}`                                 | Clic en webhook → Eliminar  |
| Regenerar secret          | `POST /webhooks/{id}/regenerate-secret` (solo interfaz) | Clic en webhook → Regenerar |
