> 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/03_flux_acheteur.md).

# Flux Acheteur - Configuration des Marchés Publics

## Vue d'ensemble

Le flux acheteur dans Passe Marché permet aux plateformes de marchés publics de créer et configurer des marchés publics via API, puis de rediriger les acheteurs vers une interface dédiée pour finaliser la configuration. Ce processus garantit une expérience utilisateur optimale tout en maintenant le contrôle technique via API.

## Environnements

Les exemples de ce document utilisent `${BASE_URL}` comme placeholder. Consultez la [documentation des environnements](/passe-marche/docs/08_environnements.md) pour les URLs spécifiques à chaque environnement.

## Architecture du Flux

```
┌─────────────────┐    1. Authentification   ┌─────────────────┐
│   Plateforme    │ ────────────────────────▶│   Passe Marché  │
│   Éditeur       │◄──────────────────────── │   API OAuth     │
└─────────────────┘    2. Token d'accès      └─────────────────┘

┌─────────────────┐    3. Création marché    ┌─────────────────┐
│   Plateforme    │ ────────────────────────▶│   Passe Marché  │
│   Éditeur       │◄──────────────────────── │   API           │
└─────────────────┘    4. URL config         └─────────────────┘

┌─────────────────┐    5. Redirection        ┌─────────────────┐
│   Acheteur      │ ────────────────────────▶│   Interface     │
│   Public        │◄──────────────────────── │   Configuration │
└─────────────────┘    6. Configuration      └─────────────────┘

┌─────────────────┐    7. Notification       ┌─────────────────┐
│   Plateforme    │ ◄────────────────────────│   Webhook       │
│   Éditeur       │                          │   Complétion    │
└─────────────────┘                          └─────────────────┘
┌─────────────────┐    8. Publication        ┌─────────────────┐
│   Plateforme    │ ────────────────────────▶│   Passe Marché  │
│   Éditeur       │◄──────────────────────── │   API           │
└─────────────────┘    9. Verrouillage       └─────────────────┘
```

## Étapes Détaillées du Flux

### 1. Authentification OAuth

**Prérequis** : Token d'accès valide obtenu via le flux OAuth2 Client Credentials.

Consultez la [Documentation OAuth](/passe-marche/docs/02_authentification_oauth.md) pour les détails d'implémentation.

### 2. Création du Marché Public

#### Endpoint

`POST /api/v1/public_markets`

#### Requête

```http
POST /api/v1/public_markets HTTP/1.1
Host: ${BASE_URL}
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "public_market": {
    "name": "Fourniture de matériel informatique pour les services municipaux",
    "lots": [
      {"name": "Lot 1 - Ordinateurs portables et stations de travail", "cpv_code": "30213100-6", "lot_type_code": "supplies"},
      {"name": "Lot 2 - Serveurs et infrastructure réseau", "lot_type_code": "services"}
    ],
    "deadline": "2024-06-15T23:59:59Z",
    "siret": "13002526500013",
    "market_type_codes": ["supplies", "services"]
  }
}
```

#### Paramètres Requis

| Champ               | Type     | Description                                                         | Contraintes                                       |
| ------------------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------- |
| `name`              | string   | Nom du marché public                                                | Requis, max 255 caractères                        |
| `deadline`          | datetime | Date limite de candidature                                          | Requis, format ISO 8601                           |
| `siret`             | string   | SIRET de l'organisation publique                                    | Requis, exactement 14 chiffres, validation Luhn   |
| `market_type_codes` | array    | Types de marché                                                     | Requis, minimum 1 élément                         |
| `lots`              | array    | Liste des lots du marché                                            | Optionnel, chaque lot requiert un `name`          |
| `provider_user_id`  | string   | Identifiant de l'utilisateur côté éditeur (acheteur)                | Optionnel, max 255 caractères                     |
| `lot_limit`         | integer  | Nombre maximum de lots pour lesquels une entreprise peut candidater | Optionnel, ne peut pas dépasser le nombre de lots |

**Propriétés d'un lot**

| Champ           | Type   | Requis | Description           | Contraintes                                                                        |
| --------------- | ------ | ------ | --------------------- | ---------------------------------------------------------------------------------- |
| `name`          | string | Oui    | Nom du lot            | Max 255 caractères                                                                 |
| `cpv_code`      | string | Non    | Code CPV du lot       | Format `XXXXXXXX-X` (8 chiffres, tiret, 1 chiffre)                                 |
| `lot_type_code` | string | Non    | Type de marché du lot | `supplies`, `services`, `works` — si absent, hérite du premier `market_type_codes` |

#### Codes de Types de Marché

| Code       | Description | Utilisation                              |
| ---------- | ----------- | ---------------------------------------- |
| `supplies` | Fournitures | Biens matériels, consommables            |
| `services` | Services    | Prestations intellectuelles, maintenance |
| `works`    | Travaux     | Construction, rénovation, BTP            |
| `defense`  | Défense     | Marchés liés à la défense nationale      |

**Note** : Le type `defense` ne peut pas être utilisé seul et doit être combiné avec un autre type.

#### Réponse de Succès (201 Created)

```json
{
  "identifier": "VR-2024-A1B2C3D4E5F6",
  "configuration_url": "${BASE_URL}/buyer/public_markets/VR-2024-A1B2C3D4E5F6/setup"
}
```

**Paramètres de Réponse** :

* `identifier` : Identifiant unique du marché (format VR-YYYY-XXXXXXXXXXXX)
* `configuration_url` : URL vers l'interface de configuration

#### Réponses d'Erreur

**Paramètres manquants (422)** :

```json
{
  "errors": {
    "name": ["Le nom du marché ne peut pas être vide"],
    "deadline": ["La date limite ne peut pas être vide"],
    "market_type_codes": ["Les types de marché ne peuvent pas être vides"]
  }
}
```

**Types de marché invalides (422)** :

```json
{
  "errors": {
    "market_type_codes": ["Le marché de défense ne peut pas être le seul type sélectionné"]
  }
}
```

**Éditeur non autorisé (403)** :

```json
{
  "error": "Forbidden"
}
```

### 3. Interface de Configuration

Une fois le marché créé, la plateforme de marchés publics redirige l'acheteur vers l'URL fournie dans la réponse. L'interface de configuration suit un processus en 4 étapes :

#### Étape 1 : Setup Initial

* **URL** : `/buyer/public_markets/{identifier}/setup`
* **Objectif** : Configuration initiale et validation des informations
* **Actions** :
  * Vérification de l'identifiant marché
  * Ajout optionnel du type "defense" si pertinent
  * Affichage des informations de base du marché (incluant le SIRET de l'organisation publique)

**Note** : Le SIRET de l'organisation publique est requis pour la conformité avec l'API Entreprise

#### Étape 1b : Configuration des types de lots (marché hétérogène)

Pour les marchés comportant plusieurs lots, l'acheteur peut affiner le type de marché par lot via l'interface. L'éditeur peut aussi pré-renseigner un type par lot à la création (champ `market_type_code` non supporté côté API — le type par lot est défini uniquement via l'interface acheteur).

**Endpoint de modification des types de lots**

`PATCH /buyer/public_markets/{identifier}/lots`

| Paramètre        | Type    | Description                              |
| ---------------- | ------- | ---------------------------------------- |
| `market_type_id` | integer | ID interne du type de marché à appliquer |
| `lot_ids[]`      | array   | IDs des lots à modifier                  |

**Comportement** :

* Si le type sélectionné est identique au `platform_market_type` du lot (type transmis par l'éditeur à la création), l'override est annulé et le lot reprend le type de la plateforme.
* Chaque lot conserve deux types distincts : `platform_market_type` (source éditeur, non modifiable) et `market_type` (override acheteur, optionnel).
* Le type effectif (`effective_market_type`) est `market_type` s'il est défini, sinon `platform_market_type`.

#### Étape 2 : Champs Obligatoires

* **URL** : `/buyer/public_markets/{identifier}/required_fields`
* **Objectif** : Sélection et configuration des champs obligatoires
* **Logique** :
  * Génération automatique des champs selon les types de marché
  * Prise en compte du contexte défense/civil
  * Groupement par catégories et sous-catégories

#### Étape 3 : Champs Optionnels

* **URL** : `/buyer/public_markets/{identifier}/additional_fields`
* **Objectif** : Sélection des champs optionnels complémentaires
* **Fonctionnalités** :
  * Filtrage des champs selon la configuration existante
  * Organisation par domaines métier
  * Aperçu des champs sélectionnés

#### Étape 4 : Résumé et Finalisation

* **URL** : `/buyer/public_markets/{identifier}/summary`
* **Objectif** : Validation finale et complétion du marché
* **Actions** :
  * Affichage de tous les champs configurés
  * Confirmation de la configuration
  * Déclenchement du processus de complétion

### 4. Processus de Complétion

#### Finalisation Automatique

Lorsque l'acheteur confirme la configuration à l'étape "Résumé" :

1. **Marquage comme complété** : Le marché passe en statut `completed`
2. **Génération de l'identifiant** : Attribution d'un identifiant unique stable
3. **Sauvegarde de la configuration** : Snapshot des champs sélectionnés
4. **Initialisation du webhook** : Préparation de la notification

#### Statuts de Synchronisation

| Statut            | Description              | Action                          |
| ----------------- | ------------------------ | ------------------------------- |
| `sync_pending`    | En attente de traitement | Webhook en file d'attente       |
| `sync_processing` | Traitement en cours      | Webhook en cours d'envoi        |
| `sync_completed`  | Synchronisation réussie  | Webhook délivré avec succès     |
| `sync_failed`     | Échec de synchronisation | Webhook échoué, retry programmé |

### 5. Webhook de Complétion

#### Déclenchement

Le webhook est automatiquement déclenché lors de la finalisation du marché et envoyé à l'URL configurée pour votre éditeur.

#### Payload du Webhook

```json
{
  "event": "market.completed",
  "timestamp": "2024-06-15T14:30:45Z",
  "market": {
    "identifier": "VR-2024-A1B2C3D4E5F6",
    "name": "Fourniture de matériel informatique pour les services municipaux",
    "lots": [
      {"id": 1, "name": "Lot 1 - Ordinateurs portables et stations de travail", "cpv_code": "30213100-6", "market_type_code": "supplies"},
      {"id": 2, "name": "Lot 2 - Serveurs et infrastructure réseau", "market_type_code": "services"}
    ],
    "market_type_codes": ["supplies", "services"],
    "completed_at": "2024-06-15T14:30:45Z",
    "field_keys": [
      "company_name",
      "siret",
      "legal_form",
      "turnover_year_n_minus_1",
      "employee_count",
      "certifications_iso"
    ],
    "configuration_summary_url": "${BASE_URL}/api/v1/public_markets/VR-2024-A1B2C3D4E5F6/configuration_summary"
  }
}
```

#### Paramètres du Payload

| Champ                              | Description                                                                                                                                   |
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `event`                            | Type d'événement (`market.completed`)                                                                                                         |
| `timestamp`                        | Horodatage ISO 8601 de l'événement                                                                                                            |
| `market.identifier`                | Identifiant unique du marché                                                                                                                  |
| `market.lots`                      | Liste des lots triés par position (`id`, `name`, `cpv_code`, `market_type_code`) — `cpv_code` et `market_type_code` absents si non renseignés |
| `market.field_keys`                | Liste des clés des champs configurés                                                                                                          |
| `market.completed_at`              | Date/heure de complétion                                                                                                                      |
| `market.configuration_summary_url` | URL de téléchargement du PDF de synthèse de configuration, absente si le PDF n'est pas (encore) disponible                                    |

#### Sécurité du Webhook

Chaque webhook inclut une signature HMAC-SHA256 dans l'en-tête `X-Webhook-Signature-SHA256`.

Consultez la [Documentation Webhooks](https://github.com/datagouv/guides.data.gouv.fr/tree/main/passemarche/docs/WEBHOOKS.md) pour les détails de vérification.

### 6. Publication du Marché

#### **Modification de la Configuration avant Publication**

Tant que la consultation n'a pas été publiée par l'éditeur, l'acheteur peut modifier la configuration du marché en ré-accédant au wizard via l'URL de configuration. Chaque re-soumission :

1. **Met à jour `completed_at`** avec un nouveau timestamp
2. **Réinitialise `sync_status`** à `sync_pending`
3. **Déclenche un nouveau webhook** vers l'éditeur avec la configuration mise à jour

#### **Endpoint de Publication**

`POST /api/v1/public_markets/{identifier}/publish`

L'éditeur appelle cet endpoint lorsque la consultation est publiée sur sa plateforme. Cela verrouille définitivement la configuration du marché, à l'exception de la DLRO qui reste modifiable via `PATCH /api/v1/public_markets/{identifier}` même après publication.

#### **Pré-conditions** :

* Le marché doit être configuré (`completed_at` présent)
* Le marché ne doit pas déjà être publié

#### **Réponse de Succès (200)** :

```json
{
  "identifier": "VR-2024-A1B2C3D4E5F6",
  "published_at": "2024-06-15T14:30:45Z"
}
```

Consultez la Référence API pour les détails complets.

#### **Effet du Verrouillage**

Après publication, l'acheteur qui tente d'accéder au wizard est redirigé vers une page « Configuration verrouillée » (`/buyer/public_markets/{identifier}/published`) qui l'informe que la consultation a été publiée et qu'il ne peut plus modifier la configuration.

> **Exception — DLRO** : la date limite de remise des offres reste modifiable après publication. L'éditeur peut appeler `PATCH /api/v1/public_markets/{identifier}` à tout moment pour mettre à jour la `deadline`, indépendamment de l'état de publication.

## Gestion des Erreurs et Edge Cases

### Marché Déjà Publié

Si un utilisateur tente d'accéder à un marché déjà publié :

* Redirection vers la page "Configuration verrouillée"
* Explication que la consultation a été publiée
* Lien de retour vers la plateforme de marché

### Session Expirée

* Sauvegarde automatique de la progression
* Possibilité de reprendre à l'étape interrompue
* Conservation des données pendant 24h

### Erreurs de Validation

* Messages d'erreur contextuels par champ
* Préservation des données saisies
* Indication claire des corrections requises

## Surveillance et Monitoring

### Métriques Clés

* **Taux de conversion** : Marchés créés vs complétés
* **Temps de configuration** : Durée moyenne par étape
* **Taux d'abandon** : Abandons par étape
* **Succès webhook** : Pourcentage de webhooks délivrés

### Logs Recommandés

**Éléments à logger** :

* Création de marchés (nom, identifiant, statut HTTP)
* Webhooks reçus (événement, identifiant marché, nombre de champs)
* Erreurs d'API (codes HTTP, messages d'erreur)
* Temps de réponse des appels API

**Format recommandé** : JSON structuré avec timestamps ISO pour faciliter l'analyse.

**🔗 Scripts de logging** : [Scripts de Référence - Logging et monitoring](/passe-marche/docs/99_scripts_reference.md#logging-et-monitoring)

## Interface de Retry

En cas d'échec de synchronisation, une interface de retry est disponible :

### Endpoint de Retry

`POST /buyer/public_markets/{identifier}/retry_sync`

### Conditions d'Utilisation

* Marché en statut `sync_failed`
* Éditeur autorisé pour ce marché
* Limite : 3 tentatives par heure

## Bonnes Pratiques d'Intégration

### Côté Éditeur

1. **Validation Préalable** : Vérifier les données avant envoi API
2. **Gestion d'État** : Suivre le statut des marchés créés
3. **Webhook Robuste** : Implémenter une réception idempotente
4. **Monitoring** : Surveiller les taux de succès et les erreurs
5. **UX Cohérente** : Intégrer harmonieusement la redirection

### Scripts d'Automatisation

**Fonctionnalités disponibles** :

* Gestionnaire complet de marchés (création, listing, détails)
* Validation automatique des données
* Cache local des marchés créés
* Test de webhooks avec signature HMAC
* Gestion d'erreurs et retry intelligent
* Statistiques et monitoring

**🔗 Scripts complets** : [Scripts de Référence - Gestionnaire de marchés](https://guides.data.gouv.fr/passe-marche/docs/pages/KQbuhDbhm0LJC96OrqVi#gestionnaire-de-marchés---script-complet)

Ce flux acheteur garantit une expérience optimale tout en maintenant le contrôle technique et la traçabilité nécessaires pour les marchés publics.


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://guides.data.gouv.fr/passe-marche/docs/03_flux_acheteur.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
