> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://help.fotostudio.io/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# Webhook in uscita

I webhook ti permettono di connettere Fotostudio a strumenti esterni come **Make**, **Zapier**, **n8n** o il tuo backend. Ad ogni evento importante (nuovo contatto, fattura pagata, contratto firmato...), Fotostudio invia automaticamente i dati verso l'URL che hai scelto.

---

## Configurare un webhook

Vai su **Moduli → Webhook in uscita** e clicca su **Nuovo webhook**.

Compila i seguenti campi:

| Campo | Descrizione |
| ---- |
| **Etichetta** | Un nome per riconoscerlo (es. "Make – fatture") |
| **URL di destinazione** | L'URL HTTPS fornito dal tuo strumento (Make, Zapier...) |
| **Eventi** | Gli eventi da monitorare (puoi selezionarne più di uno) |

Un **secret** viene generato automaticamente alla creazione. Copialo subito: non verrà più mostrato in seguito. Serve a verificare che le chiamate provengano da Fotostudio.

---

## Eventi disponibili

| Evento | Si attiva quando... |
| ---- |
| `contact.created` | Viene creato un nuovo contatto |
| `contact.updated` | Un contatto viene modificato (dati, info...) |
| `project.created` | Viene creata una nuova sessione |
| `project.status_changed` | Lo stato di una sessione cambia |
| `project.confirmed` | Una sessione viene confermata |
| `invoice.created` | Viene creata una fattura |
| `invoice.paid` | Una fattura viene segnata come pagata |
| `payment.created` | Un pagamento viene registrato |
| `estimate.accepted` | Un preventivo viene accettato dal cliente |
| `estimate.refused` | Un preventivo viene rifiutato dal cliente |
| `contract.signed` | Un contratto viene firmato |

---

## Formato dei dati inviati

Ogni chiamata è un `POST` in JSON con la seguente struttura:

```json
{
  "event": "invoice.paid",
  "timestamp": "2026-06-12T10:30:00Z",
  "data": {
    ...
  }
}
```

### Header HTTP

| Header | Valore |
| ---- |
| `Content-Type` | `application/json` |
| `X-FS-Event` | Nome dell'evento (es. `invoice.paid`) |
| `X-FS-Signature` | `sha256=<hmac>` (firma HMAC-SHA256 del body) |
| `X-FS-Delivery-Id` | Identificatore univoco della consegna |

### Verificare la firma

La firma in `X-FS-Signature` viene calcolata così:

```
HMAC-SHA256(secret, body_json)
```

In Node.js ad esempio:

```js
const crypto = require('crypto')
const sig = 'sha256=' + crypto.createHmac('sha256', SECRET).update(rawBody).digest('hex')
if (sig !== req.headers['x-fs-signature']) throw new Error('Firma non valida')
```

---

## Dettaglio dei dati per evento

### `contact.created` / `contact.updated`

```json
{
  "id": 123,
  "firstname": "Marie",
  "lastname": "Dupont",
  "email": "marie@example.com",
  "phone": "+33 6 12 34 56 78",
  "company": "Studio Photo",
  "street": "12 rue de la Paix",
  "zipcode": "75001",
  "city": "Paris",
  "country": "France",
  "created_at": "2026-01-15T09:00:00Z",
  "url": "https://www.fotostudio.io/app/contacts/123"
}
```

### `project.created` / `project.status_changed` / `project.confirmed`

```json
{
  "id": 456,
  "name": "Matrimonio Dupont",
  "start_time": "2026-07-20T14:00:00Z",
  "end_time": "2026-07-20T18:00:00Z",
  "project_type": "Matrimonio",
  "status": "Confermato",
  "validated": true,
  "location": "Château de Versailles",
  "contact_id": 123,
  "created_at": "2026-01-15T09:00:00Z",
  "url": "https://www.fotostudio.io/app/projects/456"
}
```

### `invoice.created` / `invoice.paid`

```json
{
  "id": 789,
  "numero": "F2026-042",
  "title": "Matrimonio Dupont",
  "invoice_date": "2026-06-01",
  "total_price": 1500.00,
  "amount_to_pay": 750.00,
  "paid": false,
  "draft": false,
  "contact_id": 123,
  "project_id": 456,
  "created_at": "2026-06-01T10:00:00Z",
  "url": "https://www.fotostudio.io/app/invoices/789"
}
```

> `amount_to_pay` è il saldo restante da pagare (totale - pagamenti già ricevuti).

### `payment.created`

```json
{
  "id": 101,
  "amount": 750.00,
  "payment_date": "2026-06-10",
  "payment_type": "Bonifico",
  "invoice_id": 789,
  "contact_id": 123,
  "created_at": "2026-06-10T14:00:00Z"
}
```

### `estimate.accepted` / `estimate.refused`

```json
{
  "id": 202,
  "numero": "D2026-018",
  "title": "Matrimonio Dupont",
  "total_price": 1500.00,
  "accepted": true,
  "refused": false,
  "accepted_at": "2026-06-05T16:00:00Z",
  "contact_id": 123,
  "project_id": 456,
  "created_at": "2026-05-20T09:00:00Z",
  "url": "https://www.fotostudio.io/app/estimates/202"
}
```

### `contract.signed`

```json
{
  "id": 303,
  "title": "Contratto Matrimonio Dupont",
  "signed_at": "2026-06-08T11:30:00Z",
  "project_id": 456,
  "contact_id": 123,
  "created_at": "2026-05-25T10:00:00Z",
  "url": "https://www.fotostudio.io/app/contracts/303"
}
```

---

## Cronologia delle consegne

Nella scheda di ogni webhook, la scheda **Log** mostra la cronologia delle chiamate con:

* data e ora
* evento scatenante
* stato (successo / errore)
* codice HTTP di risposta
* messaggio di errore in caso di fallimento

In caso di errore, Fotostudio **riprova automaticamente fino a 3 volte** con un ritardo esponenziale. Puoi anche rilanciare manualmente una chiamata dai log.

---

## Usare con Make

1. In Make, crea un nuovo scenario e aggiungi un modulo **Webhooks → Custom webhook**
2. Copia l'URL generato da Make
3. In Fotostudio, crea un webhook con questo URL e seleziona gli eventi desiderati
4. Scatena un evento di test da Fotostudio (crea un contatto, ad esempio)
5. Make riceve i dati. Puoi poi costruire la tua automazione

---

## Usare con Zapier

1. In Zapier, crea un nuovo Zap e scegli **Webhooks by Zapier → Catch Hook** come trigger
2. Copia l'URL fornito da Zapier
3. In Fotostudio, crea un webhook con questo URL
4. Scatena un evento di test. Zapier rileva automaticamente la struttura dei dati
5. Configura la tua azione (Google Sheets, Notion, Slack...)

---

## FAQ

**Cosa succede se il mio server non è disponibile?**
Fotostudio riprova 3 volte con un ritardo crescente. Dopo 3 tentativi, la consegna viene segnata come fallita ma rimane nei log. Puoi rilanciarla manualmente.

**Il mio webhook deve rispondere entro quanto tempo?**
Il tuo endpoint deve rispondere entro **10 secondi**. Oltre questo limite, la richiesta viene considerata fallita.

**Posso avere più webhook?**
Sì, puoi creare tutti i webhook che vuoi, ciascuno con i propri eventi e il proprio URL.

**Come disattivare temporaneamente un webhook?**
Nell'elenco, usa il pulsante di attivazione per abilitare o disabilitare un webhook senza eliminarlo.