> For the documentation index, fetch https://sync.so/docs/llms.txt. Append .md to a page URL for Markdown. Documentation-search MCP: https://sync.so/docs/_mcp/server.

# Webhooks

> Configura webhooks para actualizaciones en tiempo real del estado de generación de lip sync. Incluye verificación de firma, manejo de errores y ejemplos de código.

Los webhooks de Sync Labs entregan notificaciones HTTP POST en tiempo real cuando tus jobs de generación de lip sync se completan o fallan. Usa webhooks en lugar de polling para construir flujos de trabajo eficientes y orientados a eventos que respondan a cambios de estado sin llamadas repetidas a la API.

## ¿Cómo configuro webhooks?

Para utilizar webhooks:

1. Especifica un parámetro `webhookUrl` al llamar a un endpoint de API que lo soporte.
2. Asegúrate de que tu endpoint de webhook pueda recibir y manejar requests HTTP `POST` y pueda consumir el [Webhook Payload para actualizaciones de estado](/api-reference/api/webhooks-payload-reference/webhooks).

> **Note**
>
> Por motivos de seguridad, tu webhook URL debe estar configurada para aceptar y
> procesar requests HTTPS `POST`.

Al aprovechar webhooks, puedes simplificar tu flujo con llamadas no bloqueantes, lo que te permite enfocarte en otras tareas mientras recibes notificaciones de finalización de jobs.

Si no recibes eventos, confirma que se incluyó exactamente `webhookUrl` en el request de generación, que el endpoint sea públicamente accesible por HTTPS y que devuelva una respuesta `2xx` rápidamente a requests `POST`. Si la entrega falla porque tu endpoint no está disponible o rechaza el request, haz polling del endpoint de estado de generación como fallback.

## Manejo de errores en webhooks

Cuando una generación falla, el payload del webhook incluirá información de error en dos campos:

* `error`: un mensaje de error legible por humanos que describe qué salió mal
* `error_code`: un código de error específico que puede usarse para manejo programático de errores (consulta la [guía de manejo de errores](/developer-guides/error-handling) para ver una lista completa de códigos)

Esta estructura de errores mejorada te permite tanto mostrar mensajes significativos a los usuarios como implementar lógica de manejo específica basada en códigos de error.

### Verifica firmas de webhook

Para asegurar que los requests de webhook provengan de Sync Labs, firmamos cada request con una firma. La firma se incluye en el header `Sync-Signature`.

Para verificar firmas, usa tu [signing secret](https://sync.so/settings/webhooks). También puedes obtenerlo programáticamente con [`GET /v2/organizations/webhook/secret`](/api-reference/api/organizations-api/get-webhook-secret). Guarda de forma segura el valor completo `whsec_...`; `masked=true` es solo para visualización y no debe usarse para verificación.

La firma está compuesta por 2 componentes:

* Timestamp (al momento de enviar el evento)
* Hash de firma (el timestamp y el cuerpo JSON raw exacto del request)

**`Javascript`**

```javascript Javascript
const express = require("express");
const { createHmac, timingSafeEqual } = require("crypto");

const app = express();

const WEBHOOK_SECRET = "whsec_";

// Keep the exact request bytes for signature verification.
app.use("/webhook", express.raw({ type: "application/json" }));

const verifySignature = (rawBody, signature, secret) => {
  try {
    if (!signature) {
      return false;
    }
    const [, timestamp, receivedSignature] =
      signature.match(/t=(\d+),v1=(.+)/) ?? [];
    if (!timestamp || !receivedSignature) {
      return false;
    }

    const signedPayload = Buffer.concat([
      Buffer.from(`${timestamp}.`),
      rawBody,
    ]);
    const expectedSignature = createHmac("sha256", secret)
      .update(signedPayload)
      .digest("hex");

    // Timing-safe comparison to prevent timing attacks
    return timingSafeEqual(
      Buffer.from(receivedSignature),
      Buffer.from(expectedSignature)
    );
  } catch (error) {
    return false;
  }
};

app.post("/webhook", (req, res) => {
  const signature = req.headers["sync-signature"];

  if (!verifySignature(req.body, signature, WEBHOOK_SECRET)) {
    return res.status(400).json({
      message: "Invalid signature",
    });
  }

  return res.status(200).json({
    message: "Webhook signature verified",
  });
});

app.listen(8080, () => {});
```

**`Python`**

```python Python
import hmac
import hashlib
import re
from flask import Flask, request, jsonify

app = Flask(__name__)

WEBHOOK_SECRET = 'whsec_'


def verify_signature(raw_body: bytes, signature: str, webhook_secret: str) -> bool:
    if not signature:
        return False

    try:
        match = re.match(r't=(\d+),v1=(.+)', signature)
        if not match:
            return False

        timestamp, received_signature = match.groups()
        if not timestamp or not received_signature:
            return False

        expected_signature = hmac.new(
            webhook_secret.encode("utf-8"),
            timestamp.encode("utf-8") + b"." + raw_body,
            hashlib.sha256
        ).hexdigest()

        # Timing-safe comparison to prevent timing attacks
        return hmac.compare_digest(received_signature, expected_signature)
    except Exception:
        return False


@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('Sync-Signature')

    if not verify_signature(request.get_data(cache=True), signature, WEBHOOK_SECRET):
        return jsonify({'message': 'Invalid signature'}), 400

    return jsonify({'message': 'Webhook signature verified'}), 200


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8085)

```

## Preguntas frecuentes

#### ¿Cómo pruebo webhooks en local?

Usa una herramienta de túnel como ngrok para exponer tu servidor local a internet. Inicia tu endpoint de webhook en local y luego ejecuta ngrok para obtener una URL HTTPS pública. Pasa esa URL como webhookUrl al crear una generación. Sync Labs enviará requests POST a tu servidor local a través del túnel.

#### ¿Qué pasa si mi endpoint está caído?

Si tu endpoint de webhook no es alcanzable cuando Sync Labs intenta la entrega, la notificación puede perderse. No hay reintento automático para entregas de webhook fallidas. Como red de seguridad, puedes hacer polling del endpoint de estado de generación para verificar jobs completados o fallidos que tu webhook pudo haber perdido.

#### ¿Cómo verifico las firmas de webhook?

Cada request de webhook incluye un header Sync-Signature que contiene un timestamp y un hash HMAC-SHA256. Usa tu signing secret de la página de configuración de webhooks para calcular la firma esperada y compárala con una función de comparación segura en tiempo para evitar timing attacks. Consulta los ejemplos de código de arriba.