> For the complete documentation index, see [llms.txt](https://guides.data.gouv.fr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://guides.data.gouv.fr/passe-marche/docs/07_webhooks.md).

# Webhooks - Notifications en Temps Réel

## Vue d'ensemble

Les webhooks Passe Marché permettent aux plateformes de marchés publics de recevoir des notifications en temps réel lors d'événements importants (complétion de marchés, finalisation de candidatures). Ce système garantit une synchronisation fiable et automatique entre Passe Marché et les plateformes éditrices.

## Environnements

Les URLs dans les payloads webhook (ex : `attestation_url`) correspondent à l'environnement source. Consultez la [documentation des environnements](/passe-marche/docs/08_environnements.md) pour les URLs spécifiques.

## Architecture des Webhooks

```
┌─────────────────┐    Événement     ┌─────────────────┐
│   Passe Marché  │    Métier        │   File d'Attente│
│   Application   │ ─────────────────▶│   Webhooks      │
└─────────────────┘                  └─────────────────┘
                                              │
┌─────────────────┐    HTTP POST      ┌─────────────────┐
│   Plateforme    │ ◄────────────────── │   Processeur    │
│   Éditeur       │   + Signature HMAC │   Webhook       │
└─────────────────┘                  └─────────────────┘
                                              │
┌─────────────────┐    Retry          ┌─────────────────┐
│   Gestion       │ ◄────────────────── │   Gestionnaire  │
│   d'Erreurs     │                   │   d'Erreurs     │
└─────────────────┘                  └─────────────────┘
```

## Configuration des Webhooks

### Configuration Plateforme de Marchés Publics

Les webhooks sont configurés par l'administrateur Passe Marché au niveau de chaque plateforme de marchés publics.

### Paramètres de Configuration

| Paramètre                | Description                                              | Exemple                                    |
| ------------------------ | -------------------------------------------------------- | ------------------------------------------ |
| `completion_webhook_url` | URL de réception des webhooks                            | `https://editeur.com/webhooks/passemarche` |
| `buyer_return_url`       | URL de redirection post-complétion pour le flux acheteur | `https://editeur.com/callback/buyer`       |
| `candidate_return_url`   | URL de redirection post-complétion pour le flux candidat | `https://editeur.com/callback/candidate`   |
| `webhook_secret`         | Secret HMAC généré automatiquement                       | `a1b2c3d4e5f6...`                          |

### Paramètres de Redirection

Lors de la redirection vers l'URL configurée, Passe Marché ajoute automatiquement les paramètres suivants :

| Flux     | URL configurée         | Paramètres ajoutés                            |
| -------- | ---------------------- | --------------------------------------------- |
| Acheteur | `buyer_return_url`     | `market_identifier`                           |
| Candidat | `candidate_return_url` | `market_identifier`, `application_identifier` |

Exemple :

Si les URLs de redirection configurées sont :

```
buyer_return_url : https://editeur.com/callback/buyer
candidate_return_url : https://editeur.com/callback/candidate
```

L'utilisateur sera redirigé vers :

```
# Flux acheteur (buyer_return_url)
https://editeur.com/callback/buyer?market_identifier=VR-2024-A1B2C3D4E5F6

# Flux candidat (candidate_return_url)
https://editeur.com/callback/candidate?market_identifier=VR-2024-A1B2C3D4E5F6&application_identifier=VR-2024-TEST00000001
```

Les paramètres existants dans l'URL sont préservés.

## Types d'Événements

### Événement : Marché Complété

**Type** : `market.completed`

**Déclencheur** : Finalisation de la configuration d'un marché public par l'acheteur

**Payload** :

```json
{
  "event": "market.completed",
  "timestamp": "2024-06-15T14:30:45.123Z",
  "market": {
    "identifier": "VR-2024-A1B2C3D4E5F6",
    "name": "Fourniture de matériel informatique",
    "lots": [
      {
        "id": 42,
        "name": "Lot 1 - Ordinateurs portables",
        "cpv_code": "30213100-6",
        "market_type_code": "supplies"
      }
    ],
    "market_type_codes": ["supplies", "services"],
    "completed_at": "2024-06-15T14:30:45.123Z",
    "field_keys": [
      "company_name",
      "siret",
      "legal_form",
      "turnover_year_n_minus_1",
      "turnover_year_n_minus_2",
      "turnover_year_n_minus_3",
      "employee_count",
      "certifications_iso"
    ],
    "configuration_summary_url": "${BASE_URL}/api/v1/public_markets/VR-2024-A1B2C3D4E5F6/configuration_summary"
  }
}
```

### Événement : Candidature Finalisée

**Type** : `market_application.completed`

**Déclencheur** : Soumission finale d'une candidature par une entreprise

**Payload** :

```json
{
  "event": "market_application.completed",
  "timestamp": "2024-06-15T16:45:30.456Z",
  "market_identifier": "VR-2024-A1B2C3D4E5F6",
  "market_application": {
    "identifier": "FT20240615A1B2C3D4",
    "siret": "12345678901234",
    "attestation_url": "${BASE_URL}/api/v1/market_applications/FT20240615A1B2C3D4/attestation",
    "documents_package_url": "${BASE_URL}/api/v1/market_applications/FT20240615A1B2C3D4/documents_package"
  }
}
```

## Format des Requêtes Webhook

### En-têtes HTTP

```http
POST /webhooks/passemarche HTTP/1.1
Host: votre-editeur.com
Content-Type: application/json
X-Webhook-Signature-SHA256: sha256=a1b2c3d4e5f6789...
User-Agent: PasseMarche-Webhook/1.0
Content-Length: 1245
```

### Corps de la Requête

Le corps contient le payload JSON sérialisé de l'événement.

## Sécurité : Signatures HMAC

### Génération de la Signature

Chaque webhook inclut une signature HMAC-SHA256 calculée avec le secret de l'éditeur :

```
signature = HMAC-SHA256(webhook_secret, json_payload)
header_value = "sha256=" + hex(signature)
```

### Vérification Côté Récepteur

**Processus de vérification** :

1. Extraire la signature de l'en-tête `X-Webhook-Signature-SHA256`
2. Calculer la signature attendue avec HMAC-SHA256(secret, payload)
3. Comparer les signatures de manière sécurisée
4. Traiter l'événement uniquement si la signature est valide

**🔗 Scripts complets** :

* [Vérification signature HMAC (Bash)](https://guides.data.gouv.fr/passe-marche/docs/pages/KQbuhDbhm0LJC96OrqVi#vérification-signature-hmac-bash)
* [Serveur webhook complet (Node.js)](/passe-marche/docs/99_scripts_reference.md#serveur-webhook-minimal-nodejs)

## Mécanisme de Retry et Gestion d'Erreurs

### Stratégie de Retry

Passe Marché implémente un système de retry basé sur ActiveJob :

**Configuration par défaut** :

* **Tentatives** : 3 essais maximum
* **Délais** : Backoff polynomial croissant (`polynomially_longer`, quelques secondes puis dizaines de secondes)
* **Timeout** : 30 secondes par tentative

### Codes de Réponse et Actions

| Code HTTP                         | Type           | Action Passe Marché    | Description                       |
| --------------------------------- | -------------- | ---------------------- | --------------------------------- |
| 200-299                           | Succès         | ✅ Marquer comme traité | Webhook délivré avec succès       |
| 400, 401, 403, 404, 405, 410, 422 | Erreur client  | ❌ Pas de retry         | Erreur configuration côté éditeur |
| 408, 429                          | Temporaire     | 🔄 Retry avec délai    | Timeout ou rate limiting          |
| 500-599                           | Erreur serveur | 🔄 Retry selon config  | Problème temporaire côté éditeur  |
| Timeout réseau                    | Réseau         | 🔄 Retry selon config  | Problème de connectivité          |

### États de Synchronisation

| État              | Description                 | Interface Admin            |
| ----------------- | --------------------------- | -------------------------- |
| `sync_pending`    | En attente de traitement    | 🕐 En attente              |
| `sync_processing` | Webhook en cours d'envoi    | 📤 Envoi en cours          |
| `sync_completed`  | Webhook délivré avec succès | ✅ Synchronisé              |
| `sync_failed`     | Tous les retries échoués    | ❌ Échec - Retry disponible |

## Gestion de l'Idempotence

### Problématique

Un même webhook peut être reçu plusieurs fois en cas de :

* Retry automatique après timeout
* Problème réseau temporaire
* Redémarrage du processus de livraison

### Solution Recommandée

**Générer un ID unique** pour chaque événement :

```
event_id = event_type + timestamp + object_identifier
```

**Stratégies de déduplication** :

* Cache mémoire pour développement/test
* Redis/Memcached pour production
* Table de base de données avec TTL

**🔗 Implémentations complètes** : [Scripts de Référence - Serveur webhook](/passe-marche/docs/99_scripts_reference.md#serveur-webhook-minimal-nodejs)

## Monitoring et Métriques

### Métriques Recommandées

* **Taux de succès** des webhooks
* **Temps de traitement** moyen
* **Doublons détectés**
* **Erreurs par type**
* **Webhook en échec** nécessitant attention

### Endpoints de Monitoring

Exposez un endpoint `/webhooks/stats` pour surveiller :

* Nombre total de webhooks reçus/traités
* Taux de succès en pourcentage
* Temps de réponse moyens
* Distribution des erreurs

Cette documentation webhook fournit les éléments nécessaires pour une intégration robuste et sécurisée des notifications en temps réel avec Passe Marché.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://guides.data.gouv.fr/passe-marche/docs/07_webhooks.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
