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

# Webhooks

> Configura webhooks para recibir notificaciones en tiempo real sobre eventos de la plataforma LINA.

## Descripción general

Los webhooks permiten que LINA envíe notificaciones HTTP POST a tu servidor cuando ocurren eventos relevantes. Esto elimina la necesidad de hacer polling y te permite reaccionar en tiempo real.

## Eventos disponibles

| Evento               | Descripción                                                           |
| -------------------- | --------------------------------------------------------------------- |
| `patient.created`    | Se ha registrado un nuevo paciente                                    |
| `form.completed`     | Un paciente ha completado un formulario                               |
| `call.ended`         | Una llamada IA ha finalizado                                          |
| `conversation.ended` | Una conversación de chat IA ha finalizado                             |
| `credits.low`        | Tu saldo de créditos está por debajo del 10% de la asignación mensual |
| `schedule.sent`      | Un formulario programado ha sido enviado al paciente                  |

## Configuración

<Steps>
  <Step title="Registrar un webhook">
    ```bash theme={null}
    curl -X POST https://api.linahealthcareplatform.com/api/v1/webhooks \
      -H "Authorization: Bearer YOUR_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "url": "https://tu-servidor.com/webhooks/lina",
        "events": ["form.completed", "call.ended", "credits.low"]
      }'
    ```

    **Respuesta:**

    ```json theme={null}
    {
      "id": "wh_abc123",
      "url": "https://tu-servidor.com/webhooks/lina",
      "events": ["form.completed", "call.ended", "credits.low"],
      "secret": "whsec_a1b2c3d4e5f6...",
      "status": "active",
      "createdAt": "2026-05-14T10:00:00Z"
    }
    ```

    <Warning>
      El campo `secret` solo se muestra una vez en la respuesta de creación. Guárdalo de forma segura — lo necesitarás para verificar las firmas.
    </Warning>
  </Step>

  <Step title="Recibir eventos">
    LINA enviará peticiones `POST` a tu URL con el siguiente formato:

    ```json theme={null}
    {
      "id": "evt_xyz789",
      "event": "form.completed",
      "createdAt": "2026-05-14T12:34:56Z",
      "data": {
        "formId": "form_abc123",
        "patientId": "pat_xyz789",
        "responses": [...]
      }
    }
    ```

    **Headers incluidos:**

    ```
    Content-Type: application/json
    X-Lina-Signature: sha256=a1b2c3d4...
    X-Lina-Event: form.completed
    X-Lina-Delivery: evt_xyz789
    ```
  </Step>

  <Step title="Responder correctamente">
    Tu endpoint debe responder con un código HTTP `2xx` en un máximo de **10 segundos**. Cualquier otra respuesta se considera un fallo y se reintentará.
  </Step>
</Steps>

## Verificación de firma

Todos los webhooks incluyen una firma HMAC-SHA256 en el header `X-Lina-Signature`. **Siempre debes verificar esta firma** para asegurar que la petición proviene de LINA.

<CodeGroup>
  ```javascript Node.js theme={null}
  const crypto = require('crypto');

  function verifyWebhookSignature(payload, signature, secret) {
    const expectedSignature = 'sha256=' + crypto
      .createHmac('sha256', secret)
      .update(payload, 'utf8')
      .digest('hex');

    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(expectedSignature)
    );
  }

  // En tu handler Express:
  app.post('/webhooks/lina', express.raw({ type: 'application/json' }), (req, res) => {
    const signature = req.headers['x-lina-signature'];
    const isValid = verifyWebhookSignature(req.body, signature, process.env.LINA_WEBHOOK_SECRET);

    if (!isValid) {
      return res.status(401).send('Invalid signature');
    }

    const event = JSON.parse(req.body);
    // Procesar el evento...
    res.status(200).send('OK');
  });
  ```

  ```python Python theme={null}
  import hmac
  import hashlib

  def verify_webhook_signature(payload: bytes, signature: str, secret: str) -> bool:
      expected = 'sha256=' + hmac.new(
          secret.encode('utf-8'),
          payload,
          hashlib.sha256
      ).hexdigest()
      return hmac.compare_digest(expected, signature)

  # En tu handler Flask:
  @app.route('/webhooks/lina', methods=['POST'])
  def handle_webhook():
      signature = request.headers.get('X-Lina-Signature')
      is_valid = verify_webhook_signature(
          request.data, signature, os.environ['LINA_WEBHOOK_SECRET']
      )

      if not is_valid:
          return 'Invalid signature', 401

      event = request.get_json()
      # Procesar el evento...
      return 'OK', 200
  ```
</CodeGroup>

<Warning>
  Nunca proceses un webhook sin verificar la firma. Un atacante podría enviar eventos falsos a tu endpoint.
</Warning>

## Política de reintentos

Si tu endpoint no responde con `2xx`, LINA reintentará el envío con **backoff exponencial**:

| Intento      | Retraso    |
| ------------ | ---------- |
| 1º reintento | 1 minuto   |
| 2º reintento | 10 minutos |
| 3º reintento | 1 hora     |

Después del tercer intento fallido, el evento se marca como `failed` y no se reintenta más. Puedes consultar los eventos fallidos en el panel de LINA o vía API.

<Note>
  Si tu endpoint falla en más del 95% de los envíos durante 24 horas, el webhook se desactivará automáticamente. Recibirás un email de notificación y podrás reactivarlo desde el panel.
</Note>

## Buenas prácticas

1. **Responde rápido** — Devuelve `200` inmediatamente y procesa el evento de forma asíncrona.
2. **Idempotencia** — Usa el `id` del evento para evitar procesar duplicados.
3. **Verifica siempre** — Comprueba la firma HMAC en cada petición.
4. **Usa HTTPS** — Solo se admiten URLs con HTTPS en producción.
5. **Registra eventos** — Almacena los eventos recibidos para debugging y auditoría.
