> This page is for Plate-forme, version V4 (default).
> For other versions, use one of these documentation indexes:
> - V4 (default): https://next.developer.frame.io/platform/v4/llms.txt
> - V4 expérimental: https://next.developer.frame.io/platform/v4-experimental/llms.txt
> - Hérité: https://next.developer.frame.io/platform/v2/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://next.developer.frame.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://next.developer.frame.io/_mcp/server.

# Webhooks V4

## Qu’est-ce qu’un webhook ?

Un **webhook** est un rappel HTTP de type push que Frame.io déclenche **dès qu’un événement important se produit** sur votre compte (par exemple, la fin du transcodage d’un nouveau fichier, l’ajout d’un commentaire ou la création d’un projet).

Au lieu d’interroger l’API, vous fournissez une URL HTTPS publique ; Frame.io envoie alors en temps réel une payload au format JSON à cette URL, ce qui vous permet de :

#### Synchroniser les métadonnées avec un système DAM/MAM externe

#### Alimenter les canaux Slack ou les systèmes de tickets

Pour en savoir plus sur ce qu’est un webhook et à quoi il sert, consultez la page [https://docs.webhook.site/](https://docs.webhook.site/).

## Vue d’ensemble des points d’entrée

| **Opération**                                                     | **Point d’entrée**                                                    | **Détails**                                                         |
| ----------------------------------------------------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------- |
| **Créer** un webhook                                              | POST /v4/accounts/\{account\_id}/workspaces/\{workspace\_id}/webhooks | Corps avec `name`, `url`, `events[]`                                |
| **Répertorier** tous les webhooks pour un espace de travail donné | GET /v4/accounts/\{account\_id}/workspaces/\{workspace\_id}/webhooks  | Prend en charge la pagination.                                      |
| **Afficher** un webhook                                           | GET /v4/webhooks/\{webhook\_id}                                       | Renvoie le secret de signature uniquement au moment de la création. |
| **Mettre à jour** un webhook                                      | PATCH /v4/webhooks/\{webhook\_id}                                     | Modifie `url`, `events` ou `is_active`.                             |
| **Supprimer** un webhook                                          | DELETE /v4/webhooks/\{webhook\_id}                                    | Suspend immédiatement les livraisons.                               |

> **Warning**
>
> **Authentification** : tous les points d’entrée V4 nécessitent un jeton d’accès OAuth 2.0 obtenu via l’Adobe Developer Console. Les jetons de développeur hérités et les JWT **ne sont pas** acceptés.

## Modifications et mises à jour dans Frame V4

> **Info**
>
> Les webhooks créés dans la version héritée sont transférés vers la version 4 avec les modifications suivantes :
>
> 1. **Structure de la payload** : ajout de l’identifiant du compte à la payload.
> 2. **Modifications apportées aux points d’entrée** : le `team_id` n’est plus fourni dans la payload JSON, mais figure désormais dans le paramètre « path » de l’URL : `https://api.frame.io/v4/accounts/:account_id/workspaces/:workspace_id/webhooks`
> 3. **Intégration API** : en raison des modifications apportées à la structure de l’API, aux points d’entrée et aux méthodes d’authentification, tout code existant destiné aux webhooks entrants qui effectue des appels ultérieurs à l’API Frame.io pour l’enrichissement et la recherche de ressources doit être mis à jour.
> 4. **Types d’événements** : les webhooks liés aux ressources ont été scindés en événements distincts pour les fichiers et les dossiers. Tous les webhooks de la version héritée et contenant des événements liés aux ressources doivent être mis à jour pour correspondre aux événements appropriés pour les fichiers et les dossiers.

> **Warning**
>
> **Statut du webhook après la migration** : lorsque votre compte passe à Frame.io V4, les webhooks existants des versions précédentes sont automatiquement désactivés. Cela vous permet de modifier les points d’entrée de vos webhooks et la logique d’intégration afin de les adapter aux mises à jour de la version 4 avant de les réactiver. Les webhooks qui n’ont pas été mis à jour pour être compatibles avec la version 4 rencontreront des erreurs s’ils sont activés sans avoir été modifiés en conséquence. Vous pouvez vérifier quels webhooks sont inactifs en consultant le champ `is_active` via l’API ou en vérifiant les [paramètres de vos webhooks](https://next.frame.io/settings/webhooks) avant de les réactiver.

## Abonnements aux événements de webhook

Lorsque vous créez et mettez à jour des webhooks, identifiez les événements qui vous intéressent. Choisissez-en autant que vous le souhaitez. Notez toutefois que l’expérience s’en trouve améliorée si vous vous abonnez à un nombre réduit d’événements, en répartissant vos webhooks de manière logique à l’aide de schémas de nommage distincts et de points d’entrée différents, afin de pouvoir modéliser votre logique métier côté réception et ainsi réduire le filtrage et le routage dans les fonctions partagées.

> **Note**
>
> Portée de l’événement : tous les événements sont limités à l’espace de travail indiqué lors de la création du webhook. Cela signifie que des événements seront envoyés pour toutes les actions effectuées dans l’ensemble des projets de cet espace de travail.

### Projets

| Événement         | Description                                        |
| ----------------- | -------------------------------------------------- |
| `project.created` | Un nouveau projet a été **créé**.                  |
| `project.updated` | Les paramètres d’un projet ont été **mis à jour**. |
| `project.deleted` | Un projet a été **supprimé**.                      |

### Fichiers

| Événement               | Description                                                                                                                                                                                                                                            |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `file.created`          | Un fichier a été **créé** dans Frame.io. *Remarque :* cet événement se déclenche avant la fin du chargement du fichier. Si votre gestionnaire a besoin du fichier complet, nous vous recommandons plutôt de surveiller l’événement `upload.completed`. |
| `file.ready`            | Tous les transcodages sont **terminés**, une fois que le fichier a été chargé et traité.                                                                                                                                                               |
| `file.updated`          | Le nom d’un fichier ou d’autres informations ont changé.                                                                                                                                                                                               |
| `file.deleted`          | Un fichier a été **supprimé** (manuellement ou autrement).                                                                                                                                                                                             |
| `file.upload.completed` | Un fichier a été **chargé**.                                                                                                                                                                                                                           |
| `file.versioned`        | Une version de fichier a été **créée**.                                                                                                                                                                                                                |

### Dossiers

| Événement        | Description                                         |
| ---------------- | --------------------------------------------------- |
| `folder.created` | Un nouveau dossier a été **créé**.                  |
| `folder.updated` | Les paramètres d’un dossier ont été **mis à jour**. |
| `folder.deleted` | Un dossier a été **supprimé**.                      |

### Commentaires

| Événement             | Description                                                       |
| --------------------- | ----------------------------------------------------------------- |
| `comment.created`     | Un nouveau commentaire ou une nouvelle réponse a été **créé(e)**. |
| `comment.updated`     | Un commentaire a été mis à jour.                                  |
| `comment.deleted`     | Un commentaire a été **supprimé**.                                |
| `comment.completed`   | Un commentaire a été marqué comme **terminé**.                    |
| `comment.uncompleted` | Un commentaire a été marqué comme **inachevé**.                   |

### Métadonnées

| Événement                | Description                                          |
| ------------------------ | ---------------------------------------------------- |
| `metadata.value.updated` | Champs de métadonnées mis à jour pour une ressource. |

### Collections

| Événement            | Description                              |
| -------------------- | ---------------------------------------- |
| `collection.created` | Une nouvelle collection a été **créée**. |
| `collection.updated` | Une collection a été **mise à jour**.    |
| `collection.deleted` | Une collection a été **supprimée**.      |

### Champs personnalisés

| Événement             | Description                                   |
| --------------------- | --------------------------------------------- |
| `customfield.created` | Un nouveau champ personnalisé a été **créé**. |
| `customfield.updated` | Un champ personnalisé a été **mis à jour**.   |
| `customfield.deleted` | Un champ personnalisé a été **supprimé**.     |

### Partages

| Événement       | Description                        |
| --------------- | ---------------------------------- |
| `share.created` | Un nouveau partage a été **créé**. |
| `share.updated` | Un partage a été **mis à jour**.   |
| `share.deleted` | Un partage a été **supprimé**.     |
| `share.viewed`  | Un partage a été **consulté**.     |

## Payload du message du webhook

Toutes les payloads des webhooks contiennent un champ `type`, qui indique l’événement qui s’est produit, ainsi qu’un objet `resource`. L’objet `resource` contient le `type` et l’`ID` de la ressource Frame.io associée à l’événement.

### Exemple de payload

```json
{
  "account": {
    "id": "6f70f1bd-7e89-4a7e-b4d3-7e576585a181"
  },
  "project": {
    "id": "7e46e495-4444-4555-8649-bee4d391a997"
  },
  "resource": {
    "id": "d3075547-4e64-45f0-ad12-d075660eddd2",
    "type": "file"
  },
  "type": "file.ready",
  "user": {
    "id": "56556a3f-859f-4b38-b6c6-e8625b5da8a5"
  },
  "workspace": {
    "id": "378fcbf7-6f88-4224-8139-6a743ed940b2"
  }
}
```

Dans l’exemple ci-dessus concernant l’événement `file.created`, `resource.id` indique l’`ID` du fichier nouvellement créé. En outre, les objets `workspace`, `project` et `user` sont inclus, avec les `workspace.id`, `project.id` et `user.id` correspondants. Ces valeurs permettent de réduire le nombre d’appels API en filtrant les événements entrants ou en consultant les données mises en cache localement.

> **Warning**
>
> **Nous ne fournissons aucune information supplémentaire concernant la ressource souscrite, hormis son identifiant**.
>
> Si votre application a besoin d’informations ou de contexte supplémentaires, nous vous recommandons d’effectuer un appel API pour obtenir plus d’informations sur les ressources concernées.

## Sécurité

Par défaut, tous les webhooks disposent d’une clé de signature. Ce secret de signature non configurable permet de vérifier que la requête provient bien de Frame.io.

La payload de la réponse pour le webhook que vous avez configuré contient le secret de signature propre à ce webhook. Ce secret **n’est fourni que dans cette réponse initiale de création du webhook** ; veillez donc à le conserver en lieu sûr dans votre référentiel de secrets ou dans vos variables d’environnement. Utilisez-le ultérieurement pour vérifier que le webhook provient bien directement de nos serveurs et qu’il n’a pas été intercepté ou altéré d’une quelconque manière.

### Vérification des signatures des webhooks

Pour protéger une intégration contre les attaques de type « man-in-the-middle » et les attaques par rejeu, il est essentiel de vérifier la signature de la payload du webhook. La vérification permet de s’assurer que les payloads des webhooks ont bien été envoyées par Frame.io et que leur contenu n’a pas été modifié pendant le transfert.

La requête `POST` comprend les en-têtes HTTP suivants :

| Nom de l’en-tête                              | Description                                               | Exemple                                                               |
| --------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------------------------- |
| `X-Frameio-Request-Timestamp`                 | Horodatage auquel la requête a été envoyée.               | `1604004499`                                                          |
| `X-Frameio-Signature`                         | Signature du webhook de calcul.                           | `v0=a77ce6856e609c884575c2fd211d07a9ad1c3f72e19c06ff710e8f086ffca883` |
| `user-agent: &quot;Frame.io V4 API&quot;`     | Agent utilisateur dans l’en-tête pour la version 4.       |                                                                       |
| `user-agent: &quot;Frame.io Legacy API&quot;` | Agent utilisateur dans l’en-tête pour la version héritée. |                                                                       |

**`Python`**

```python title="Python"
import hmac
import hashlib

def verify_signature(curr_time, req_time, signature, body, secret):
    """
    Verify Webhook signature
    :Args:
        curr_time (float): Current epoch time
        req_time (float): Request epoch time
        signature (str): Signature provided by the Frame.io API for the given request
        body (str): Webhook body from the received POST
        secret (str): The secret for this Webhook that you saved when you first created it
    """
    if int(curr_time) - int(req_time) < 500:
        message = 'v0:{}:{}'.format(req_time, body)
        calculated_signature = 'v0={}'.format(hmac.new(
            bytes(secret, 'latin-1'),
            msg=bytes(message, 'latin-1'),
            digestmod=hashlib.sha256).hexdigest())
        if calculated_signature == signature:
            return True
    return False
```

La **date et l’heure** correspondent à l’heure système des serveurs de Frame.io au moment où le webhook sortant est envoyé. Cela permet de prévenir les [attaques par rejeu](https://en.wikipedia.org/wiki/Replay_attack). Nous vous recommandons de vérifier que cette heure ne s’écarte pas de plus de 5 minutes de l’heure locale. La **signature** est un hachage HMAC SHA-256 généré à l’aide de la clé de signature fournie lors de la création initiale du webhook. **Suivez ces étapes pour vérifier la signature :**

#### Extraire la signature

Extrayez la signature des en-têtes HTTP.

#### Créer un message à signer

Créez un message à signer en combinant la version, l’heure de transmission et le corps de la requête : `v0:timestamp:body.`

#### Traiter HMAC SHA256

Traitez la signature HMAC SHA-256 à l’aide de votre clé de signature.

#### Comparer les signatures

Comparez votre signature calculée avec celle fournie !

> **Note**
>
> La signature fournie est précédée de `v0=`. Pour l’instant, Frame.io propose une seule version pour la signature des requêtes. Assurez-vous que ce préfixe soit ajouté au début de votre signature calculée.

## Nouvelles tentatives et enregistrements

#### Politique de nouvelles tentatives

* Cinq tentatives au total (la première + 4 nouvelles tentatives)

* Retard exponentiel à partir de 15 s (+ variation)

* Un statut autre que `2xx` ou un délai d’attente supérieur à 5 secondes déclenche une nouvelle tentative.

#### Enregistrement des erreurs

Frame.io conserve un **journal des erreurs** avec : `webhook_id`, `account_id`, `event_type`, `resource_id`, `user_id`.

## Tutoriel sur les webhooks

### Étape 1 : configurer le serveur de réception (à effectuer en premier afin de connaître votre URL)

Ici, nous utilisons [webhook.site](http://webhook.site/), qui permet de créer facilement un récepteur de webhook à usage unique pouvant servir à inspecter les payloads et à envoyer des réponses simples, sans aucune logique métier. Lorsque vous accédez pour la première fois à [https://webhook.site](https://webhook.site/), un point d’entrée webhook unique est créé pour vous ; vous pouvez le copier immédiatement pour l’utiliser.

Cette URL est propre à votre session.

![Exemple de l’étape 1](/_fern-files/frame-io.docs.buildwithfern.com/09ca9e64de4cd7b5b0982e6c2ae5f0978320cd11272b448b7f9f8c2aff1239ab/docs/pages/v4/guides/webhook_site_example.gif)

### Étape 2 : choisir le ou les événements auxquels vous souhaitez vous abonner

Dans ce tutoriel, nous allons faire simple et configurer ce webhook pour qu’il se contente de s’abonner aux événements `file.created`. La payload JSON que nous utiliserons pour la création du webhook sera la suivante.

```json
{
    "data": {
        "name": "asset.created sample webhook",
        "events": ["file.created"],
        "url": "https://webhook.site/c05f2216-9558-4816-bc09-f77ee7b9de40"
    }
}
```

### Étape 3 : créer une ressource webhook à l’aide de Postman

À l’aide de Postman, effectuez un appel API pour créer la ressource webhook, en indiquant le point d’entrée [webhook.site](http://webhook.site/) dans la payload.

### Étape 4 : tester !

Maintenant que vous avez créé l’abonnement au webhook et configuré les points d’entrée pour recevoir les webhooks, il est temps de le tester en déclenchant le premier webhook en effectuant l’action appropriée qui entraînerait son déclenchement.

Comme notre exemple a été configuré pour se déclencher via l’événement `file.created`, nous allons maintenant charger un nouveau fichier dans n’importe quel projet du compte et de l’espace de travail dans lesquels le webhook a été configuré.

![Exemple de l’étape 4](/_fern-files/frame-io.docs.buildwithfern.com/7503b906ce873425c6477487378fe9c513d5cbddc524754f0e1fe8ba10de5c16/docs/pages/v4/guides/trigger_asset_created_webhook.gif)

## Ressources supplémentaires

#### [Ngrok](https://ngrok.com/)

**Ngrok** est un outil formidable pour les développeurs qui travaillent avec des webhooks devant être accessibles via une URL publique. Il établit des tunnels sécurisés entre votre environnement local et Internet, ce qui vous permet de rendre votre serveur local accessible afin de recevoir des payloads de webhook en temps réel.

#### [Hookdeck](https://hookdeck.com/)

**Hookdeck** est une plateforme conçue pour aider les équipes à gérer efficacement les webhooks grâce à une passerelle d’événements robuste. Il centralise la gestion des webhooks, garantissant ainsi qu’aucun événement ne soit manqué, et propose des fonctionnalités telles que le filtrage, la mise en file d’attente et la reprise des webhooks ayant échoué.

#### [Webhook.site](https://webhook.site)

**Webhook.site** est un outil exceptionnel pour le prototypage et le test des webhooks, offrant une plateforme simple, mais puissante permettant de capturer et d’analyser les requêtes HTTP envoyées à des URL uniques générées automatiquement.

#### [Val.town](https://www.val.town/)

**Val.town** est un excellent outil pour créer rapidement des prototypes de gestionnaires de webhooks, car il simplifie le processus d’écriture, de test et de déploiement de petites fonctions JavaScript et Python directement depuis le navigateur.