> ## 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).

# Webhooks sortants

Les webhooks te permettent de connecter Fotostudio à des outils externes comme **Make**, **Zapier**, **n8n** ou ton propre backend. À chaque événement important (nouveau contact, facture payée, contrat signé...), Fotostudio envoie automatiquement les données vers l'URL de ton choix.

---

## Configurer un webhook

Rends-toi dans **Modules → Webhooks sortants** et clique sur **Nouveau webhook**.

Remplis les champs suivants :

| Champ | Description |
| ---- |
| **Label** | Un nom pour t'y retrouver (ex : "Make – factures") |
| **URL de destination** | L'URL HTTPS fournie par ton outil (Make, Zapier...) |
| **Événements** | Les événements à écouter (tu peux en cocher plusieurs) |

Un **secret** est généré automatiquement à la création. Copie-le immédiatement : il ne sera plus affiché ensuite. Il sert à vérifier que les appels viennent bien de Fotostudio.

---

## Événements disponibles

| Événement | Déclenché quand... |
| ---- |
| `contact.created` | Un nouveau contact est créé |
| `contact.updated` | Un contact est modifié (coordonnées, infos...) |
| `project.created` | Une nouvelle séance est créée |
| `project.status_changed` | Le statut d'une séance change |
| `project.confirmed` | Une séance est confirmée |
| `invoice.created` | Une facture est créée |
| `invoice.paid` | Une facture est marquée comme payée |
| `payment.created` | Un paiement est enregistré |
| `estimate.accepted` | Un devis est accepté par le client |
| `estimate.refused` | Un devis est refusé par le client |
| `contract.signed` | Un contrat est signé |

---

## Format des données envoyées

Chaque appel est un `POST` en JSON avec la structure suivante :

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

### En-têtes HTTP

| Header | Valeur |
| ---- |
| `Content-Type` | `application/json` |
| `X-FS-Event` | Nom de l'événement (ex : `invoice.paid`) |
| `X-FS-Signature` | `sha256=<hmac>` (signature HMAC-SHA256 du body) |
| `X-FS-Delivery-Id` | Identifiant unique de la livraison |

### Vérifier la signature

La signature dans `X-FS-Signature` est calculée ainsi :

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

En Node.js par exemple :

```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('Signature invalide')
```

---

## Détail des données par événement

### `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": "Mariage Dupont",
  "start_time": "2026-07-20T14:00:00Z",
  "end_time": "2026-07-20T18:00:00Z",
  "project_type": "Mariage",
  "status": "Confirmé",
  "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": "Mariage 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` est le solde restant à payer (total - paiements déjà reçus).

### `payment.created`

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

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

```json
{
  "id": 202,
  "numero": "D2026-018",
  "title": "Mariage 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": "Contrat Mariage 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"
}
```

---

## Historique des livraisons

Dans la fiche de chaque webhook, l'onglet **Logs** affiche l'historique des appels avec :

* la date et l'heure
* l'événement déclenché
* le statut (succès / échec)
* le code HTTP de réponse
* le message d'erreur en cas d'échec

En cas d'échec, Fotostudio **réessaie automatiquement jusqu'à 3 fois** avec un délai exponentiel. Tu peux aussi relancer manuellement un appel depuis les logs.

---

## Utiliser avec Make

1. Dans Make, crée un nouveau scénario et ajoute un module **Webhooks → Custom webhook**
2. Copie l'URL générée par Make
3. Dans Fotostudio, crée un webhook avec cette URL et sélectionne les événements souhaités
4. Déclenche un événement test depuis Fotostudio (crée un contact, par exemple)
5. Make reçoit les données. Tu peux ensuite construire ton automatisation

---

## Utiliser avec Zapier

1. Dans Zapier, crée un nouveau Zap et choisis **Webhooks by Zapier → Catch Hook** comme déclencheur
2. Copie l'URL fournie par Zapier
3. Dans Fotostudio, crée un webhook avec cette URL
4. Déclenche un événement test. Zapier détecte automatiquement la structure des données
5. Configure ton action (Google Sheets, Notion, Slack...)

---

## FAQ

**Que se passe-t-il si mon serveur est indisponible ?**
Fotostudio réessaie 3 fois avec un délai croissant. Après 3 tentatives, la livraison est marquée en échec mais reste dans les logs. Tu peux la relancer manuellement.

**Mon webhook doit-il répondre en moins de combien de temps ?**
Ton endpoint doit répondre dans les **10 secondes**. Au-delà, la requête est considérée comme en échec.

**Puis-je avoir plusieurs webhooks ?**
Oui, tu peux créer autant de webhooks que tu veux, chacun avec ses propres événements et son URL.

**Comment désactiver temporairement un webhook ?**
Dans la liste, utilise le bouton de bascule pour activer ou désactiver un webhook sans le supprimer.
