> 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

> Configurez des webhooks pour recevoir en temps réel les mises à jour de statut des générations lip sync. Inclut la vérification de signature, la gestion des erreurs et des exemples de code.

Les webhooks Sync Labs envoient des notifications HTTP POST en temps réel quand vos jobs de génération lip sync se terminent ou échouent. Utilisez les webhooks au lieu du polling pour créer des workflows efficaces orientés événements qui réagissent aux changements de statut sans appels API répétés.

## Comment configurer les webhooks?

Pour utiliser les webhooks:

1. Spécifiez un paramètre `webhookUrl` lorsque vous appelez un endpoint API qui le prend en charge.
2. Assurez-vous que votre endpoint webhook peut recevoir et traiter les requêtes HTTP `POST`, et consommer le [Webhook Payload des mises à jour de statut](/api-reference/api/webhooks-payload-reference/webhooks).

> **Note**
>
> Pour des raisons de sécurité, votre URL webhook doit être configurée pour accepter et
> traiter des requêtes HTTPS `POST`.

En exploitant les webhooks, vous simplifiez votre workflow avec des appels non bloquants, ce qui vous permet de vous concentrer sur d'autres tâches tout en recevant les notifications de fin de job.

Si vous ne recevez pas d'événements, confirmez que la valeur exacte `webhookUrl` a bien été incluse dans la requête de génération, que l'endpoint est publiquement accessible en HTTPS, et qu'il renvoie rapidement une réponse `2xx` aux requêtes `POST`. Si la livraison est manquée parce que votre endpoint est indisponible ou rejette la requête, interrogez l'endpoint de statut de génération comme solution de repli.

## Gestion des erreurs dans les webhooks

Quand une génération échoue, le payload webhook inclut les informations d'erreur dans deux champs:

* `error`: message d'erreur lisible par un humain, décrivant ce qui a échoué
* `error_code`: code d'erreur spécifique, utilisable pour une gestion programmatique (voir le [guide gestion des erreurs](/developer-guides/error-handling) pour la liste complète)

Cette structure d'erreur améliorée vous permet à la fois d'afficher des messages utiles aux utilisateurs et d'implémenter une logique de gestion spécifique selon les codes d'erreur.

### Vérifier les signatures webhook

Pour garantir que les requêtes webhook proviennent de Sync Labs, nous signons chaque requête webhook. La signature est incluse dans le header `Sync-Signature`.

Pour vérifier les signatures, utilisez votre [signing secret](https://sync.so/settings/webhooks). Vous pouvez aussi le récupérer de façon programmatique avec [`GET /v2/organizations/webhook/secret`](/api-reference/api/organizations-api/get-webhook-secret). Stockez la valeur complète `whsec_...` de façon sécurisée, `masked=true` est uniquement destiné à l'affichage et ne doit pas être utilisé pour la vérification.

La signature est composée de 2 éléments:

* Timestamp (au moment de l'envoi de l'événement)
* Hash de signature (le timestamp et le body JSON brut exact de la requête)

**`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)

```

## Questions fréquentes

#### Comment tester des webhooks en local?

Utilisez un outil de tunneling comme ngrok pour exposer votre serveur local sur internet. Démarrez votre endpoint webhook en local, puis lancez ngrok pour obtenir une URL HTTPS publique. Passez cette URL comme webhookUrl lors de la création d'une génération. Sync Labs enverra les requêtes POST vers votre serveur local via le tunnel.

#### Que se passe-t-il si mon endpoint est indisponible?

Si votre endpoint webhook est inaccessible quand Sync Labs tente l'envoi, la notification peut être perdue. Il n'y a pas de retry automatique pour les échecs de livraison webhook. En filet de sécurité, vous pouvez interroger l'endpoint de statut de génération pour détecter les jobs terminés ou échoués que votre webhook aurait manqués.

#### Comment vérifier les signatures webhook?

Chaque requête webhook inclut un header Sync-Signature contenant un timestamp et un hash HMAC-SHA256. Utilisez votre signing secret depuis la page des paramètres webhooks pour calculer la signature attendue et comparez-la avec une fonction de comparaison temporellement sûre afin d'éviter les attaques de timing. Voir les exemples de code ci-dessus.