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

# Webhook V4

## Cos'è un webhook?

Un **webhook** è un callback HTTP in stile push che Frame.io attiva **non appena accade qualcosa di interessante** nel tuo account, ad esempio quando un nuovo file completa la transcodifica, quando viene aggiunto un commento o quando viene creato un progetto.

Invece di interrogare l'API, fornisci un URL HTTPS pubblico; Frame.io invia un payload JSON a quell'URL in tempo reale così puoi:

#### Sincronizzare i metadati con un DAM/MAM esterno

#### Popolare i canali Slack o i sistemi di ticketing

Per ulteriori informazioni su cosa sia un webhook e cosa faccia, consulta [https://docs.webhook.site/](https://docs.webhook.site/).

## Panoramica degli endpoint

| **Operazione**                                   | **Endpoint**                                                          | **Dettagli**                                                   |
| ------------------------------------------------ | --------------------------------------------------------------------- | -------------------------------------------------------------- |
| **Crea** un webhook                              | POST /v4/accounts/\{account\_id}/workspaces/\{workspace\_id}/webhooks | Corpo con `name`, `URL`, `events[]`                            |
| **Elenca** tutti i webhook per un'area di lavoro | GET /v4/accounts/\{account\_id}/workspaces/\{workspace\_id}/webhooks  | Supporta la paginazione                                        |
| **Mostra** un webhook                            | GET /v4/webhooks/\{webhook\_id}                                       | Restituisce il secret di firma solo al momento della creazione |
| **Aggiorna** un webhook                          | PATCH /v4/webhooks/\{webhook\_id}                                     | Cambia `URL`, `eventi` o `is_active`                           |
| **Elimina** un webhook                           | DELETE /v4/webhooks/\{webhook\_id}                                    | Arresta immediatamente le consegne                             |

> **Warning**
>
> **Autenticazione**: tutti gli endpoint V4 richiedono un token di accesso OAuth 2.0 ottenuto tramite Adobe Developer Console. I token sviluppatore legacy e i JWT **non** vengono accettati.

## Cambiamenti e aggiornamenti in Frame V4

> **Info**
>
> I webhook creati nella versione legacy vengono trasferiti in V4 con i seguenti cambiamenti:
>
> 1. **Struttura del payload**: l'ID account è stato aggiunto al payload
> 2. **Cambiamenti degli endpoint**: il `team_id` non viene più fornito nel payload JSON, ma si trova invece nel parametro del percorso dell'URL: `https://api.frame.io/v4/accounts/:account_id/workspaces/:workspace_id/webhooks`
> 3. **Integrazione API**: a causa dei cambiamenti a struttura dell'API, endpoint e metodi di autenticazione, è necessario aggiornare qualsiasi codice esistente per i webhook in entrata che effettua chiamate successive all'API Frame.io per l'arricchimento e la ricerca delle risorse
> 4. **Tipi di eventi**: i webhook delle risorse sono stati suddivisi in eventi di file e cartelle separati. Tutti i webhook provenienti dalla versione legacy con eventi di risorse devono essere aggiornati in modo da avere gli eventi di file e cartelle appropriati

> **Warning**
>
> **Stato dei webhook dopo la migrazione**: quando il tuo account viene migrato a Frame.io V4, i webhook esistenti delle versioni precedenti vengono automaticamente disabilitati. In questo modo puoi modificare gli endpoint dei webhook e la logica di integrazione in modo che funzionino con gli aggiornamenti di V4 prima di riattivarli. I webhook che non sono stati aggiornati in modo da essere compatibili con V4 avranno degli errori se vengono abilitati senza le modifiche appropriate. Puoi verificare quali webhook sono inattivi esaminando il campo `is_active` tramite l'API o rivedendo le [impostazioni dei webhook](https://next.frame.io/settings/webhooks) prima di riattivarli.

## Sottoscrizioni agli eventi webhook

Durante la creazione e l'aggiornamento dei webhook devi identificare gli eventi che ti interessano. Scegli quanti ne desideri. Tieni presente che l'esperienza è migliore se sottoscrivi meno eventi, suddividendo logicamente i tuoi webhook con diversi schemi di denominazione e diversi endpoint in modo da poter modellare la logica di business sul lato ricevente per eseguire meno operazioni di filtro e instradamento nelle funzioni condivise.

> **Note**
>
> Ambito degli eventi: tutti gli eventi sono limitati all'area di lavoro fornita durante la creazione del webhook. Questo significa che gli eventi verranno inviati per le azioni intraprese in tutti i progetti in quella area di lavoro.

### Progetti

| Evento            | Descrizione                                              |
| ----------------- | -------------------------------------------------------- |
| `project.created` | Un nuovo progetto è stato **creato**                     |
| `project.updated` | Le impostazioni di un progetto sono state **aggiornate** |
| `project.deleted` | Un progetto è stato **eliminato**                        |

### File

| Evento                  | Descrizione                                                                                                                                                                                                                |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `file.created`          | Un file è stato **creato** in Frame.io. *Nota:* questo si attiva prima che il file finisca di caricarsi. Se il tuo gestore ha bisogno del file completo, consigliamo di rimanere in ascolto dell'evento `upload.completed` |
| `file.ready`            | Tutte le transcodifiche sono state **completate**, dopo che un file è stato caricato ed elaborato                                                                                                                          |
| `file.updated`          | C'è stata una modifica al nome di un file o ad altre informazioni                                                                                                                                                          |
| `file.deleted`          | Un file è stato **eliminato** (manualmente o in altro modo)                                                                                                                                                                |
| `file.upload.completed` | Un file è stato **caricato**                                                                                                                                                                                               |
| `file.versioned`        | È stata **creata** una versione del file                                                                                                                                                                                   |

### Cartelle

| Evento           | Descrizione                                               |
| ---------------- | --------------------------------------------------------- |
| `folder.created` | È stata **creata** una nuova cartella                     |
| `folder.updated` | Le impostazioni di una cartella sono state **aggiornate** |
| `folder.deleted` | Una cartella è stata **eliminata**                        |

### Commenti

| Evento                | Descrizione                                                |
| --------------------- | ---------------------------------------------------------- |
| `comment.created`     | Una nuova risposta o un nuovo commento è stato **creato**  |
| `comment.updated`     | Un commento è stato aggiornato                             |
| `comment.deleted`     | Un commento è stato **eliminato**                          |
| `comment.completed`   | Un commento è stato contrassegnato come **completato**     |
| `comment.uncompleted` | Un commento è stato contrassegnato come **non completato** |

### Metadati

| Evento                   | Descrizione                                   |
| ------------------------ | --------------------------------------------- |
| `metadata.value.updated` | Campi dei metadati aggiornati per una risorsa |

### Raccolte

| Evento               | Descrizione                           |
| -------------------- | ------------------------------------- |
| `collection.created` | Una nuova raccolta è stata **creata** |
| `collection.updated` | Una raccolta è stata **aggiornata**   |
| `collection.deleted` | Una raccolta è stata **eliminata**    |

### Campi personalizzati

| Evento                | Descrizione                                      |
| --------------------- | ------------------------------------------------ |
| `customfield.created` | Un nuovo campo personalizzato è stato **creato** |
| `customfield.updated` | Un campo personalizzato è stato **aggiornato**   |
| `customfield.deleted` | Un campo personalizzato è stato **eliminato**    |

### Condivisioni

| Evento          | Descrizione                               |
| --------------- | ----------------------------------------- |
| `share.created` | Una nuova condivisione è stata **creata** |
| `share.updated` | Una condivisione è stata **aggiornata**   |
| `share.deleted` | Una condivisione è stata **eliminata**    |
| `share.viewed`  | Una condivisione è stata **visualizzata** |

## Payload del messaggio webhook

Tutti i payload dei webhook contengono un campo `type`, che indica l'evento che si è verificato, nonché un oggetto `resource`. L'oggetto `resource` contiene il `type` e l'`ID` della risorsa Frame.io correlata all'evento.

### Payload di esempio

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

Nell'esempio precedente di un evento `file.created`, il `resource.id` indica l'`ID` del file appena creato. Inoltre, sono inclusi gli oggetti `workspace`, `project` e `user`, che contengono i relativi `workspace.id`, `project.id` e `user.id`. Questi valori possono essere utilizzati per ridurre le chiamate API filtrando gli eventi in arrivo o cercando i dati memorizzati in cache localmente.

> **Warning**
>
> **Non includiamo informazioni aggiuntive oltre all'ID della risorsa sottoscritta**.
>
> Se la tua applicazione richiede più informazioni o contesto, consigliamo di effettuare una chiamata API per cercare maggiori informazioni sulle risorse a cui si fa riferimento.

## Sicurezza

Per impostazione predefinita, tutti i webhook hanno una chiave di firma. Questo secret di firma non configurabile può essere utilizzato per verificare che la richiesta provenga da Frame.io.

Il payload di risposta per il webhook che hai configurato include il secret di firma specifico per questo webhook. Questo secret viene **fornito solo in questa risposta iniziale di creazione del webhook**, quindi conservalo in un luogo sicuro nell'archivio dei secret o nelle variabili d'ambiente. Utilizzalo in seguito per verificare che il webhook provenga direttamente dai nostri server e non sia stato intercettato o manipolato in alcun modo.

### Verifica delle firme dei webhook

Per proteggere un'integrazione da attacchi man-in-the-middle e replay, è essenziale verificare la firma del payload del webhook. La verifica garantisce che i payload dei webhook siano stati effettivamente inviati da Frame.io e che il contenuto del payload non sia stato modificato durante il trasporto.

Nella richiesta `POST` sono incluse le seguenti intestazioni HTTP:

| Nome intestazione                             | Descrizione                                         | Esempio                                                               |
| --------------------------------------------- | --------------------------------------------------- | --------------------------------------------------------------------- |
| `X-Frameio-Request-Timestamp`                 | La marca temporale dell'invio della richiesta       | `1604004499`                                                          |
| `X-Frameio-Signature`                         | La firma del webhook calcolata                      | `v0=a77ce6856e609c884575c2fd211d07a9ad1c3f72e19c06ff710e8f086ffca883` |
| `user-agent: &quot;Frame.io V4 API&quot;`     | User agent nell'intestazione per V4                 |                                                                       |
| `user-agent: &quot;Frame.io Legacy API&quot;` | User agent nell'intestazione per la versione legacy |                                                                       |

**`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 temporale** è l'ora dei sistemi Frame.io quando viene inviato il webhook in uscita. Può essere utilizzata per prevenire attacchi di tipo [replay](https://en.wikipedia.org/wiki/Replay_attack). Si consiglia di verificare che questo orario rientri nei 5 minuti dall'orario locale. **La firma** è un hash HMAC SHA256 che utilizza la chiave di firma fornita quando il webhook viene creato per la prima volta. **Segui questi passaggi per verificare la firma:**

#### Estrai la firma

Estrai la firma dalle intestazioni HTTP.

#### Crea un messaggio da firmare

Crea un messaggio da firmare combinando la versione, l'ora di consegna e il corpo della richiesta: `v0:timestamp:body.`

#### Calcola HMAC SHA256

Calcola la firma HMAC SHA256 utilizzando il secret di firma.

#### Confronta le firme

Confronta la firma calcolata con quella fornita.

> **Note**
>
> La firma fornita ha il prefisso `v0=`. Al momento Frame.io ha solo questa versione per firmare le richieste. Assicurati che questo prefisso venga anteposto alla firma calcolata.

## Nuovi tentativi e registrazione

#### Criterio per nuovo tentativo

* Cinque tentativi totali (iniziale + 4 nuovi tentativi)

* Back-off esponenziale che inizia a 15 s (+ jitter)

* Uno stato non `2xx` o un timeout >5 secondi attiva il nuovo tentativo

#### Registrazione degli errori

Frame.io gestisce un **registro degli errori** con: `webhook_id`, `account_id`, `event_type`, `resource_id`, `user_id`.

## Esercitazione sui webhook

### Passaggio 1: configura l'endpoint ricevente (da fare per primo in modo da conoscere quale sarà l'URL)

Qui stiamo usando [webhook.site](http://webhook.site/) che consente di creare facilmente un ricevitore del webhook monouso da utilizzare per ispezionare i payload, inviando risposte di base senza alcuna logica di business. Quando vai per la prima volta in [https://webhook.site](https://webhook.site/), viene creato un endpoint di webhook unico che puoi copiare immediatamente per l'uso.

Questo URL è unico per la sessione.

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

### Passaggio 2: scegli l'evento (o gli eventi) da sottoscrivere

Per questa esercitazione, punteremo alla semplicità e configureremo questo webhook in modo da sottoscrivere solo eventi `file.created`. Il payload JSON che useremo per la creazione del webhook sarà il seguente.

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

### Passaggio 3: crea una risorsa webhook usando Postman

Usa Postman per effettuare una chiamata API al fine di creare la risorsa webhook, fornendo l'endpoint [webhook.site](http://webhook.site/) nel payload.

### Passaggio 4: test

Dopo aver creato la sottoscrizione del webhook e configurato un endpoint per ricevere i webhook, è il momento di testarlo attivando il primo webhook ed eseguendo l'azione appropriata che lo farebbe attivare.

Poiché il nostro esempio è stato configurato per attivarsi con il trigger `file.created`, procederemo caricando una nuova risorsa in qualsiasi progetto all'interno dell'account e dell'area di lavoro corrispondenti in cui è stato configurato il webhook.

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

## Risorse aggiuntive

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

**Ngrok** è uno strumento fantastico per gli sviluppatori che lavorano con webhook che devono essere esposti su un URL accessibile pubblicamente. Permette di creare tunnel sicuri dal tuo ambiente locale a Internet e di esporre il tuo server locale in modo da ricevere i payload dei webhook in tempo reale.

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

**Hookdeck** è una piattaforma progettata per aiutare i team a gestire i webhook in modo affidabile grazie a un gateway degli eventi molto affidabile. Centralizza la gestione dei webhook, assicurando che nessun evento venga perso. Inoltre, offre funzionalità come filtri, accodamento e nuovi tentativi per i webhook non riusciti.

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

**Webhook.site** è uno strumento molto efficace per la prototipazione e il test dei webhook. È una piattaforma semplice, ma potente, che permette di acquisire e ispezionare le richieste HTTP inviate a URL unici generati automaticamente.

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

**Val.town** è uno strumento eccellente per la prototipazione rapida di gestori di webhook perché semplifica il processo di scrittura, test e distribuzione di piccole funzioni JavaScript e Python direttamente dal browser.