> This page is for Plataforma, version V4 (default).
> For other versions, use one of these documentation indexes:
> - V4 (default): https://next.developer.frame.io/platform/v4/llms.txt
> - V4 experimental: https://next.developer.frame.io/platform/v4-experimental/llms.txt
> - Heredado: 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 de V4

## ¿Qué es un webhook?

Un **webhook** es una devolución de llamada HTTP de tipo push que Frame.io activa **en cuanto ocurre algo relevante** en la cuenta (por ejemplo, cuando termina de transcodificarse un archivo nuevo, se añade un comentario o se crea un proyecto).

En lugar de sondear la API, proporcione una URL HTTPS pública. Frame.io envía una carga útil JSON a esa URL en tiempo real para que pueda:

#### Sincronizar metadatos con un DAM/MAM externo.

#### Rellenar canales de Slack o sistemas de tickets.

Para obtener más información sobre qué es un webhook y qué hace, consulte [https://docs.webhook.site/](https://docs.webhook.site/).

## Información general del punto final

| **Operación**                                            | **Punto final**                                                       | **Detalles**                                                   |
| -------------------------------------------------------- | --------------------------------------------------------------------- | -------------------------------------------------------------- |
| **Crear** un webhook                                     | POST /v4/accounts/\{account\_id}/workspaces/\{workspace\_id}/webhooks | Cuerpo con `name`, `url` y `events[]`                          |
| **Enumerar** todos los webhooks de un espacio de trabajo | GET /v4/accounts/\{account\_id}/workspaces/\{workspace\_id}/webhooks  | Admite paginación                                              |
| **Mostrar** un webhook                                   | GET /v4/webhooks/\{webhook\_id}                                       | Devuelve el secreto de firma solo en el momento de la creación |
| **Actualizar** un webhook                                | PATCH /v4/webhooks/\{webhook\_id}                                     | Cambia `url`, `events` o `is_active`                           |
| **Eliminar** un webhook                                  | DELETE /v4/webhooks/\{webhook\_id}                                    | Detiene inmediatamente las entregas                            |

> **Warning**
>
> **Autenticación**: Todos los puntos finales V4 requieren un token de acceso OAuth 2.0 obtenido mediante Adobe Developer Console. **No** se aceptan tokens de desarrollador heredados ni JWT.

## Cambios y actualizaciones en Frame V4

> **Info**
>
> Los webhooks creados en la versión heredada se transfieren a V4 con los siguientes cambios:
>
> 1. **Estructura de la carga útil**: Se ha añadido el ID de Account a la carga útil
> 2. **Cambios en el punto final**: `team_id` ya no se proporciona en la carga útil JSON, sino en el parámetro de ruta de la URL: `https://api.frame.io/v4/accounts/:account_id/workspaces/:workspace_id/webhooks`
> 3. **Integración de API**: Debido a los cambios en la estructura de la API, los puntos finales y los métodos de autenticación, es necesario actualizar cualquier código existente de webhooks entrantes que realice llamadas posteriores a la API de Frame.io para enriquecer recursos o buscarlos
> 4. **Tipos de evento**: Los webhooks de Assets se han dividido en eventos independientes de Files y Folders. Cualquier webhook procedente de la versión heredada con eventos de Assets debe actualizarse para incluir los eventos de Files y Folders correspondientes

> **Warning**
>
> **Estado del webhook después de la migración**: Cuando la cuenta migra a Frame.io V4, los webhooks existentes de versiones anteriores se desactivan automáticamente. Esto garantiza que pueda modificar los puntos finales de webhook y la lógica de integración para que funcionen con las actualizaciones de V4 antes de volver a activarlos. Los webhooks que no se hayan actualizado para ser compatibles con V4 encontrarán errores si se activan sin las modificaciones adecuadas. Puede comprobar qué webhooks están inactivos examinando el campo `is_active` mediante la API o revisando la [configuración de webhooks](https://next.frame.io/settings/webhooks) antes de volver a activarlos.

## Suscripciones a eventos de webhook

Al crear y actualizar webhooks, identifique qué eventos le interesan. Elija tantos como quiera, o solo unos pocos. Tenga en cuenta que la experiencia mejora si se suscribe a menos eventos y divide los webhooks de forma lógica con distintos esquemas de nomenclatura y distintos puntos finales. De este modo, podrá modelar la lógica empresarial en el punto final receptor para reducir el filtrado y el enrutamiento en funciones compartidas.

> **Note**
>
> Ámbito de eventos: todos los eventos tienen como ámbito el Workspace proporcionado durante la creación del webhook. Esto significa que se enviarán eventos para las acciones realizadas en todos los proyectos de ese Workspace.

### Proyectos

| Evento            | Descripción                                          |
| ----------------- | ---------------------------------------------------- |
| `project.created` | Se ha **creado** un nuevo Project                    |
| `project.updated` | Se ha **actualizado** la configuración de un Project |
| `project.deleted` | Se ha **eliminado** un Project                       |

### Archivos

| Evento                  | Descripción                                                                                                                                                                                                              |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `file.created`          | Se ha **creado** un File en Frame.io. *Nota:* Esto se activa antes de que el archivo termine de cargarse. Si el controlador necesita el archivo completo, recomendamos escuchar el evento `upload.completed` en su lugar |
| `file.ready`            | Todas las transcodificaciones han **finalizado** después de que un archivo se haya cargado y procesado                                                                                                                   |
| `file.updated`          | Ha cambiado el nombre u otra información de un File                                                                                                                                                                      |
| `file.deleted`          | Se ha **eliminado** un File, manualmente o de otro modo                                                                                                                                                                  |
| `file.upload.completed` | Se ha **cargado** un File                                                                                                                                                                                                |
| `file.versioned`        | Se ha **creado** una versión de File                                                                                                                                                                                     |

### Carpetas

| Evento           | Descripción                                          |
| ---------------- | ---------------------------------------------------- |
| `folder.created` | Se ha **creado** una nueva Folder                    |
| `folder.updated` | Se ha **actualizado** la configuración de una Folder |
| `folder.deleted` | Se ha **eliminado** una Folder                       |

### Comentarios

| Evento                | Descripción                                                |
| --------------------- | ---------------------------------------------------------- |
| `comment.created`     | Se ha **creado** un nuevo comentario o una nueva respuesta |
| `comment.updated`     | Se ha actualizado un comentario                            |
| `comment.deleted`     | Se ha **eliminado** un comentario                          |
| `comment.completed`   | Se ha marcado un comentario como **completado**            |
| `comment.uncompleted` | Se ha marcado un comentario como **no completado**         |

### Metadatos

| Evento                   | Descripción                                     |
| ------------------------ | ----------------------------------------------- |
| `metadata.value.updated` | Campos de metadatos actualizados para un activo |

### Colecciones

| Evento               | Descripción                           |
| -------------------- | ------------------------------------- |
| `collection.created` | Se ha **creado** una nueva Collection |
| `collection.updated` | Se ha **actualizado** una Collection  |
| `collection.deleted` | Se ha **eliminado** una Collection    |

### Campos personalizados

| Evento                | Descripción                                   |
| --------------------- | --------------------------------------------- |
| `customfield.created` | Se ha **creado** un nuevo campo personalizado |
| `customfield.updated` | Se ha **actualizado** un campo personalizado  |
| `customfield.deleted` | Se ha **eliminado** un campo personalizado    |

### Usos compartidos

| Evento          | Descripción                     |
| --------------- | ------------------------------- |
| `share.created` | Se ha **creado** un nuevo Share |
| `share.updated` | Se ha **actualizado** un Share  |
| `share.deleted` | Se ha **eliminado** un Share    |
| `share.viewed`  | Se ha **visualizado** un Share  |

## Carga útil de mensajes de webhook

Todas las cargas útiles de webhook contienen un campo `type`, que indica el evento que se ha producido, y un objeto `resource`. El objeto `resource` contiene el `tipo` y el `ID` del recurso de Frame.io relacionado con el evento.

### Ejemplo de carga útil

```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"
  }
}
```

En el ejemplo anterior de un evento `file.created`, `resource.id` indica el `ID` del File recién creado. Además, se incluyen los objetos `workspace`, `project` y `user`, que contienen los valores relacionados `workspace.id`, `project.id` y `user.id`. Estos valores se pueden usar para reducir las llamadas de API mediante el filtrado de eventos entrantes o la búsqueda local de datos almacenados en caché.

> **Warning**
>
> **No incluimos información adicional sobre el recurso suscrito aparte del ID del recurso**.
>
> Si la aplicación requiere información o contexto adicional, recomendamos realizar una llamada de API para buscar más información sobre los recursos a los que se hace referencia.

## Seguridad

De forma predeterminada, todos los webhooks tienen una clave de firma. Este secreto de firma no configurable se puede usar para verificar que la solicitud procede de Frame.io.

La carga útil de respuesta del webhook configurado incluye el secreto de firma específico de este webhook. Este secreto **solo se proporciona en la respuesta inicial de creación del webhook**, así que almacénelo en un lugar seguro, como el almacenamiento de secretos o las variables de entorno. Úselo más adelante para verificar que el webhook procede directamente de nuestros servidores y que no se ha interceptado ni manipulado de ningún modo.

### Verificación de firmas de webhook

Para proteger una integración contra ataques de intermediario y de repetición, es esencial verificar la firma de la carga útil del webhook. La verificación garantiza que las cargas útiles de webhook las haya enviado realmente Frame.io y que el contenido no se haya modificado durante el transporte.

La solicitud `POST` incluye los siguientes encabezados HTTP:

| Nombre de encabezado                          | Descripción                                           | Ejemplo                                                               |
| --------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------------------- |
| `X-Frameio-Request-Timestamp`                 | Marca de tiempo en que se envió la solicitud          | `1604004499`                                                          |
| `X-Frameio-Signature`                         | Firma de webhook calculada                            | `v0=a77ce6856e609c884575c2fd211d07a9ad1c3f72e19c06ff710e8f086ffca883` |
| `user-agent: &quot;Frame.io V4 API&quot;`     | Agente de usuario en el encabezado de V4              |                                                                       |
| `user-agent: &quot;Frame.io Legacy API&quot;` | Agente de usuario en el encabezado de la API heredada |                                                                       |

**`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 marca de tiempo** es la hora del sistema de Frame.io cuando se envía el webhook saliente. Puede usarse para evitar ataques de [reproducción](https://en.wikipedia.org/wiki/Replay_attack). Recomendamos verificar que esta hora esté dentro de un intervalo de 5 minutos con respecto a la hora local. **La firma** es un hash HMAC SHA-256 que usa la clave de firma proporcionada al crear el Webhook por primera vez. **Siga estos pasos para verificar la firma:**

#### Extracción de la firma

Extraiga la firma de los encabezados HTTP.

#### Creación del mensaje que se va a firmar

Cree un mensaje para firmarlo combinando la versión, la hora de entrega y el cuerpo de la solicitud: `v0:timestamp:body.`

#### Cálculo de HMAC SHA-256

Calcule la firma HMAC SHA-256 con el secreto de firma.

#### Comparación de firmas

Compare la firma calculada con la firma proporcionada.

> **Note**
>
> La firma proporcionada lleva el prefijo `v0=`. Actualmente, Frame.io solo tiene esta versión para firmar solicitudes. Asegúrese de añadir este prefijo al principio de la firma calculada.

## Reintentos y registro

#### Política de reintentos

* Cinco intentos en total (el inicial y 4 reintentos)

* Espera exponencial que comienza en 15 s, con variación aleatoria

* Un estado que no sea `2xx` o un tiempo de espera superior a 5 segundos activan el reintento

#### Registro de errores

Frame.io conserva un **registro de errores** con `webhook_id`, `account_id`, `event_type`, `resource_id` y `user_id`.

## Tutorial de webhooks

### Paso 1: Configuración del punto final receptor (se hace en primer lugar para saber cuál será la URL)

Aquí usamos [webhook.site](http://webhook.site/), que permite crear fácilmente un receptor de webhook de un solo uso para inspeccionar cargas útiles y enviar respuestas básicas sin ninguna lógica empresarial real. Al acceder por primera vez a [https://webhook.site](https://webhook.site/), se crea un punto final de webhook único que puede copiar de inmediato para usarlo.

Esta URL es exclusiva de la sesión.

![Ejemplo del paso 1](/_fern-files/frame-io.docs.buildwithfern.com/09ca9e64de4cd7b5b0982e6c2ae5f0978320cd11272b448b7f9f8c2aff1239ab/docs/pages/v4/guides/webhook_site_example.gif)

### Paso 2: Elección de los eventos a los que desea suscribirse

En este tutorial, mantendremos la configuración sencilla y haremos que este webhook se suscriba únicamente a eventos `file.created`. La carga útil JSON que usaremos para la creación del webhook será la siguiente.

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

### Paso 3: Creación de un recurso de webhook con Postman

Use Postman para realizar una llamada de API y crear el recurso de webhook, proporcionando el punto final de [webhook.site](http://webhook.site/) en la carga útil.

### Paso 4: Prueba

Ahora que ha creado la suscripción de webhook y tiene configurado un punto final para recibir webhooks, es el momento de probarlo activando el primer webhook mediante la acción correspondiente.

Dado que el ejemplo se ha configurado para activarse con el activador `file.created`, cargaremos un activo nuevo en cualquier Project de la Account y el Workspace correspondientes en los que se haya configurado el webhook.

![Ejemplo del paso 4](/_fern-files/frame-io.docs.buildwithfern.com/7503b906ce873425c6477487378fe9c513d5cbddc524754f0e1fe8ba10de5c16/docs/pages/v4/guides/trigger_asset_created_webhook.gif)

## Recursos adicionales

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

**Ngrok** es una herramienta excelente para desarrolladores que trabajan con webhooks que deben exponerse en una URL de acceso público. Crea túneles seguros desde el entorno local hacia Internet, lo que permite exponer el servidor local para recibir cargas útiles de webhook en tiempo real.

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

**Hookdeck** es una plataforma diseñada para ayudar a los equipos a gestionar webhooks de forma fiable mediante una puerta de enlace de eventos robusta. Centraliza la gestión de webhooks, garantiza que no se pierda ningún evento y ofrece funciones como filtrado, cola y reintento de webhooks fallidos.

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

**Webhook.site** es una herramienta extraordinaria para crear prototipos y probar webhooks. Ofrece una plataforma sencilla y eficaz para capturar e inspeccionar solicitudes HTTP enviadas a URL únicas generadas automáticamente.

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

**Val.town** es una herramienta excelente para crear rápidamente prototipos de controladores de webhook, ya que simplifica el proceso de escribir, probar e implementar pequeñas funciones de JavaScript y Python directamente desde el explorador.