{
  "openapi": "3.0.3",
  "info": {
    "title": "Commerce 360 — API externe V1",
    "version": "1.0.0",
    "description": "API destinée aux canaux externes de Commerce 360.\n\nToutes les routes métier utilisent des identifiants publics et un jeton JWT. Les paramètres inconnus sont refusés. Les listes sont paginées et les relations coûteuses sont généralement activées avec `include`.\n\nPour les écritures financières et les transactions, `Idempotency-Key` est obligatoire. Une clé ne doit être réutilisée qu’avec un identifiant de ressource et un corps strictement identiques."
  },
  "components": {
    "schemas": {
      "ApiError": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "message"
        ],
        "properties": {
          "statusCode": {
            "type": "integer",
            "description": "Code de statut HTTP.",
            "example": 400
          },
          "code": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ],
            "description": "Code stable lorsque l’erreur provient de l’API métier."
          },
          "error": {
            "type": "string",
            "description": "Libellé HTTP générique."
          },
          "message": {
            "type": "string",
            "description": "Message explicatif. Les erreurs métier commencent par leur code stable."
          }
        }
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Jeton obtenu par `POST /auth`. Saisir uniquement le jeton dans la fenêtre Authorize."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Requête invalide : paramètre, entête ou corps non conforme.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "statusCode": 400,
              "code": "INVALID_REQUEST",
              "error": "Request Error",
              "message": "INVALID_REQUEST: Requête invalide : paramètre, entête ou corps non conforme."
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Jeton absent, expiré, invalide ou identité technique inexploitable.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "statusCode": 401,
              "code": "UNAUTHORIZED",
              "error": "Request Error",
              "message": "UNAUTHORIZED: Jeton absent, expiré, invalide ou identité technique inexploitable."
            }
          }
        }
      },
      "Forbidden": {
        "description": "Le compte authentifié ne possède pas toutes les permissions nécessaires.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "statusCode": 403,
              "code": "FORBIDDEN",
              "error": "Request Error",
              "message": "FORBIDDEN: Le compte authentifié ne possède pas toutes les permissions nécessaires."
            }
          }
        }
      },
      "NotFound": {
        "description": "La ressource publique demandée est inconnue ou hors périmètre.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "statusCode": 404,
              "code": "RESOURCE_NOT_FOUND",
              "error": "Request Error",
              "message": "RESOURCE_NOT_FOUND: La ressource publique demandée est inconnue ou hors périmètre."
            }
          }
        }
      },
      "Conflict": {
        "description": "Une règle métier, financière, de disponibilité ou d’idempotence refuse l’opération.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "statusCode": 409,
              "code": "CONFLICT",
              "error": "Request Error",
              "message": "CONFLICT: Une règle métier, financière, de disponibilité ou d’idempotence refuse l’opération."
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Limite de requêtes atteinte. Réessayer après la fenêtre indiquée par le serveur.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "statusCode": 429,
              "code": "RATE_LIMITED",
              "error": "Request Error",
              "message": "RATE_LIMITED: Limite de requêtes atteinte. Réessayer après la fenêtre indiquée par le serveur."
            }
          }
        }
      },
      "InternalServerError": {
        "description": "Erreur interne inattendue. Conserver le contexte et l’identifiant de requête des journaux.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "statusCode": 500,
              "code": "INTERNAL_SERVER_ERROR",
              "error": "Internal Server Error",
              "message": "INTERNAL_SERVER_ERROR: Erreur interne inattendue. Conserver le contexte et l’identifiant de requête des journaux."
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "Service momentanément indisponible, notamment pendant une maintenance.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "statusCode": 503,
              "code": "SERVICE_UNAVAILABLE",
              "error": "Internal Server Error",
              "message": "SERVICE_UNAVAILABLE: Service momentanément indisponible, notamment pendant une maintenance."
            }
          }
        }
      }
    }
  },
  "paths": {
    "/v1/catalog/changes": {
      "get": {
        "summary": "Lire les changements incrémentaux du catalogue",
        "tags": [
          "Catalogue"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "in": "query",
            "name": "since",
            "required": true,
            "description": "Borne de début ISO 8601 incluse du flux incrémental.",
            "example": "2026-07-01T00:00:00.000Z"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "in": "query",
            "name": "until",
            "required": false,
            "description": "Borne de fin ISO 8601. La valeur retournée doit être conservée comme prochain point de reprise.",
            "example": "2026-07-19T12:00:00.000Z"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^(products|product-items|categories|characteristics|shops)(,(products|product-items|categories|characteristics|shops))*$"
            },
            "in": "query",
            "name": "types",
            "required": false,
            "description": "Types demandés, séparés par des virgules et sans espace."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "shopId",
            "required": false,
            "description": "Identifiant public de la boutique."
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "in": "query",
            "name": "page",
            "required": false,
            "description": "Numéro de page, à partir de 1.",
            "example": 1
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "in": "query",
            "name": "limit",
            "required": false,
            "description": "Nombre maximal de résultats retournés par page.",
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "Page ordonnée de changements avec la fenêtre réellement utilisée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "since",
                    "until",
                    "changes",
                    "pagination"
                  ],
                  "properties": {
                    "since": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "until": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "changes": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "type",
                          "id",
                          "action",
                          "updatedAt"
                        ],
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "product",
                              "product-item",
                              "category",
                              "characteristic",
                              "shop"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "description": "Identifiant public stable de la ressource."
                          },
                          "productId": {
                            "type": "string"
                          },
                          "action": {
                            "type": "string",
                            "enum": [
                              "created",
                              "updated",
                              "deleted",
                              "price_updated",
                              "stock_updated",
                              "visibility_updated",
                              "media_updated"
                            ]
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "Date de dernière modification au format ISO 8601."
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "page",
                        "limit",
                        "total",
                        "hasNextPage"
                      ],
                      "properties": {
                        "page": {
                          "type": "integer",
                          "description": "Numéro de la page courante."
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Taille maximale de la page."
                        },
                        "total": {
                          "type": "integer",
                          "description": "Nombre total d’éléments correspondant aux filtres."
                        },
                        "hasNextPage": {
                          "type": "boolean",
                          "description": "Indique si une page suivante existe."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listCatalogChanges",
        "description": "Retourne les entités du catalogue créées, modifiées ou supprimées dans une fenêtre temporelle. Le consommateur doit paginer jusqu’à `hasNextPage=false` en conservant la même borne `until`, puis utiliser cette borne comme prochain point de reprise.\n\n**Permissions obligatoires (toutes)** : `products:read`, `stock:read`, `referentials:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "products:read",
            "stock:read",
            "referentials:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/catalog/products": {
      "get": {
        "summary": "Lister le catalogue produits complet",
        "tags": [
          "Catalogue"
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "in": "query",
            "name": "page",
            "required": false,
            "description": "Numéro de page, à partir de 1.",
            "example": 1
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 50
            },
            "in": "query",
            "name": "limit",
            "required": false,
            "description": "Nombre maximal de résultats retournés par page.",
            "example": 50
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "in": "query",
            "name": "updatedSince",
            "required": false,
            "description": "Ne retourne que les données modifiées depuis cet instant ISO 8601.",
            "example": "2026-07-01T00:00:00.000Z"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "query",
            "name": "shopUuid",
            "required": false,
            "description": "Identifiant public de la boutique."
          },
          {
            "schema": {
              "type": "boolean",
              "default": false
            },
            "in": "query",
            "name": "availableOnly",
            "required": false,
            "description": "Si vrai, exclut les références ou articles sans stock disponible calculé.",
            "example": true
          },
          {
            "schema": {
              "type": "boolean",
              "default": true
            },
            "in": "query",
            "name": "displayedOnline",
            "required": false,
            "description": "Filtre sur l’indicateur de visibilité en ligne.",
            "example": true
          }
        ],
        "responses": {
          "200": {
            "description": "Page de produits et articles du catalogue, accompagnée des filtres appliqués.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "pagination",
                    "filters",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "reference",
                          "ean",
                          "name",
                          "description",
                          "displayedOnline",
                          "quantityType",
                          "category",
                          "priceRange",
                          "promotionPriceRange",
                          "availableItemsCount",
                          "stock",
                          "media",
                          "updatedAt",
                          "supplier",
                          "items"
                        ],
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "description": "Identifiant public stable de la ressource."
                          },
                          "reference": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "ean": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "name": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "description": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "displayedOnline": {
                            "type": "boolean"
                          },
                          "quantityType": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "category": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "code",
                              "label"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Identifiant public stable de la ressource."
                              },
                              "code": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "label": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              }
                            }
                          },
                          "priceRange": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "minInclTax",
                              "maxInclTax",
                              "currency"
                            ],
                            "properties": {
                              "minInclTax": {
                                "type": "number"
                              },
                              "maxInclTax": {
                                "type": "number"
                              },
                              "currency": {
                                "type": "string",
                                "enum": [
                                  "EUR"
                                ],
                                "description": "Devise monétaire ISO 4217.",
                                "example": "EUR"
                              }
                            }
                          },
                          "promotionPriceRange": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "minInclTax",
                              "maxInclTax",
                              "currency"
                            ],
                            "properties": {
                              "minInclTax": {
                                "type": "number"
                              },
                              "maxInclTax": {
                                "type": "number"
                              },
                              "currency": {
                                "type": "string",
                                "enum": [
                                  "EUR"
                                ],
                                "description": "Devise monétaire ISO 4217.",
                                "example": "EUR"
                              }
                            }
                          },
                          "availableItemsCount": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "stock": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "available",
                              "totalQuantity"
                            ],
                            "properties": {
                              "available": {
                                "type": "boolean",
                                "description": "Disponibilité résultant du calcul de stock Commerce 360."
                              },
                              "totalQuantity": {
                                "type": [
                                  "null",
                                  "integer"
                                ]
                              }
                            }
                          },
                          "media": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "type",
                                "url",
                                "isMain"
                              ],
                              "properties": {
                                "type": {
                                  "type": "string",
                                  "enum": [
                                    "image"
                                  ]
                                },
                                "url": {
                                  "type": "string"
                                },
                                "isMain": {
                                  "type": "boolean"
                                }
                              }
                            }
                          },
                          "updatedAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "description": "Date de dernière modification au format ISO 8601."
                          },
                          "supplier": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "name",
                              "shortName"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Identifiant public stable de la ressource."
                              },
                              "name": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "shortName": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              }
                            }
                          },
                          "items": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "uuid",
                                "code",
                                "price",
                                "promotionPrice",
                                "quantity",
                                "availability",
                                "shop",
                                "characteristics",
                                "inStockDate",
                                "updatedAt"
                              ],
                              "properties": {
                                "uuid": {
                                  "type": "string",
                                  "description": "Identifiant public stable de la ressource."
                                },
                                "code": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                },
                                "price": {
                                  "type": "object",
                                  "additionalProperties": false,
                                  "required": [
                                    "inclTax",
                                    "exclTax",
                                    "currency"
                                  ],
                                  "properties": {
                                    "inclTax": {
                                      "type": [
                                        "null",
                                        "number"
                                      ]
                                    },
                                    "exclTax": {
                                      "type": [
                                        "null",
                                        "number"
                                      ]
                                    },
                                    "currency": {
                                      "type": "string",
                                      "enum": [
                                        "EUR"
                                      ],
                                      "description": "Devise monétaire ISO 4217.",
                                      "example": "EUR"
                                    }
                                  },
                                  "description": "Prix de base faisant foi sur l’article."
                                },
                                "promotionPrice": {
                                  "type": [
                                    "null",
                                    "object"
                                  ],
                                  "additionalProperties": false,
                                  "required": [
                                    "inclTax",
                                    "exclTax",
                                    "currency"
                                  ],
                                  "properties": {
                                    "inclTax": {
                                      "type": [
                                        "null",
                                        "number"
                                      ]
                                    },
                                    "exclTax": {
                                      "type": [
                                        "null",
                                        "number"
                                      ]
                                    },
                                    "currency": {
                                      "type": "string",
                                      "enum": [
                                        "EUR"
                                      ],
                                      "description": "Devise monétaire ISO 4217.",
                                      "example": "EUR"
                                    }
                                  },
                                  "description": "Prix promotionnel distinct ; null lorsqu’aucune promotion ne s’applique."
                                },
                                "quantity": {
                                  "type": [
                                    "null",
                                    "integer"
                                  ]
                                },
                                "availability": {
                                  "type": "object",
                                  "additionalProperties": false,
                                  "required": [
                                    "available",
                                    "status",
                                    "reason"
                                  ],
                                  "properties": {
                                    "available": {
                                      "type": "boolean",
                                      "description": "Disponibilité résultant du calcul de stock Commerce 360."
                                    },
                                    "status": {
                                      "type": "string",
                                      "enum": [
                                        "available",
                                        "out_of_stock",
                                        "sold",
                                        "reserved",
                                        "withdrawn",
                                        "unsalable"
                                      ],
                                      "description": "Statut public normalisé."
                                    },
                                    "reason": {
                                      "type": [
                                        "null",
                                        "string"
                                      ]
                                    }
                                  }
                                },
                                "shop": {
                                  "type": [
                                    "null",
                                    "object"
                                  ],
                                  "additionalProperties": false,
                                  "required": [
                                    "id",
                                    "name",
                                    "shortName",
                                    "city"
                                  ],
                                  "properties": {
                                    "id": {
                                      "type": "string",
                                      "description": "Identifiant public stable de la ressource."
                                    },
                                    "name": {
                                      "type": [
                                        "null",
                                        "string"
                                      ]
                                    },
                                    "shortName": {
                                      "type": [
                                        "null",
                                        "string"
                                      ]
                                    },
                                    "city": {
                                      "type": [
                                        "null",
                                        "string"
                                      ]
                                    }
                                  },
                                  "description": "Identifiant public historique de la boutique."
                                },
                                "characteristics": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "additionalProperties": false,
                                    "required": [
                                      "code",
                                      "label",
                                      "value",
                                      "source"
                                    ],
                                    "properties": {
                                      "code": {
                                        "type": "string"
                                      },
                                      "label": {
                                        "type": "string"
                                      },
                                      "value": {
                                        "type": [
                                          "null",
                                          "string"
                                        ]
                                      },
                                      "source": {
                                        "type": "string",
                                        "enum": [
                                          "product",
                                          "item"
                                        ]
                                      }
                                    }
                                  }
                                },
                                "inStockDate": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                },
                                "updatedAt": {
                                  "type": [
                                    "null",
                                    "string"
                                  ],
                                  "description": "Date de dernière modification au format ISO 8601."
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "page",
                        "limit",
                        "count",
                        "total",
                        "totalPages",
                        "hasNextPage",
                        "hasPreviousPage",
                        "nextPage",
                        "previousPage"
                      ],
                      "properties": {
                        "page": {
                          "type": "integer",
                          "description": "Numéro de la page courante."
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Taille maximale de la page."
                        },
                        "count": {
                          "type": "integer",
                          "description": "Nombre d’éléments présents dans cette page."
                        },
                        "total": {
                          "type": "integer",
                          "description": "Nombre total d’éléments correspondant aux filtres."
                        },
                        "totalPages": {
                          "type": "integer",
                          "description": "Nombre total de pages."
                        },
                        "hasNextPage": {
                          "type": "boolean",
                          "description": "Indique si une page suivante existe."
                        },
                        "hasPreviousPage": {
                          "type": "boolean"
                        },
                        "nextPage": {
                          "type": [
                            "null",
                            "integer"
                          ]
                        },
                        "previousPage": {
                          "type": [
                            "null",
                            "integer"
                          ]
                        }
                      }
                    },
                    "filters": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "page",
                        "limit",
                        "updatedSince",
                        "shopUuid",
                        "availableOnly",
                        "displayedOnline"
                      ],
                      "properties": {
                        "page": {
                          "type": "integer",
                          "description": "Numéro de la page courante."
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Taille maximale de la page."
                        },
                        "updatedSince": {
                          "type": [
                            "null",
                            "string"
                          ]
                        },
                        "shopUuid": {
                          "type": [
                            "null",
                            "string"
                          ]
                        },
                        "availableOnly": {
                          "type": "boolean"
                        },
                        "displayedOnline": {
                          "type": "boolean"
                        }
                      }
                    },
                    "meta": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "generatedAt",
                        "currency",
                        "included"
                      ],
                      "properties": {
                        "generatedAt": {
                          "type": "string"
                        },
                        "currency": {
                          "type": "string",
                          "enum": [
                            "EUR"
                          ],
                          "description": "Devise monétaire ISO 4217.",
                          "example": "EUR"
                        },
                        "included": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listCatalogProducts",
        "description": "Retourne une vue paginée conçue pour alimenter un site marchand : références visibles, articles physiques, prix article, éventuel prix promotionnel et stock disponible calculé. `availableOnly=true` élimine les articles sans quantité disponible. Utiliser `updatedSince` pour limiter une resynchronisation.\n\n**Permissions obligatoires (toutes)** : `products:read`, `stock:read`, `referentials:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "products:read",
            "stock:read",
            "referentials:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/products": {
      "get": {
        "summary": "Lister les références produits",
        "tags": [
          "Produits"
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "in": "query",
            "name": "page",
            "required": false,
            "description": "Numéro de page, à partir de 1.",
            "example": 1
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 50
            },
            "in": "query",
            "name": "limit",
            "required": false,
            "description": "Nombre maximal de résultats retournés par page.",
            "example": 50
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 300
            },
            "in": "query",
            "name": "search",
            "required": false,
            "description": "Recherche textuelle normalisée sur les champs métier exposés.",
            "example": "martin"
          },
          {
            "schema": {
              "type": "boolean",
              "default": true
            },
            "in": "query",
            "name": "displayedOnline",
            "required": false,
            "description": "Filtre sur l’indicateur de visibilité en ligne.",
            "example": true
          },
          {
            "schema": {
              "type": "boolean",
              "default": false
            },
            "in": "query",
            "name": "availableOnly",
            "required": false,
            "description": "Si vrai, exclut les références ou articles sans stock disponible calculé.",
            "example": true
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "in": "query",
            "name": "updatedSince",
            "required": false,
            "description": "Ne retourne que les données modifiées depuis cet instant ISO 8601.",
            "example": "2026-07-01T00:00:00.000Z"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "supplierId",
            "required": false,
            "description": "Identifiant public du fournisseur."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "productTypeId",
            "required": false,
            "description": "Identifiant public du type produit."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "categoryId",
            "required": false,
            "description": "Identifiant public de la catégorie."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "shopId",
            "required": false,
            "description": "Identifiant public de la boutique."
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^(characteristics|media|stock|prices)(,(characteristics|media|stock|prices))*$"
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Relations optionnelles à inclure, séparées par des virgules et sans espace."
          }
        ],
        "responses": {
          "200": {
            "description": "Page de références produits correspondant aux filtres.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "reference",
                          "ean",
                          "name",
                          "description",
                          "displayedOnline",
                          "quantityType",
                          "category",
                          "productType",
                          "priceRange",
                          "promotionPriceRange",
                          "availableItemsCount",
                          "updatedAt"
                        ],
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "description": "Identifiant public stable de la ressource."
                          },
                          "reference": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "ean": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "name": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "description": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "displayedOnline": {
                            "type": "boolean"
                          },
                          "quantityType": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "category": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "code",
                              "label"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Identifiant public stable de la ressource."
                              },
                              "code": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "label": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              }
                            }
                          },
                          "productType": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "code",
                              "label"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Identifiant public stable de la ressource."
                              },
                              "code": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "label": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              }
                            }
                          },
                          "priceRange": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "minInclTax",
                              "maxInclTax",
                              "currency"
                            ],
                            "properties": {
                              "minInclTax": {
                                "type": "number"
                              },
                              "maxInclTax": {
                                "type": "number"
                              },
                              "currency": {
                                "type": "string",
                                "enum": [
                                  "EUR"
                                ],
                                "description": "Devise monétaire ISO 4217.",
                                "example": "EUR"
                              }
                            }
                          },
                          "promotionPriceRange": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "minInclTax",
                              "maxInclTax",
                              "currency"
                            ],
                            "properties": {
                              "minInclTax": {
                                "type": "number"
                              },
                              "maxInclTax": {
                                "type": "number"
                              },
                              "currency": {
                                "type": "string",
                                "enum": [
                                  "EUR"
                                ],
                                "description": "Devise monétaire ISO 4217.",
                                "example": "EUR"
                              }
                            }
                          },
                          "availableItemsCount": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "stock": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "available",
                              "totalQuantity"
                            ],
                            "properties": {
                              "available": {
                                "type": "boolean",
                                "description": "Disponibilité résultant du calcul de stock Commerce 360."
                              },
                              "totalQuantity": {
                                "type": [
                                  "null",
                                  "integer"
                                ]
                              }
                            }
                          },
                          "media": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "type",
                                "url",
                                "isMain"
                              ],
                              "properties": {
                                "type": {
                                  "type": "string",
                                  "enum": [
                                    "image"
                                  ]
                                },
                                "url": {
                                  "type": "string"
                                },
                                "isMain": {
                                  "type": "boolean"
                                }
                              }
                            }
                          },
                          "characteristics": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "code",
                                "label",
                                "value",
                                "source"
                              ],
                              "properties": {
                                "code": {
                                  "type": "string"
                                },
                                "label": {
                                  "type": "string"
                                },
                                "value": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                },
                                "source": {
                                  "type": "string",
                                  "enum": [
                                    "product"
                                  ]
                                }
                              }
                            }
                          },
                          "updatedAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "description": "Date de dernière modification au format ISO 8601."
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "page",
                        "limit",
                        "count",
                        "total",
                        "totalPages",
                        "hasNextPage"
                      ],
                      "properties": {
                        "page": {
                          "type": "integer",
                          "description": "Numéro de la page courante."
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Taille maximale de la page."
                        },
                        "count": {
                          "type": "integer",
                          "description": "Nombre d’éléments présents dans cette page."
                        },
                        "total": {
                          "type": "integer",
                          "description": "Nombre total d’éléments correspondant aux filtres."
                        },
                        "totalPages": {
                          "type": "integer",
                          "description": "Nombre total de pages."
                        },
                        "hasNextPage": {
                          "type": "boolean",
                          "description": "Indique si une page suivante existe."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listProducts",
        "description": "Recherche les références produit exposables en ligne avec pagination et filtres. Les relations volumineuses sont absentes par défaut et se demandent avec `include`. Les prix proviennent des articles Commerce 360 ; une promotion est exposée séparément du prix de base.\n\n**Permissions obligatoires (toutes)** : `products:read`.\n\n**Permissions conditionnelles** :\n- `stock:read` lorsque `availableOnly`, `shopId`, `include=stock` ou `include=items` nécessite le calcul de disponibilité.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "products:read"
          ],
          "anyOf": [],
          "conditional": [
            "`stock:read` lorsque `availableOnly`, `shopId`, `include=stock` ou `include=items` nécessite le calcul de disponibilité."
          ]
        }
      }
    },
    "/v1/products/{productId}": {
      "get": {
        "summary": "Consulter une référence produit",
        "tags": [
          "Produits"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^(characteristics|media|prices|stock|items)(,(characteristics|media|prices|stock|items))*$"
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Relations optionnelles à inclure, séparées par des virgules et sans espace."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "shopId",
            "required": false,
            "description": "Identifiant public de la boutique."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "path",
            "name": "productId",
            "required": true,
            "description": "Identifiant public stable de la référence produit.",
            "example": "product_01HZX8K5M6"
          }
        ],
        "responses": {
          "200": {
            "description": "Fiche publique de la référence produit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "uuid",
                    "reference",
                    "ean",
                    "name",
                    "description",
                    "displayedOnline",
                    "quantityType",
                    "discontinuation",
                    "alwaysSalable",
                    "neverSalable",
                    "unsalable",
                    "category",
                    "supplier",
                    "updatedAt"
                  ],
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "description": "Identifiant public stable de la ressource."
                    },
                    "reference": {
                      "type": [
                        "null",
                        "string"
                      ]
                    },
                    "ean": {
                      "type": [
                        "null",
                        "string"
                      ]
                    },
                    "name": {
                      "type": [
                        "null",
                        "string"
                      ]
                    },
                    "description": {
                      "type": [
                        "null",
                        "string"
                      ]
                    },
                    "displayedOnline": {
                      "type": "boolean"
                    },
                    "quantityType": {
                      "type": [
                        "null",
                        "string"
                      ]
                    },
                    "discontinuation": {
                      "type": "boolean"
                    },
                    "alwaysSalable": {
                      "type": "boolean"
                    },
                    "neverSalable": {
                      "type": "boolean"
                    },
                    "unsalable": {
                      "type": "boolean"
                    },
                    "category": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "code",
                        "label"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Identifiant public stable de la ressource."
                        },
                        "code": {
                          "type": [
                            "null",
                            "string"
                          ]
                        },
                        "label": {
                          "type": [
                            "null",
                            "string"
                          ]
                        }
                      }
                    },
                    "supplier": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "name",
                        "shortName"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Identifiant public stable de la ressource."
                        },
                        "name": {
                          "type": [
                            "null",
                            "string"
                          ]
                        },
                        "shortName": {
                          "type": [
                            "null",
                            "string"
                          ]
                        }
                      }
                    },
                    "price": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "advisedInclTax",
                        "currency"
                      ],
                      "properties": {
                        "advisedInclTax": {
                          "type": "number"
                        },
                        "currency": {
                          "type": "string",
                          "enum": [
                            "EUR"
                          ],
                          "description": "Devise monétaire ISO 4217.",
                          "example": "EUR"
                        }
                      },
                      "description": "Prix de base faisant foi sur l’article."
                    },
                    "promotionPrice": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "advisedInclTax",
                        "currency"
                      ],
                      "properties": {
                        "advisedInclTax": {
                          "type": "number"
                        },
                        "currency": {
                          "type": "string",
                          "enum": [
                            "EUR"
                          ],
                          "description": "Devise monétaire ISO 4217.",
                          "example": "EUR"
                        }
                      },
                      "description": "Prix promotionnel distinct ; null lorsqu’aucune promotion ne s’applique."
                    },
                    "priceRange": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "minInclTax",
                        "maxInclTax",
                        "currency"
                      ],
                      "properties": {
                        "minInclTax": {
                          "type": "number"
                        },
                        "maxInclTax": {
                          "type": "number"
                        },
                        "currency": {
                          "type": "string",
                          "enum": [
                            "EUR"
                          ],
                          "description": "Devise monétaire ISO 4217.",
                          "example": "EUR"
                        }
                      }
                    },
                    "promotionPriceRange": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "minInclTax",
                        "maxInclTax",
                        "currency"
                      ],
                      "properties": {
                        "minInclTax": {
                          "type": "number"
                        },
                        "maxInclTax": {
                          "type": "number"
                        },
                        "currency": {
                          "type": "string",
                          "enum": [
                            "EUR"
                          ],
                          "description": "Devise monétaire ISO 4217.",
                          "example": "EUR"
                        }
                      }
                    },
                    "stock": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "available",
                        "availableItemsCount",
                        "totalQuantity"
                      ],
                      "properties": {
                        "available": {
                          "type": "boolean",
                          "description": "Disponibilité résultant du calcul de stock Commerce 360."
                        },
                        "availableItemsCount": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "totalQuantity": {
                          "type": [
                            "null",
                            "integer"
                          ]
                        }
                      }
                    },
                    "characteristics": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "code",
                          "label",
                          "value",
                          "source"
                        ],
                        "properties": {
                          "code": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "value": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "product"
                            ]
                          }
                        }
                      }
                    },
                    "media": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "type",
                          "url",
                          "isMain"
                        ],
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "image"
                            ]
                          },
                          "url": {
                            "type": "string"
                          },
                          "isMain": {
                            "type": "boolean"
                          }
                        }
                      }
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "code",
                          "price",
                          "promotionPrice",
                          "quantity",
                          "availability",
                          "shop",
                          "characteristics",
                          "inStockDate",
                          "updatedAt"
                        ],
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "description": "Identifiant public stable de la ressource."
                          },
                          "code": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "price": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "inclTax",
                              "exclTax",
                              "currency"
                            ],
                            "properties": {
                              "inclTax": {
                                "type": [
                                  "null",
                                  "number"
                                ]
                              },
                              "exclTax": {
                                "type": [
                                  "null",
                                  "number"
                                ]
                              },
                              "currency": {
                                "type": "string",
                                "enum": [
                                  "EUR"
                                ],
                                "description": "Devise monétaire ISO 4217.",
                                "example": "EUR"
                              }
                            },
                            "description": "Prix de base faisant foi sur l’article."
                          },
                          "promotionPrice": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "inclTax",
                              "exclTax",
                              "currency"
                            ],
                            "properties": {
                              "inclTax": {
                                "type": [
                                  "null",
                                  "number"
                                ]
                              },
                              "exclTax": {
                                "type": [
                                  "null",
                                  "number"
                                ]
                              },
                              "currency": {
                                "type": "string",
                                "enum": [
                                  "EUR"
                                ],
                                "description": "Devise monétaire ISO 4217.",
                                "example": "EUR"
                              }
                            },
                            "description": "Prix promotionnel distinct ; null lorsqu’aucune promotion ne s’applique."
                          },
                          "quantity": {
                            "type": [
                              "null",
                              "integer"
                            ]
                          },
                          "availability": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "available",
                              "status",
                              "reason"
                            ],
                            "properties": {
                              "available": {
                                "type": "boolean",
                                "description": "Disponibilité résultant du calcul de stock Commerce 360."
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "available",
                                  "out_of_stock",
                                  "sold",
                                  "reserved",
                                  "withdrawn",
                                  "unsalable"
                                ],
                                "description": "Statut public normalisé."
                              },
                              "reason": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              }
                            }
                          },
                          "shop": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "name",
                              "shortName",
                              "city"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Identifiant public stable de la ressource."
                              },
                              "name": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "shortName": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "city": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              }
                            },
                            "description": "Identifiant public historique de la boutique."
                          },
                          "characteristics": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "code",
                                "label",
                                "value",
                                "source"
                              ],
                              "properties": {
                                "code": {
                                  "type": "string"
                                },
                                "label": {
                                  "type": "string"
                                },
                                "value": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                },
                                "source": {
                                  "type": "string",
                                  "enum": [
                                    "product",
                                    "item"
                                  ]
                                }
                              }
                            }
                          },
                          "inStockDate": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "updatedAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "description": "Date de dernière modification au format ISO 8601."
                          }
                        }
                      }
                    },
                    "updatedAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "description": "Date de dernière modification au format ISO 8601."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "getProduct",
        "description": "Retourne une référence produit publique. `include` permet d’ajouter caractéristiques, médias, prix, stock et articles. `shopId` limite les calculs et articles à une boutique précise.\n\n**Permissions obligatoires (toutes)** : `products:read`.\n\n**Permissions conditionnelles** :\n- `stock:read` lorsque `include` demande `stock` ou `items`, ou lorsqu’une boutique est utilisée pour un calcul de disponibilité.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "products:read"
          ],
          "anyOf": [],
          "conditional": [
            "`stock:read` lorsque `include` demande `stock` ou `items`, ou lorsqu’une boutique est utilisée pour un calcul de disponibilité."
          ]
        }
      }
    },
    "/v1/products/{productId}/items": {
      "get": {
        "summary": "Lister les articles physiques d’un produit",
        "tags": [
          "Produits"
        ],
        "parameters": [
          {
            "schema": {
              "type": "boolean",
              "default": true
            },
            "in": "query",
            "name": "availableOnly",
            "required": false,
            "description": "Si vrai, exclut les références ou articles sans stock disponible calculé.",
            "example": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "shopId",
            "required": false,
            "description": "Identifiant public de la boutique."
          },
          {
            "schema": {
              "type": "boolean"
            },
            "in": "query",
            "name": "hasPromotion",
            "required": false,
            "description": "Filtre sur la présence d’un prix promotionnel distinct du prix de base.",
            "example": true
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "in": "query",
            "name": "updatedSince",
            "required": false,
            "description": "Ne retourne que les données modifiées depuis cet instant ISO 8601.",
            "example": "2026-07-01T00:00:00.000Z"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^(characteristics|media|shop)(,(characteristics|media|shop))*$"
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Relations optionnelles à inclure, séparées par des virgules et sans espace."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "path",
            "name": "productId",
            "required": true,
            "description": "Identifiant public stable de la référence produit.",
            "example": "product_01HZX8K5M6"
          }
        ],
        "responses": {
          "200": {
            "description": "Articles physiques rattachés au produit.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "productId",
                          "code",
                          "serialNumber",
                          "reference",
                          "product",
                          "price",
                          "promotion",
                          "quantity",
                          "availability",
                          "inStockDate",
                          "updatedAt"
                        ],
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "description": "Identifiant public stable de la ressource."
                          },
                          "productId": {
                            "type": "string"
                          },
                          "code": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "serialNumber": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "reference": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "product": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "reference",
                              "ean",
                              "name",
                              "displayedOnline"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Identifiant public stable de la ressource."
                              },
                              "reference": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "ean": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "name": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "displayedOnline": {
                                "type": "boolean"
                              }
                            }
                          },
                          "price": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "inclTax",
                              "exclTax",
                              "currency"
                            ],
                            "properties": {
                              "inclTax": {
                                "type": [
                                  "null",
                                  "number"
                                ]
                              },
                              "exclTax": {
                                "type": [
                                  "null",
                                  "number"
                                ]
                              },
                              "currency": {
                                "type": "string",
                                "enum": [
                                  "EUR"
                                ],
                                "description": "Devise monétaire ISO 4217.",
                                "example": "EUR"
                              }
                            },
                            "description": "Prix de base faisant foi sur l’article."
                          },
                          "promotion": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "active",
                              "type",
                              "value",
                              "priceInclTax"
                            ],
                            "properties": {
                              "active": {
                                "type": "boolean"
                              },
                              "type": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "value": {
                                "type": [
                                  "null",
                                  "number"
                                ]
                              },
                              "priceInclTax": {
                                "type": [
                                  "null",
                                  "number"
                                ]
                              }
                            }
                          },
                          "quantity": {
                            "type": [
                              "null",
                              "integer"
                            ]
                          },
                          "availability": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "available",
                              "status",
                              "reason"
                            ],
                            "properties": {
                              "available": {
                                "type": "boolean",
                                "description": "Disponibilité résultant du calcul de stock Commerce 360."
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "available",
                                  "out_of_stock",
                                  "sold",
                                  "reserved",
                                  "withdrawn",
                                  "unsalable"
                                ],
                                "description": "Statut public normalisé."
                              },
                              "reason": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              }
                            }
                          },
                          "shop": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "name",
                              "shortName",
                              "city"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Identifiant public stable de la ressource."
                              },
                              "name": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "shortName": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "city": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              }
                            },
                            "description": "Identifiant public historique de la boutique."
                          },
                          "characteristics": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "code",
                                "label",
                                "value",
                                "source"
                              ],
                              "properties": {
                                "code": {
                                  "type": "string"
                                },
                                "label": {
                                  "type": "string"
                                },
                                "value": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                },
                                "source": {
                                  "type": "string",
                                  "enum": [
                                    "product",
                                    "item"
                                  ]
                                }
                              }
                            }
                          },
                          "media": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "type",
                                "url",
                                "isMain"
                              ],
                              "properties": {
                                "type": {
                                  "type": "string",
                                  "enum": [
                                    "image"
                                  ]
                                },
                                "url": {
                                  "type": "string"
                                },
                                "isMain": {
                                  "type": "boolean"
                                }
                              }
                            }
                          },
                          "inStockDate": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "updatedAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "description": "Date de dernière modification au format ISO 8601."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listProductItems",
        "description": "Retourne les articles physiques rattachés à une référence produit. La disponibilité repose sur le calcul natif de stock disponible, après prise en compte des sorties et engagements. Le prix de base reste présent et le prix promotionnel est fourni dans un champ distinct.\n\n**Permissions obligatoires (toutes)** : `products:read`, `stock:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "products:read",
            "stock:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/product-items": {
      "get": {
        "summary": "Lister les articles physiques",
        "tags": [
          "Produits"
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "in": "query",
            "name": "page",
            "required": false,
            "description": "Numéro de page, à partir de 1.",
            "example": 1
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 50
            },
            "in": "query",
            "name": "limit",
            "required": false,
            "description": "Nombre maximal de résultats retournés par page.",
            "example": 50
          },
          {
            "schema": {
              "type": "boolean",
              "default": true
            },
            "in": "query",
            "name": "availableOnly",
            "required": false,
            "description": "Si vrai, exclut les références ou articles sans stock disponible calculé.",
            "example": true
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "in": "query",
            "name": "updatedSince",
            "required": false,
            "description": "Ne retourne que les données modifiées depuis cet instant ISO 8601.",
            "example": "2026-07-01T00:00:00.000Z"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "productId",
            "required": false,
            "description": "Identifiant public stable de la référence produit.",
            "example": "product_01HZX8K5M6"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "shopId",
            "required": false,
            "description": "Identifiant public de la boutique."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "supplierId",
            "required": false,
            "description": "Identifiant public du fournisseur."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "productTypeId",
            "required": false,
            "description": "Identifiant public du type produit."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "categoryId",
            "required": false,
            "description": "Identifiant public de la catégorie."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 300
            },
            "in": "query",
            "name": "search",
            "required": false,
            "description": "Recherche textuelle normalisée sur les champs métier exposés.",
            "example": "martin"
          },
          {
            "schema": {
              "type": "number",
              "minimum": 0
            },
            "in": "query",
            "name": "priceMin",
            "required": false,
            "description": "Prix article minimum, toutes taxes comprises.",
            "example": 10
          },
          {
            "schema": {
              "type": "number",
              "minimum": 0
            },
            "in": "query",
            "name": "priceMax",
            "required": false,
            "description": "Prix article maximum, toutes taxes comprises.",
            "example": 500
          },
          {
            "schema": {
              "type": "boolean"
            },
            "in": "query",
            "name": "hasPromotion",
            "required": false,
            "description": "Filtre sur la présence d’un prix promotionnel distinct du prix de base.",
            "example": true
          },
          {
            "schema": {
              "type": "boolean"
            },
            "in": "query",
            "name": "isSecondHand",
            "required": false,
            "description": "Filtre les articles d’occasion.",
            "example": false
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^(product|characteristics|media|shop|category|supplier)(,(product|characteristics|media|shop|category|supplier))*$"
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Relations optionnelles à inclure, séparées par des virgules et sans espace."
          }
        ],
        "responses": {
          "200": {
            "description": "Page d’articles physiques correspondant aux filtres.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "productId",
                          "code",
                          "serialNumber",
                          "reference",
                          "price",
                          "promotion",
                          "quantity",
                          "availability",
                          "inStockDate",
                          "updatedAt"
                        ],
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "description": "Identifiant public stable de la ressource."
                          },
                          "productId": {
                            "type": "string"
                          },
                          "code": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "serialNumber": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "reference": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "product": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "reference",
                              "ean",
                              "name",
                              "displayedOnline"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Identifiant public stable de la ressource."
                              },
                              "reference": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "ean": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "name": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "displayedOnline": {
                                "type": "boolean"
                              }
                            }
                          },
                          "price": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "inclTax",
                              "exclTax",
                              "currency"
                            ],
                            "properties": {
                              "inclTax": {
                                "type": [
                                  "null",
                                  "number"
                                ]
                              },
                              "exclTax": {
                                "type": [
                                  "null",
                                  "number"
                                ]
                              },
                              "currency": {
                                "type": "string",
                                "enum": [
                                  "EUR"
                                ],
                                "description": "Devise monétaire ISO 4217.",
                                "example": "EUR"
                              }
                            },
                            "description": "Prix de base faisant foi sur l’article."
                          },
                          "promotion": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "active",
                              "type",
                              "value",
                              "priceInclTax"
                            ],
                            "properties": {
                              "active": {
                                "type": "boolean"
                              },
                              "type": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "value": {
                                "type": [
                                  "null",
                                  "number"
                                ]
                              },
                              "priceInclTax": {
                                "type": [
                                  "null",
                                  "number"
                                ]
                              }
                            }
                          },
                          "quantity": {
                            "type": [
                              "null",
                              "integer"
                            ]
                          },
                          "availability": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "available",
                              "status",
                              "reason"
                            ],
                            "properties": {
                              "available": {
                                "type": "boolean",
                                "description": "Disponibilité résultant du calcul de stock Commerce 360."
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "available",
                                  "out_of_stock",
                                  "sold",
                                  "reserved",
                                  "withdrawn",
                                  "unsalable"
                                ],
                                "description": "Statut public normalisé."
                              },
                              "reason": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              }
                            }
                          },
                          "shop": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "name",
                              "shortName",
                              "city"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Identifiant public stable de la ressource."
                              },
                              "name": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "shortName": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "city": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              }
                            },
                            "description": "Identifiant public historique de la boutique."
                          },
                          "characteristics": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "code",
                                "label",
                                "value",
                                "source"
                              ],
                              "properties": {
                                "code": {
                                  "type": "string"
                                },
                                "label": {
                                  "type": "string"
                                },
                                "value": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                },
                                "source": {
                                  "type": "string",
                                  "enum": [
                                    "product",
                                    "item"
                                  ]
                                }
                              }
                            }
                          },
                          "media": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "type",
                                "url",
                                "isMain"
                              ],
                              "properties": {
                                "type": {
                                  "type": "string",
                                  "enum": [
                                    "image"
                                  ]
                                },
                                "url": {
                                  "type": "string"
                                },
                                "isMain": {
                                  "type": "boolean"
                                }
                              }
                            }
                          },
                          "inStockDate": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "updatedAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "description": "Date de dernière modification au format ISO 8601."
                          },
                          "category": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "code",
                              "label"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Identifiant public stable de la ressource."
                              },
                              "code": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "label": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              }
                            }
                          },
                          "supplier": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "name",
                              "shortName"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Identifiant public stable de la ressource."
                              },
                              "name": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              },
                              "shortName": {
                                "type": [
                                  "null",
                                  "string"
                                ]
                              }
                            }
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "page",
                        "limit",
                        "count",
                        "total",
                        "totalPages",
                        "hasNextPage"
                      ],
                      "properties": {
                        "page": {
                          "type": "integer",
                          "description": "Numéro de la page courante."
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Taille maximale de la page."
                        },
                        "count": {
                          "type": "integer",
                          "description": "Nombre d’éléments présents dans cette page."
                        },
                        "total": {
                          "type": "integer",
                          "description": "Nombre total d’éléments correspondant aux filtres."
                        },
                        "totalPages": {
                          "type": "integer",
                          "description": "Nombre total de pages."
                        },
                        "hasNextPage": {
                          "type": "boolean",
                          "description": "Indique si une page suivante existe."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listProductItemsGlobally",
        "description": "Recherche paginée dans tous les articles physiques vendables. Les filtres de prix utilisent le prix article Commerce 360. `hasPromotion` cible les articles ayant un prix promotionnel distinct et `availableOnly` s’appuie sur le stock disponible calculé.\n\n**Permissions obligatoires (toutes)** : `products:read`, `stock:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "products:read",
            "stock:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/product-items/{itemId}": {
      "get": {
        "summary": "Consulter un article physique",
        "tags": [
          "Produits"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^(product|characteristics|media|shop|category|supplier)(,(product|characteristics|media|shop|category|supplier))*$"
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Relations optionnelles à inclure, séparées par des virgules et sans espace."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "path",
            "name": "itemId",
            "required": true,
            "description": "Identifiant public stable de l’article physique.",
            "example": "item_01HZX8K5M6"
          }
        ],
        "responses": {
          "200": {
            "description": "Fiche publique de l’article physique.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "uuid",
                    "productId",
                    "code",
                    "serialNumber",
                    "reference",
                    "price",
                    "promotion",
                    "quantity",
                    "availability",
                    "inStockDate",
                    "updatedAt"
                  ],
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "description": "Identifiant public stable de la ressource."
                    },
                    "productId": {
                      "type": "string"
                    },
                    "code": {
                      "type": [
                        "null",
                        "string"
                      ]
                    },
                    "serialNumber": {
                      "type": [
                        "null",
                        "string"
                      ]
                    },
                    "reference": {
                      "type": [
                        "null",
                        "string"
                      ]
                    },
                    "product": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "reference",
                        "ean",
                        "name",
                        "displayedOnline"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Identifiant public stable de la ressource."
                        },
                        "reference": {
                          "type": [
                            "null",
                            "string"
                          ]
                        },
                        "ean": {
                          "type": [
                            "null",
                            "string"
                          ]
                        },
                        "name": {
                          "type": [
                            "null",
                            "string"
                          ]
                        },
                        "displayedOnline": {
                          "type": "boolean"
                        }
                      }
                    },
                    "price": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "inclTax",
                        "exclTax",
                        "currency"
                      ],
                      "properties": {
                        "inclTax": {
                          "type": [
                            "null",
                            "number"
                          ]
                        },
                        "exclTax": {
                          "type": [
                            "null",
                            "number"
                          ]
                        },
                        "currency": {
                          "type": "string",
                          "enum": [
                            "EUR"
                          ],
                          "description": "Devise monétaire ISO 4217.",
                          "example": "EUR"
                        }
                      },
                      "description": "Prix de base faisant foi sur l’article."
                    },
                    "promotion": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "active",
                        "type",
                        "value",
                        "priceInclTax"
                      ],
                      "properties": {
                        "active": {
                          "type": "boolean"
                        },
                        "type": {
                          "type": [
                            "null",
                            "string"
                          ]
                        },
                        "value": {
                          "type": [
                            "null",
                            "number"
                          ]
                        },
                        "priceInclTax": {
                          "type": [
                            "null",
                            "number"
                          ]
                        }
                      }
                    },
                    "quantity": {
                      "type": [
                        "null",
                        "integer"
                      ]
                    },
                    "availability": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "available",
                        "status",
                        "reason"
                      ],
                      "properties": {
                        "available": {
                          "type": "boolean",
                          "description": "Disponibilité résultant du calcul de stock Commerce 360."
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "available",
                            "out_of_stock",
                            "sold",
                            "reserved",
                            "withdrawn",
                            "unsalable"
                          ],
                          "description": "Statut public normalisé."
                        },
                        "reason": {
                          "type": [
                            "null",
                            "string"
                          ]
                        }
                      }
                    },
                    "shop": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "name",
                        "shortName",
                        "city"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Identifiant public stable de la ressource."
                        },
                        "name": {
                          "type": [
                            "null",
                            "string"
                          ]
                        },
                        "shortName": {
                          "type": [
                            "null",
                            "string"
                          ]
                        },
                        "city": {
                          "type": [
                            "null",
                            "string"
                          ]
                        }
                      },
                      "description": "Identifiant public historique de la boutique."
                    },
                    "characteristics": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "code",
                          "label",
                          "value",
                          "source"
                        ],
                        "properties": {
                          "code": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "value": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "product",
                              "item"
                            ]
                          }
                        }
                      }
                    },
                    "media": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "type",
                          "url",
                          "isMain"
                        ],
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "image"
                            ]
                          },
                          "url": {
                            "type": "string"
                          },
                          "isMain": {
                            "type": "boolean"
                          }
                        }
                      }
                    },
                    "inStockDate": {
                      "type": [
                        "null",
                        "string"
                      ]
                    },
                    "updatedAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "description": "Date de dernière modification au format ISO 8601."
                    },
                    "category": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "code",
                        "label"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Identifiant public stable de la ressource."
                        },
                        "code": {
                          "type": [
                            "null",
                            "string"
                          ]
                        },
                        "label": {
                          "type": [
                            "null",
                            "string"
                          ]
                        }
                      }
                    },
                    "supplier": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "name",
                        "shortName"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Identifiant public stable de la ressource."
                        },
                        "name": {
                          "type": [
                            "null",
                            "string"
                          ]
                        },
                        "shortName": {
                          "type": [
                            "null",
                            "string"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "getProductItem",
        "description": "Retourne l’état public courant d’un article physique : identité, prix de base, éventuel prix promotionnel, disponibilité calculée et relations demandées avec `include`.\n\n**Permissions obligatoires (toutes)** : `products:read`, `stock:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "products:read",
            "stock:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/categories": {
      "get": {
        "summary": "Lister les catégories",
        "tags": [
          "Référentiels"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "parentId",
            "required": false,
            "description": "Identifiant public de la catégorie parente."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "productTypeId",
            "required": false,
            "description": "Identifiant public du type produit."
          },
          {
            "schema": {
              "type": "boolean",
              "default": true
            },
            "in": "query",
            "name": "displayRefsOnline",
            "required": false,
            "description": "Filtre les catégories qui peuvent contenir des références affichables en ligne.",
            "example": true
          },
          {
            "schema": {
              "type": "boolean"
            },
            "in": "query",
            "name": "isSecondHand",
            "required": false,
            "description": "Filtre les articles d’occasion.",
            "example": false
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "children"
              ]
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Relations optionnelles à inclure, séparées par des virgules et sans espace."
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des catégories répondant aux filtres.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "code",
                          "label",
                          "type",
                          "parentId",
                          "productTypeId",
                          "quantityType",
                          "isSecondHand",
                          "displayRefsOnline"
                        ],
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "description": "Identifiant public stable de la ressource."
                          },
                          "code": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "label": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "product"
                            ]
                          },
                          "parentId": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "productTypeId": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "quantityType": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "isSecondHand": {
                            "type": "boolean"
                          },
                          "displayRefsOnline": {
                            "type": "boolean"
                          },
                          "children": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "uuid",
                                "code",
                                "label",
                                "type",
                                "parentId",
                                "productTypeId",
                                "quantityType",
                                "isSecondHand",
                                "displayRefsOnline"
                              ],
                              "properties": {
                                "uuid": {
                                  "type": "string",
                                  "description": "Identifiant public stable de la ressource."
                                },
                                "code": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                },
                                "label": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                },
                                "type": {
                                  "type": "string",
                                  "enum": [
                                    "product"
                                  ]
                                },
                                "parentId": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                },
                                "productTypeId": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                },
                                "quantityType": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                },
                                "isSecondHand": {
                                  "type": "boolean"
                                },
                                "displayRefsOnline": {
                                  "type": "boolean"
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listCategories",
        "description": "Retourne les catégories du catalogue visibles par le consommateur. `includeChildren=true` ajoute les enfants directs pour reconstruire la navigation ; `parentId` limite la réponse à une branche.\n\n**Permissions obligatoires (toutes)** : `referentials:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "referentials:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/product-types": {
      "get": {
        "summary": "Lister les types produits",
        "tags": [
          "Référentiels"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^(categories|characteristics)(,(categories|characteristics))*$"
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Relations optionnelles à inclure, séparées par des virgules et sans espace."
          },
          {
            "schema": {
              "type": "boolean"
            },
            "in": "query",
            "name": "displayedOnline",
            "required": false,
            "description": "Filtre sur l’indicateur de visibilité en ligne.",
            "example": true
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des types produits.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "id",
                          "code",
                          "label"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Identifiant public stable de la ressource."
                          },
                          "code": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "categories": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "id",
                                "code",
                                "label"
                              ],
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "description": "Identifiant public stable de la ressource."
                                },
                                "code": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                },
                                "label": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                }
                              }
                            }
                          },
                          "characteristics": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "id",
                                "code",
                                "label",
                                "type",
                                "form",
                                "display",
                                "suffix"
                              ],
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "description": "Identifiant public stable de la ressource."
                                },
                                "code": {
                                  "type": "string"
                                },
                                "label": {
                                  "type": "string"
                                },
                                "type": {
                                  "type": "string",
                                  "enum": [
                                    "select",
                                    "open_value"
                                  ]
                                },
                                "form": {
                                  "type": "string",
                                  "enum": [
                                    "product",
                                    "item",
                                    "both"
                                  ]
                                },
                                "display": {
                                  "type": "boolean"
                                },
                                "suffix": {
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listProductTypes",
        "description": "Retourne les types produits utilisés par les références Commerce 360. Les caractéristiques associées peuvent être incluses pour préparer les filtres et formulaires du canal externe.\n\n**Permissions obligatoires (toutes)** : `referentials:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "referentials:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/characteristics": {
      "get": {
        "summary": "Lister les caractéristiques",
        "tags": [
          "Référentiels"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "productTypeId",
            "required": false,
            "description": "Identifiant public du type produit."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "categoryId",
            "required": false,
            "description": "Identifiant public de la catégorie."
          },
          {
            "schema": {
              "type": "boolean"
            },
            "in": "query",
            "name": "display",
            "required": false,
            "description": "Filtre les caractéristiques configurées pour être affichées.",
            "example": true
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "product",
                "item",
                "both"
              ]
            },
            "in": "query",
            "name": "form",
            "required": false,
            "description": "Contexte d’utilisation de la caractéristique : produit, article ou les deux.",
            "example": "product"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^values(,values)*$"
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Relations optionnelles à inclure, séparées par des virgules et sans espace."
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des caractéristiques.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "id",
                          "code",
                          "label",
                          "type",
                          "form",
                          "display",
                          "suffix"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Identifiant public stable de la ressource."
                          },
                          "code": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "select",
                              "open_value"
                            ]
                          },
                          "form": {
                            "type": "string",
                            "enum": [
                              "product",
                              "item",
                              "both"
                            ]
                          },
                          "display": {
                            "type": "boolean"
                          },
                          "suffix": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "values": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "id",
                                "label"
                              ],
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "description": "Identifiant public stable de la ressource."
                                },
                                "label": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listCharacteristics",
        "description": "Retourne les définitions de caractéristiques produit. `include=values` ajoute les valeurs possibles lorsqu’elles sont gérées comme référentiel.\n\n**Permissions obligatoires (toutes)** : `referentials:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "referentials:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/characteristics/{characteristicId}/values": {
      "get": {
        "summary": "Lister les valeurs d’une caractéristique",
        "tags": [
          "Référentiels"
        ],
        "parameters": [
          {
            "schema": {
              "type": "boolean",
              "default": false
            },
            "in": "query",
            "name": "usedOnly",
            "required": false,
            "description": "Si vrai, ne retourne que les valeurs réellement utilisées.",
            "example": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "productTypeId",
            "required": false,
            "description": "Identifiant public du type produit."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "categoryId",
            "required": false,
            "description": "Identifiant public de la catégorie."
          },
          {
            "schema": {
              "type": "boolean",
              "default": false
            },
            "in": "query",
            "name": "availableOnly",
            "required": false,
            "description": "Si vrai, exclut les références ou articles sans stock disponible calculé.",
            "example": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "path",
            "name": "characteristicId",
            "required": true,
            "description": "Identifiant public de la caractéristique."
          }
        ],
        "responses": {
          "200": {
            "description": "Caractéristique demandée et liste de ses valeurs.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "characteristic",
                    "data"
                  ],
                  "properties": {
                    "characteristic": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "code",
                        "label"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Identifiant public stable de la ressource."
                        },
                        "code": {
                          "type": "string"
                        },
                        "label": {
                          "type": "string"
                        }
                      }
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "id",
                          "label"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Identifiant public stable de la ressource."
                          },
                          "label": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listCharacteristicValues",
        "description": "Retourne les valeurs publiques d’une caractéristique précise, dans l’ordre défini par Commerce 360.\n\n**Permissions obligatoires (toutes)** : `referentials:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "referentials:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/shops": {
      "get": {
        "summary": "Lister les boutiques",
        "tags": [
          "Référentiels"
        ],
        "parameters": [
          {
            "schema": {
              "type": "boolean",
              "default": true
            },
            "in": "query",
            "name": "activeOnly",
            "required": false,
            "description": "Si vrai, retourne uniquement les boutiques actives.",
            "example": true
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des boutiques.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "id",
                          "name",
                          "shortName",
                          "city"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Identifiant public stable de la ressource."
                          },
                          "name": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "shortName": {
                            "type": [
                              "null",
                              "string"
                            ]
                          },
                          "city": {
                            "type": [
                              "null",
                              "string"
                            ]
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listShops",
        "description": "Retourne les boutiques Commerce 360 utilisables comme contexte de catalogue, de client ou de transaction. Les boutiques actives sont retournées par défaut.\n\n**Permissions obligatoires (toutes)** : `referentials:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "referentials:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/customers": {
      "get": {
        "summary": "Lister les clients",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "in": "query",
            "name": "page",
            "required": false,
            "description": "Numéro de page, à partir de 1.",
            "example": 1
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "in": "query",
            "name": "limit",
            "required": false,
            "description": "Nombre maximal de résultats retournés par page.",
            "example": 50
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            },
            "in": "query",
            "name": "search",
            "required": false,
            "description": "Recherche textuelle normalisée sur les champs métier exposés.",
            "example": "martin"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "individual",
                "company"
              ]
            },
            "in": "query",
            "name": "typeCustomer",
            "required": false,
            "description": "Type de client : particulier ou société.",
            "example": "individual"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "query",
            "name": "shopId",
            "required": false,
            "description": "Identifiant public de la boutique."
          },
          {
            "schema": {
              "type": "boolean",
              "default": false
            },
            "in": "query",
            "name": "guest",
            "required": false,
            "description": "Filtre sur les fiches invitées.",
            "example": false
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "in": "query",
            "name": "updatedSince",
            "required": false,
            "description": "Ne retourne que les données modifiées depuis cet instant ISO 8601.",
            "example": "2026-07-01T00:00:00.000Z"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Relations optionnelles à inclure, séparées par des virgules et sans espace."
          }
        ],
        "responses": {
          "200": {
            "description": "Page de clients correspondant aux filtres.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "number",
                          "typeCustomer",
                          "firstName",
                          "lastName",
                          "companyName",
                          "guest",
                          "updatedAt"
                        ],
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 36,
                            "description": "Identifiant public stable de la ressource."
                          },
                          "number": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50,
                            "description": "Numéro métier lisible."
                          },
                          "typeCustomer": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "enum": [
                              "individual",
                              "company",
                              null
                            ]
                          },
                          "firstName": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "lastName": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "companyName": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 100
                          },
                          "email": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 254
                          },
                          "phone": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "phoneFix": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "guest": {
                            "type": "boolean"
                          },
                          "shop": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "name"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "name": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50
                              }
                            },
                            "description": "Identifiant public historique de la boutique."
                          },
                          "consents": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "phone",
                              "phoneAt",
                              "email",
                              "emailAt",
                              "personalInformation",
                              "personalInformationAt"
                            ],
                            "properties": {
                              "phone": {
                                "type": "boolean"
                              },
                              "phoneAt": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "format": "date"
                              },
                              "email": {
                                "type": "boolean"
                              },
                              "emailAt": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "format": "date"
                              },
                              "personalInformation": {
                                "type": "boolean"
                              },
                              "personalInformationAt": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "format": "date"
                              }
                            }
                          },
                          "comment": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 10000
                          },
                          "updatedAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "format": "date-time",
                            "description": "Date de dernière modification au format ISO 8601."
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "page",
                        "limit",
                        "count",
                        "total",
                        "totalPages",
                        "hasNextPage"
                      ],
                      "properties": {
                        "page": {
                          "type": "integer",
                          "description": "Numéro de la page courante."
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Taille maximale de la page."
                        },
                        "count": {
                          "type": "integer",
                          "description": "Nombre d’éléments présents dans cette page."
                        },
                        "total": {
                          "type": "integer",
                          "description": "Nombre total d’éléments correspondant aux filtres."
                        },
                        "totalPages": {
                          "type": "integer",
                          "description": "Nombre total de pages."
                        },
                        "hasNextPage": {
                          "type": "boolean",
                          "description": "Indique si une page suivante existe."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listCustomers",
        "description": "Retourne une liste paginée de clients. Utiliser cette route pour parcourir ou synchroniser, et `/v1/customers/search` pour rapprocher un compte web à partir d’éléments d’identité.\n\n**Permissions obligatoires (toutes)** : `customers:read`.\n\n**Permissions conditionnelles** :\n- `customers:pii:read` pour demander ou filtrer des coordonnées personnelles.\n- `internal-comments:read` pour inclure les commentaires internes.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "customers:read"
          ],
          "anyOf": [],
          "conditional": [
            "`customers:pii:read` pour demander ou filtrer des coordonnées personnelles.",
            "`internal-comments:read` pour inclure les commentaires internes."
          ]
        }
      }
    },
    "/v1/customers/search": {
      "get": {
        "summary": "Rechercher des clients pour rapprochement",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 254
            },
            "in": "query",
            "name": "email",
            "required": false,
            "description": "Adresse email exacte ou recherchée.",
            "example": "alice.martin@example.com"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50
            },
            "in": "query",
            "name": "phone",
            "required": false,
            "description": "Numéro national ou international utilisé pour le rapprochement.",
            "example": "+33612345678"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50
            },
            "in": "query",
            "name": "firstName",
            "required": false,
            "description": "Prénom recherché.",
            "example": "Alice"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50
            },
            "in": "query",
            "name": "lastName",
            "required": false,
            "description": "Nom recherché.",
            "example": "Martin"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "in": "query",
            "name": "companyName",
            "required": false,
            "description": "Raison sociale recherchée.",
            "example": "Maison Martin"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50
            },
            "in": "query",
            "name": "customerNumber",
            "required": false,
            "description": "Numéro métier Commerce 360 du client.",
            "example": "CLI-00142"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "exact",
                "contains"
              ],
              "default": "exact"
            },
            "in": "query",
            "name": "matchMode",
            "required": false,
            "description": "`exact` pour un rapprochement strict ; `contains` pour une recherche assistée.",
            "example": "exact"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "in": "query",
            "name": "page",
            "required": false,
            "description": "Numéro de page, à partir de 1.",
            "example": 1
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            },
            "in": "query",
            "name": "limit",
            "required": false,
            "description": "Nombre maximal de résultats retournés par page.",
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "Résultats de rapprochement paginés.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "number",
                          "typeCustomer",
                          "firstName",
                          "lastName",
                          "companyName",
                          "email",
                          "phone",
                          "phoneFix",
                          "postalCode",
                          "city",
                          "guest",
                          "shop",
                          "match",
                          "updatedAt"
                        ],
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 36,
                            "description": "Identifiant public stable de la ressource."
                          },
                          "number": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50,
                            "description": "Numéro métier lisible."
                          },
                          "typeCustomer": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 30
                          },
                          "firstName": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "lastName": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "companyName": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 100
                          },
                          "email": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 254
                          },
                          "phone": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "phoneFix": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "postalCode": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 30
                          },
                          "city": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 100
                          },
                          "guest": {
                            "type": "boolean"
                          },
                          "shop": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "name"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "name": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50
                              }
                            },
                            "description": "Identifiant public historique de la boutique."
                          },
                          "match": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "matchedOn",
                              "exact"
                            ],
                            "properties": {
                              "matchedOn": {
                                "type": "array",
                                "minItems": 1,
                                "uniqueItems": true,
                                "items": {
                                  "type": "string",
                                  "enum": [
                                    "email",
                                    "phone",
                                    "firstName",
                                    "lastName",
                                    "companyName",
                                    "customerNumber"
                                  ]
                                }
                              },
                              "exact": {
                                "type": "boolean"
                              }
                            }
                          },
                          "updatedAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "format": "date-time",
                            "description": "Date de dernière modification au format ISO 8601."
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "page",
                        "limit",
                        "count",
                        "total",
                        "totalPages",
                        "hasNextPage"
                      ],
                      "properties": {
                        "page": {
                          "type": "integer",
                          "description": "Numéro de la page courante."
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Taille maximale de la page."
                        },
                        "count": {
                          "type": "integer",
                          "description": "Nombre d’éléments présents dans cette page."
                        },
                        "total": {
                          "type": "integer",
                          "description": "Nombre total d’éléments correspondant aux filtres."
                        },
                        "totalPages": {
                          "type": "integer",
                          "description": "Nombre total de pages."
                        },
                        "hasNextPage": {
                          "type": "boolean",
                          "description": "Indique si une page suivante existe."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "searchCustomers",
        "description": "Recherche contrôlée par email, téléphone, nom, société ou numéro client afin d’établir une relation solide entre un compte web existant et une fiche Commerce 360. Au moins un critère métier doit être fourni. `matchMode=exact` est recommandé avant tout rattachement automatique.\n\n**Permissions obligatoires (toutes)** : `customers:read`, `customers:pii:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "customers:read",
            "customers:pii:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/customers/{customerId}": {
      "get": {
        "summary": "Consulter un client",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 150
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Relations optionnelles à inclure, séparées par des virgules et sans espace."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "path",
            "name": "customerId",
            "required": true,
            "description": "Identifiant public stable du client.",
            "example": "customer_01HZX8K5M6"
          }
        ],
        "responses": {
          "200": {
            "description": "Fiche client demandée.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "uuid",
                    "number",
                    "accountNumber",
                    "typeCustomer",
                    "civility",
                    "firstName",
                    "lastName",
                    "companyName",
                    "siren",
                    "siret",
                    "taxeNumber",
                    "legalStructure",
                    "billingDifferentAddress",
                    "communication",
                    "fidelityPoints",
                    "discount",
                    "guest",
                    "createdAt",
                    "updatedAt"
                  ],
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 36,
                      "description": "Identifiant public stable de la ressource."
                    },
                    "number": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50,
                      "description": "Numéro métier lisible."
                    },
                    "accountNumber": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 100
                    },
                    "typeCustomer": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 30
                    },
                    "civility": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 30
                    },
                    "firstName": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50
                    },
                    "lastName": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50
                    },
                    "companyName": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 100
                    },
                    "siren": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 10
                    },
                    "siret": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 20
                    },
                    "taxeNumber": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50
                    },
                    "legalStructure": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 30
                    },
                    "email": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 254
                    },
                    "phone": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50
                    },
                    "phoneFix": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50
                    },
                    "address": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 150
                    },
                    "additionalAddress": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 150
                    },
                    "postalCode": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 30
                    },
                    "city": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 100
                    },
                    "country": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "code",
                        "name"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "code": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 2
                        },
                        "name": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        }
                      }
                    },
                    "birthday": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "date"
                    },
                    "billingDifferentAddress": {
                      "type": "boolean"
                    },
                    "communication": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50
                    },
                    "couple": {
                      "type": "boolean"
                    },
                    "fidelityPoints": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "discount": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "guest": {
                      "type": "boolean"
                    },
                    "shop": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "name"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "name": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        }
                      },
                      "description": "Identifiant public historique de la boutique."
                    },
                    "consents": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "phone",
                        "phoneAt",
                        "email",
                        "emailAt",
                        "personalInformation",
                        "personalInformationAt"
                      ],
                      "properties": {
                        "phone": {
                          "type": "boolean"
                        },
                        "phoneAt": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "format": "date"
                        },
                        "email": {
                          "type": "boolean"
                        },
                        "emailAt": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "format": "date"
                        },
                        "personalInformation": {
                          "type": "boolean"
                        },
                        "personalInformationAt": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "format": "date"
                        }
                      }
                    },
                    "billingAddress": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "address",
                        "additionalAddress",
                        "postalCode",
                        "city",
                        "country"
                      ],
                      "properties": {
                        "address": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 150
                        },
                        "additionalAddress": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 150
                        },
                        "postalCode": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 30
                        },
                        "city": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 100
                        },
                        "country": {
                          "type": [
                            "null",
                            "object"
                          ],
                          "additionalProperties": false,
                          "required": [
                            "id",
                            "code",
                            "name"
                          ],
                          "properties": {
                            "id": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 36,
                              "description": "Identifiant public stable de la ressource."
                            },
                            "code": {
                              "type": [
                                "null",
                                "string"
                              ],
                              "maxLength": 2
                            },
                            "name": {
                              "type": [
                                "null",
                                "string"
                              ],
                              "maxLength": 50
                            }
                          }
                        }
                      }
                    },
                    "partner": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "civility",
                        "firstName",
                        "lastName",
                        "email",
                        "phone",
                        "birthday",
                        "weddingAnniversary"
                      ],
                      "properties": {
                        "civility": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 30
                        },
                        "firstName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "lastName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "email": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 254
                        },
                        "phone": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "birthday": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "format": "date"
                        },
                        "weddingAnniversary": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "format": "date"
                        }
                      }
                    },
                    "comment": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 10000
                    },
                    "createdAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "date-time",
                      "description": "Date de création au format ISO 8601."
                    },
                    "updatedAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "date-time",
                      "description": "Date de dernière modification au format ISO 8601."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "getCustomer",
        "description": "Retourne la fiche publique d’un client. Les coordonnées personnelles et commentaires ne sont ajoutés que si `include` les demande et si le compte possède les permissions correspondantes.\n\n**Permissions obligatoires (toutes)** : `customers:read`.\n\n**Permissions conditionnelles** :\n- `customers:pii:read` pour les coordonnées personnelles.\n- `internal-comments:read` pour les commentaires internes.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "customers:read"
          ],
          "anyOf": [],
          "conditional": [
            "`customers:pii:read` pour les coordonnées personnelles.",
            "`internal-comments:read` pour les commentaires internes."
          ]
        }
      },
      "put": {
        "summary": "Remplacer les informations modifiables d’un client",
        "tags": [
          "Clients"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "typeCustomer",
                  "billingDifferentAddress",
                  "communication",
                  "phoneCommunication",
                  "emailCommunication",
                  "personalInformations",
                  "shopId"
                ],
                "properties": {
                  "typeCustomer": {
                    "type": "string",
                    "enum": [
                      "individual",
                      "company"
                    ]
                  },
                  "civility": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "male",
                      "female",
                      null
                    ]
                  },
                  "firstName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 50,
                    "minLength": 1
                  },
                  "lastName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 50,
                    "minLength": 1
                  },
                  "companyName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 100,
                    "minLength": 1
                  },
                  "siren": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 10,
                    "minLength": 1
                  },
                  "siret": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 20,
                    "minLength": 1
                  },
                  "taxeNumber": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 50,
                    "minLength": 1
                  },
                  "legalStructure": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 30,
                    "minLength": 1
                  },
                  "email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email",
                    "minLength": 3,
                    "maxLength": 50
                  },
                  "phone": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 30,
                    "minLength": 1
                  },
                  "phonePrefix": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 15,
                    "minLength": 1
                  },
                  "phoneFix": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 30,
                    "minLength": 1
                  },
                  "phoneFixPrefix": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 15,
                    "minLength": 1
                  },
                  "address": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 150,
                    "minLength": 1
                  },
                  "additionalAddress": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 150,
                    "minLength": 1
                  },
                  "postalCode": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 30,
                    "minLength": 1
                  },
                  "city": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 100,
                    "minLength": 1
                  },
                  "countryId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 36,
                    "minLength": 1
                  },
                  "billingDifferentAddress": {
                    "type": "boolean"
                  },
                  "billingAddress": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 150,
                    "minLength": 1
                  },
                  "billingAdditionalAddress": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 150,
                    "minLength": 1
                  },
                  "billingPostalCode": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 30,
                    "minLength": 1
                  },
                  "billingCity": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 100,
                    "minLength": 1
                  },
                  "billingCountryId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 36,
                    "minLength": 1
                  },
                  "birthday": {
                    "type": [
                      "null",
                      "string"
                    ],
                    "format": "date"
                  },
                  "couple": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "partnerCivility": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "male",
                      "female",
                      null
                    ]
                  },
                  "partnerFirstName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 50,
                    "minLength": 1
                  },
                  "partnerLastName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 50,
                    "minLength": 1
                  },
                  "partnerEmail": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email",
                    "minLength": 3,
                    "maxLength": 50
                  },
                  "partnerPhone": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 30,
                    "minLength": 1
                  },
                  "partnerBirthday": {
                    "type": [
                      "null",
                      "string"
                    ],
                    "format": "date"
                  },
                  "weddingAnniversary": {
                    "type": [
                      "null",
                      "string"
                    ],
                    "format": "date"
                  },
                  "communication": {
                    "type": "string",
                    "enum": [
                      "none",
                      "email",
                      "sms",
                      "phonecall"
                    ]
                  },
                  "phoneCommunication": {
                    "type": "boolean"
                  },
                  "emailCommunication": {
                    "type": "boolean"
                  },
                  "personalInformations": {
                    "type": "boolean"
                  },
                  "shopId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 36
                  }
                }
              },
              "example": {
                "typeCustomer": "individual",
                "firstName": "Alice",
                "lastName": "Martin",
                "email": "alice.martin@example.com",
                "phone": "0612345678",
                "communication": "email",
                "phoneCommunication": false,
                "emailCommunication": true,
                "personalInformations": true,
                "shopId": "shop_01HZX8K5M6",
                "billingDifferentAddress": false
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "path",
            "name": "customerId",
            "required": true,
            "description": "Identifiant public stable du client.",
            "example": "customer_01HZX8K5M6"
          }
        ],
        "responses": {
          "200": {
            "description": "Client remplacé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "uuid",
                    "number",
                    "typeCustomer",
                    "firstName",
                    "lastName",
                    "email",
                    "phone",
                    "address",
                    "postalCode",
                    "city",
                    "updatedAt"
                  ],
                  "properties": {
                    "uuid": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 36,
                      "description": "Identifiant public stable de la ressource."
                    },
                    "number": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 30,
                      "description": "Numéro métier lisible."
                    },
                    "typeCustomer": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 30
                    },
                    "firstName": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50
                    },
                    "lastName": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50
                    },
                    "email": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50
                    },
                    "phone": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 30
                    },
                    "address": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 150
                    },
                    "postalCode": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 30
                    },
                    "city": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 100
                    },
                    "updatedAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "date-time",
                      "description": "Date de dernière modification au format ISO 8601."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "replaceCustomer",
        "description": "Remplace la représentation modifiable complète du client. Il ne s’agit pas d’un PATCH : les champs optionnels omis sont remis à leur valeur vide ou par défaut selon les règles Commerce 360.\n\n**Permissions obligatoires (toutes)** : `customers:write`, `customers:pii:write`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "customers:write",
            "customers:pii:write"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/customers/{customerId}/credits": {
      "get": {
        "summary": "Lister les crédits d’un client",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "query",
            "name": "type",
            "required": false,
            "description": "Type public utilisé comme filtre."
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "used",
                "expired",
                "cancelled"
              ]
            },
            "in": "query",
            "name": "status",
            "required": false,
            "description": "Statut public utilisé comme filtre."
          },
          {
            "schema": {
              "type": "boolean",
              "default": false
            },
            "in": "query",
            "name": "includeExpired",
            "required": false,
            "description": "Si vrai, inclut aussi les crédits arrivés à expiration.",
            "example": false
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "in": "query",
            "name": "page",
            "required": false,
            "description": "Numéro de page, à partir de 1.",
            "example": 1
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "in": "query",
            "name": "limit",
            "required": false,
            "description": "Nombre maximal de résultats retournés par page.",
            "example": 50
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "path",
            "name": "customerId",
            "required": true,
            "description": "Identifiant public stable du client.",
            "example": "customer_01HZX8K5M6"
          }
        ],
        "responses": {
          "200": {
            "description": "Crédits du client et synthèse des montants.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "number",
                          "type",
                          "amount",
                          "amountLeft",
                          "currency",
                          "status",
                          "expiredAt",
                          "origin",
                          "createdAt",
                          "updatedAt"
                        ],
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 36,
                            "description": "Identifiant public stable de la ressource."
                          },
                          "number": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50,
                            "description": "Numéro métier lisible."
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "note",
                              "deposit",
                              "gift_card"
                            ]
                          },
                          "amount": {
                            "type": "number",
                            "description": "Montant monétaire en EUR."
                          },
                          "amountLeft": {
                            "type": "number",
                            "description": "Solde encore consommable."
                          },
                          "currency": {
                            "type": "string",
                            "enum": [
                              "EUR"
                            ],
                            "description": "Devise monétaire ISO 4217.",
                            "example": "EUR"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "used",
                              "expired",
                              "cancelled"
                            ],
                            "description": "Statut public normalisé."
                          },
                          "expiredAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "format": "date",
                            "description": "Date d’expiration au format ISO 8601, ou null lorsqu’aucune échéance ne s’applique."
                          },
                          "origin": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "type",
                              "uuid",
                              "number"
                            ],
                            "properties": {
                              "type": {
                                "type": "string",
                                "enum": [
                                  "sale",
                                  "customer_order",
                                  "reservation",
                                  "sav"
                                ]
                              },
                              "uuid": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50,
                                "description": "Numéro métier lisible."
                              }
                            },
                            "description": "Ressource métier à l’origine de la donnée."
                          },
                          "createdAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "format": "date-time",
                            "description": "Date de création au format ISO 8601."
                          },
                          "updatedAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "format": "date-time",
                            "description": "Date de dernière modification au format ISO 8601."
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "page",
                        "limit",
                        "count",
                        "total",
                        "totalPages",
                        "hasNextPage"
                      ],
                      "properties": {
                        "page": {
                          "type": "integer",
                          "description": "Numéro de la page courante."
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Taille maximale de la page."
                        },
                        "count": {
                          "type": "integer",
                          "description": "Nombre d’éléments présents dans cette page."
                        },
                        "total": {
                          "type": "integer",
                          "description": "Nombre total d’éléments correspondant aux filtres."
                        },
                        "totalPages": {
                          "type": "integer",
                          "description": "Nombre total de pages."
                        },
                        "hasNextPage": {
                          "type": "boolean",
                          "description": "Indique si une page suivante existe."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listCustomerCredits",
        "description": "Retourne les avoirs et acomptes d’un client avec montant initial, solde consommable, statut public et origine. Les cartes cadeaux ne sont incluses que lorsqu’elles sont explicitement demandées.\n\n**Permissions obligatoires (toutes)** : `customers:read`, `customer-credits:read`.\n\n**Permissions conditionnelles** :\n- `gift-cards:read` lorsque le filtre `types` contient `gift_card`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "customers:read",
            "customer-credits:read"
          ],
          "anyOf": [],
          "conditional": [
            "`gift-cards:read` lorsque le filtre `types` contient `gift_card`."
          ]
        }
      }
    },
    "/v1/customers/{customerId}/history": {
      "get": {
        "summary": "Consulter l’historique commercial d’un client",
        "tags": [
          "Clients"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Relations optionnelles à inclure, séparées par des virgules et sans espace."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "query",
            "name": "from",
            "required": false,
            "description": "Début de la période recherchée, au format ISO 8601.",
            "example": "2026-01-01T00:00:00.000Z"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "query",
            "name": "to",
            "required": false,
            "description": "Fin de la période recherchée, au format ISO 8601.",
            "example": "2026-12-31T23:59:59.999Z"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "in": "query",
            "name": "limitPerType",
            "required": false,
            "description": "Nombre maximal d’événements retournés pour chaque famille d’historique.",
            "example": 20
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "path",
            "name": "customerId",
            "required": true,
            "description": "Identifiant public stable du client.",
            "example": "customer_01HZX8K5M6"
          }
        ],
        "responses": {
          "200": {
            "description": "Historique consolidé, regroupé par type demandé.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "customer",
                    "history",
                    "hasMore"
                  ],
                  "properties": {
                    "customer": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "uuid",
                        "number",
                        "firstName",
                        "lastName"
                      ],
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "number": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50,
                          "description": "Numéro métier lisible."
                        },
                        "firstName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "lastName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        }
                      }
                    },
                    "history": {
                      "type": "object",
                      "additionalProperties": false,
                      "properties": {
                        "sales": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "uuid",
                              "number",
                              "date",
                              "status",
                              "totalPrice",
                              "shop"
                            ],
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50,
                                "description": "Numéro métier lisible."
                              },
                              "date": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "format": "date-time"
                              },
                              "status": {
                                "type": "string",
                                "description": "Statut public normalisé."
                              },
                              "totalPrice": {
                                "type": "number"
                              },
                              "shop": {
                                "type": [
                                  "null",
                                  "object"
                                ],
                                "additionalProperties": false,
                                "required": [
                                  "id",
                                  "name"
                                ],
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 36,
                                    "description": "Identifiant public stable de la ressource."
                                  },
                                  "name": {
                                    "type": [
                                      "null",
                                      "string"
                                    ],
                                    "maxLength": 50
                                  }
                                },
                                "description": "Identifiant public historique de la boutique."
                              }
                            }
                          }
                        },
                        "orders": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "uuid",
                              "number",
                              "status",
                              "totalPrice",
                              "remainingAmount"
                            ],
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50,
                                "description": "Numéro métier lisible."
                              },
                              "status": {
                                "type": "string",
                                "description": "Statut public normalisé."
                              },
                              "totalPrice": {
                                "type": "number"
                              },
                              "remainingAmount": {
                                "type": "number",
                                "minimum": 0
                              }
                            }
                          }
                        },
                        "reservations": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "uuid",
                              "number",
                              "date",
                              "status",
                              "totalPriceArticles"
                            ],
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50,
                                "description": "Numéro métier lisible."
                              },
                              "date": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "format": "date-time"
                              },
                              "status": {
                                "type": "string",
                                "description": "Statut public normalisé."
                              },
                              "totalPriceArticles": {
                                "type": "number"
                              }
                            }
                          }
                        },
                        "sav": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "uuid",
                              "number",
                              "status",
                              "availabilityDate",
                              "price",
                              "deposit",
                              "remainingAmount"
                            ],
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50,
                                "description": "Numéro métier lisible."
                              },
                              "status": {
                                "type": "string",
                                "description": "Statut public normalisé."
                              },
                              "availabilityDate": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "format": "date"
                              },
                              "price": {
                                "type": "number",
                                "description": "Prix de base faisant foi sur l’article."
                              },
                              "deposit": {
                                "type": "number"
                              },
                              "remainingAmount": {
                                "type": "number",
                                "minimum": 0
                              }
                            }
                          }
                        },
                        "quotes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "uuid",
                              "number",
                              "status",
                              "title",
                              "totalPrice",
                              "dueDate"
                            ],
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50,
                                "description": "Numéro métier lisible."
                              },
                              "status": {
                                "type": "string",
                                "description": "Statut public normalisé."
                              },
                              "title": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 250
                              },
                              "totalPrice": {
                                "type": "number"
                              },
                              "dueDate": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "format": "date"
                              }
                            }
                          }
                        },
                        "credits": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": false,
                            "required": [
                              "uuid",
                              "number",
                              "type",
                              "amount",
                              "amountLeft",
                              "status",
                              "expiredAt"
                            ],
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50,
                                "description": "Numéro métier lisible."
                              },
                              "type": {
                                "type": "string",
                                "enum": [
                                  "note",
                                  "deposit",
                                  "gift_card"
                                ]
                              },
                              "amount": {
                                "type": "number",
                                "description": "Montant monétaire en EUR."
                              },
                              "amountLeft": {
                                "type": "number",
                                "description": "Solde encore consommable."
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "active",
                                  "used",
                                  "expired",
                                  "cancelled"
                                ],
                                "description": "Statut public normalisé."
                              },
                              "expiredAt": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "format": "date",
                                "description": "Date d’expiration au format ISO 8601, ou null lorsqu’aucune échéance ne s’applique."
                              }
                            }
                          }
                        }
                      }
                    },
                    "hasMore": {
                      "type": "object",
                      "additionalProperties": false,
                      "properties": {
                        "sales": {
                          "type": "boolean"
                        },
                        "orders": {
                          "type": "boolean"
                        },
                        "reservations": {
                          "type": "boolean"
                        },
                        "sav": {
                          "type": "boolean"
                        },
                        "quotes": {
                          "type": "boolean"
                        },
                        "credits": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "getCustomerHistory",
        "description": "Consolide les événements commerciaux autorisés pour le client : ventes, commandes, réservations, SAV, devis et crédits. `limitPerType` limite séparément chaque famille afin d’éviter qu’un historique volumineux masque les autres.\n\n**Permissions obligatoires (toutes)** : `customers:read`.\n\n**Permission obligatoire (au moins une)** : `sales:read`, `orders:read`, `sav:read`, `customer-credits:read`.\n\n**Permissions conditionnelles** :\n- Chaque famille demandée dans `include` nécessite son scope de lecture ; les familles non autorisées sont omises.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "customers:read"
          ],
          "anyOf": [
            "sales:read",
            "orders:read",
            "sav:read",
            "customer-credits:read"
          ],
          "conditional": [
            "Chaque famille demandée dans `include` nécessite son scope de lecture ; les familles non autorisées sont omises."
          ]
        }
      }
    },
    "/v1/sales": {
      "get": {
        "summary": "Lister les ventes",
        "tags": [
          "Ventes"
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "in": "query",
            "name": "page",
            "required": false,
            "description": "Numéro de page, à partir de 1.",
            "example": 1
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "in": "query",
            "name": "limit",
            "required": false,
            "description": "Nombre maximal de résultats retournés par page.",
            "example": 50
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "query",
            "name": "customerId",
            "required": false,
            "description": "Identifiant public stable du client.",
            "example": "customer_01HZX8K5M6"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "completed",
                "returned",
                "cancelled",
                "cancelled_note",
                "cancelled_refund",
                "cancelled_refund_note"
              ]
            },
            "in": "query",
            "name": "status",
            "required": false,
            "description": "Statut public utilisé comme filtre."
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "sale",
                "deposit",
                "return",
                "cancel",
                "cancel_sold",
                "refund_note"
              ]
            },
            "in": "query",
            "name": "action",
            "required": false,
            "description": "Action métier de vente utilisée comme filtre."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "query",
            "name": "shopId",
            "required": false,
            "description": "Identifiant public de la boutique."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50
            },
            "in": "query",
            "name": "number",
            "required": false,
            "description": "Numéro métier exact ou partiel selon la route."
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "in": "query",
            "name": "from",
            "required": false,
            "description": "Début de la période recherchée, au format ISO 8601.",
            "example": "2026-01-01T00:00:00.000Z"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "in": "query",
            "name": "to",
            "required": false,
            "description": "Fin de la période recherchée, au format ISO 8601.",
            "example": "2026-12-31T23:59:59.999Z"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "in": "query",
            "name": "updatedSince",
            "required": false,
            "description": "Ne retourne que les données modifiées depuis cet instant ISO 8601.",
            "example": "2026-07-01T00:00:00.000Z"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Relations optionnelles à inclure, séparées par des virgules et sans espace."
          }
        ],
        "responses": {
          "200": {
            "description": "Page de ventes correspondant aux filtres.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "number",
                          "status",
                          "action",
                          "cartType",
                          "totalPrice",
                          "totalPriceExclTax",
                          "totalTaxes",
                          "totalDiscount",
                          "currency",
                          "createdAt",
                          "updatedAt"
                        ],
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 36,
                            "description": "Identifiant public stable de la ressource."
                          },
                          "number": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50,
                            "description": "Numéro métier lisible."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "completed",
                              "returned",
                              "cancelled",
                              "cancelled_note",
                              "cancelled_refund",
                              "cancelled_refund_note"
                            ],
                            "description": "Statut public normalisé."
                          },
                          "action": {
                            "type": "string",
                            "enum": [
                              "sale",
                              "deposit",
                              "return",
                              "cancel",
                              "cancel_sold",
                              "refund_note"
                            ]
                          },
                          "cartType": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "totalPrice": {
                            "type": [
                              "null",
                              "number"
                            ]
                          },
                          "totalPriceExclTax": {
                            "type": [
                              "null",
                              "number"
                            ]
                          },
                          "totalTaxes": {
                            "type": [
                              "null",
                              "number"
                            ]
                          },
                          "totalDiscount": {
                            "type": [
                              "null",
                              "number"
                            ]
                          },
                          "currency": {
                            "type": "string",
                            "enum": [
                              "EUR"
                            ],
                            "description": "Devise monétaire ISO 4217.",
                            "example": "EUR"
                          },
                          "customer": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "uuid",
                              "number",
                              "firstName",
                              "lastName"
                            ],
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 30,
                                "description": "Numéro métier lisible."
                              },
                              "firstName": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50
                              },
                              "lastName": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50
                              },
                              "email": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 254
                              },
                              "phone": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50
                              }
                            }
                          },
                          "shop": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "name"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "name": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50
                              }
                            },
                            "description": "Identifiant public historique de la boutique."
                          },
                          "seller": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "code",
                              "firstName",
                              "lastName"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "code": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50
                              },
                              "firstName": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 150
                              },
                              "lastName": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 150
                              }
                            }
                          },
                          "invoice": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "uuid",
                              "number"
                            ],
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50,
                                "description": "Numéro métier lisible."
                              }
                            },
                            "description": "Document de vente public associé, lorsqu’il existe."
                          },
                          "createdAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "format": "date-time",
                            "description": "Date de création au format ISO 8601."
                          },
                          "updatedAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "format": "date-time",
                            "description": "Date de dernière modification au format ISO 8601."
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "page",
                        "limit",
                        "count",
                        "total",
                        "totalPages",
                        "hasNextPage"
                      ],
                      "properties": {
                        "page": {
                          "type": "integer",
                          "description": "Numéro de la page courante."
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Taille maximale de la page."
                        },
                        "count": {
                          "type": "integer",
                          "description": "Nombre d’éléments présents dans cette page."
                        },
                        "total": {
                          "type": "integer",
                          "description": "Nombre total d’éléments correspondant aux filtres."
                        },
                        "totalPages": {
                          "type": "integer",
                          "description": "Nombre total de pages."
                        },
                        "hasNextPage": {
                          "type": "boolean",
                          "description": "Indique si une page suivante existe."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listSales",
        "description": "Recherche paginée des ventes par client, statut, action, boutique, numéro ou période. Les inclusions permettent d’ajouter les relations nécessaires sans surcharger la réponse par défaut.\n\n**Permissions obligatoires (toutes)** : `sales:read`.\n\n**Permissions conditionnelles** :\n- `customers:pii:read` pour les coordonnées client.\n- `customer-credits:read` pour le détail des crédits utilisés.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "sales:read"
          ],
          "anyOf": [],
          "conditional": [
            "`customers:pii:read` pour les coordonnées client.",
            "`customer-credits:read` pour le détail des crédits utilisés."
          ]
        }
      }
    },
    "/v1/sales/{saleId}": {
      "get": {
        "summary": "Consulter une vente",
        "tags": [
          "Ventes"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 150
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Valeurs autorisées : customer, shop, seller, items, payments, discounts, invoice, origins"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "path",
            "name": "saleId",
            "required": true,
            "description": "Identifiant public stable de la vente.",
            "example": "sale_01HZX8K5M6"
          }
        ],
        "responses": {
          "200": {
            "description": "Détail de la vente.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "uuid",
                    "number",
                    "status",
                    "action",
                    "cartType",
                    "productsType",
                    "cancelledAt",
                    "totalPriceOrigin",
                    "totalPrice",
                    "totalPriceExclTax",
                    "totalTaxes",
                    "totalPriceArticles",
                    "totalDiscount",
                    "totalDiscountExclTax",
                    "totalGlobalDiscount",
                    "deposit",
                    "currency",
                    "createdAt",
                    "updatedAt"
                  ],
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 36,
                      "description": "Identifiant public stable de la ressource."
                    },
                    "number": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50,
                      "description": "Numéro métier lisible."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "completed",
                        "returned",
                        "cancelled",
                        "cancelled_note",
                        "cancelled_refund",
                        "cancelled_refund_note"
                      ],
                      "description": "Statut public normalisé."
                    },
                    "action": {
                      "type": "string",
                      "enum": [
                        "sale",
                        "deposit",
                        "return",
                        "cancel",
                        "cancel_sold",
                        "refund_note"
                      ]
                    },
                    "cartType": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50
                    },
                    "productsType": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50
                    },
                    "cancelledAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "date-time"
                    },
                    "totalPriceOrigin": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "totalPrice": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "totalPriceExclTax": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "totalTaxes": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "totalPriceArticles": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "totalDiscount": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "totalDiscountExclTax": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "totalGlobalDiscount": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "deposit": {
                      "type": "boolean"
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "EUR"
                      ],
                      "description": "Devise monétaire ISO 4217.",
                      "example": "EUR"
                    },
                    "customer": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "uuid",
                        "number",
                        "firstName",
                        "lastName"
                      ],
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "number": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 30,
                          "description": "Numéro métier lisible."
                        },
                        "firstName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "lastName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "email": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 254
                        },
                        "phone": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        }
                      }
                    },
                    "shop": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "name"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "name": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        }
                      },
                      "description": "Identifiant public historique de la boutique."
                    },
                    "seller": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "code",
                        "firstName",
                        "lastName"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "code": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "firstName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 150
                        },
                        "lastName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 150
                        }
                      }
                    },
                    "origins": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "reservation",
                        "customerOrder",
                        "storeTransfer"
                      ],
                      "properties": {
                        "reservation": {
                          "type": [
                            "null",
                            "object"
                          ],
                          "additionalProperties": false,
                          "required": [
                            "uuid",
                            "number"
                          ],
                          "properties": {
                            "uuid": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 36,
                              "description": "Identifiant public stable de la ressource."
                            },
                            "number": {
                              "type": [
                                "null",
                                "string"
                              ],
                              "maxLength": 50,
                              "description": "Numéro métier lisible."
                            }
                          }
                        },
                        "customerOrder": {
                          "type": [
                            "null",
                            "object"
                          ],
                          "additionalProperties": false,
                          "required": [
                            "uuid",
                            "number"
                          ],
                          "properties": {
                            "uuid": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 36,
                              "description": "Identifiant public stable de la ressource."
                            },
                            "number": {
                              "type": [
                                "null",
                                "string"
                              ],
                              "maxLength": 50,
                              "description": "Numéro métier lisible."
                            }
                          }
                        },
                        "storeTransfer": {
                          "type": [
                            "null",
                            "object"
                          ],
                          "additionalProperties": false,
                          "required": [
                            "uuid",
                            "number"
                          ],
                          "properties": {
                            "uuid": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 36,
                              "description": "Identifiant public stable de la ressource."
                            },
                            "number": {
                              "type": [
                                "null",
                                "string"
                              ],
                              "maxLength": 50,
                              "description": "Numéro métier lisible."
                            }
                          }
                        }
                      }
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "code",
                          "name",
                          "reference",
                          "serialNumber",
                          "quantity",
                          "unitPrice",
                          "totalPrice",
                          "totalPriceExclTax",
                          "discount",
                          "characteristics",
                          "article",
                          "sav",
                          "taxes"
                        ],
                        "properties": {
                          "uuid": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 36,
                            "description": "Identifiant public stable de la ressource."
                          },
                          "code": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "name": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 100
                          },
                          "reference": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 100
                          },
                          "serialNumber": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "quantity": {
                            "type": "number"
                          },
                          "unitPrice": {
                            "type": [
                              "null",
                              "number"
                            ]
                          },
                          "totalPrice": {
                            "type": [
                              "null",
                              "number"
                            ]
                          },
                          "totalPriceExclTax": {
                            "type": [
                              "null",
                              "number"
                            ]
                          },
                          "discount": {
                            "type": [
                              "null",
                              "number"
                            ]
                          },
                          "characteristics": {
                            "anyOf": [
                              {
                                "type": "object",
                                "additionalProperties": true
                              },
                              {
                                "type": "array",
                                "items": {}
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "article": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              }
                            }
                          },
                          "sav": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "number"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50,
                                "description": "Numéro métier lisible."
                              }
                            }
                          },
                          "taxes": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "rate",
                                "amount",
                                "taxId",
                                "isMain"
                              ],
                              "properties": {
                                "rate": {
                                  "type": [
                                    "null",
                                    "number"
                                  ]
                                },
                                "amount": {
                                  "type": [
                                    "null",
                                    "number"
                                  ],
                                  "description": "Montant monétaire en EUR."
                                },
                                "taxId": {
                                  "type": [
                                    "null",
                                    "string"
                                  ],
                                  "maxLength": 36
                                },
                                "isMain": {
                                  "type": "boolean"
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "payments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "name",
                          "amount",
                          "paymentMethod",
                          "deferredPayments"
                        ],
                        "properties": {
                          "uuid": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 36,
                            "description": "Identifiant public stable de la ressource."
                          },
                          "name": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "amount": {
                            "type": [
                              "null",
                              "number"
                            ],
                            "description": "Montant monétaire en EUR."
                          },
                          "paymentMethod": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "name",
                              "code"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "name": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 100
                              },
                              "code": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50
                              }
                            }
                          },
                          "customerCredit": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "uuid",
                              "number",
                              "amount",
                              "amountLeft",
                              "status",
                              "expiredAt"
                            ],
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50,
                                "description": "Numéro métier lisible."
                              },
                              "amount": {
                                "type": [
                                  "null",
                                  "number"
                                ],
                                "description": "Montant monétaire en EUR."
                              },
                              "amountLeft": {
                                "type": [
                                  "null",
                                  "number"
                                ],
                                "description": "Solde encore consommable."
                              },
                              "status": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50,
                                "description": "Statut public normalisé."
                              },
                              "expiredAt": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "format": "date",
                                "description": "Date d’expiration au format ISO 8601, ou null lorsqu’aucune échéance ne s’applique."
                              }
                            }
                          },
                          "deferredPayments": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "uuid",
                                "status",
                                "dueDate",
                                "amount"
                              ],
                              "properties": {
                                "uuid": {
                                  "type": [
                                    "null",
                                    "string"
                                  ],
                                  "maxLength": 36,
                                  "description": "Identifiant public stable de la ressource."
                                },
                                "status": {
                                  "type": [
                                    "null",
                                    "string"
                                  ],
                                  "maxLength": 50,
                                  "description": "Statut public normalisé."
                                },
                                "dueDate": {
                                  "type": [
                                    "null",
                                    "string"
                                  ],
                                  "format": "date"
                                },
                                "amount": {
                                  "type": [
                                    "null",
                                    "number"
                                  ],
                                  "description": "Montant monétaire en EUR."
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "discounts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "type",
                          "value",
                          "amount"
                        ],
                        "properties": {
                          "uuid": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 36,
                            "description": "Identifiant public stable de la ressource."
                          },
                          "type": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "value": {
                            "type": [
                              "null",
                              "number"
                            ]
                          },
                          "amount": {
                            "type": [
                              "null",
                              "number"
                            ],
                            "description": "Montant monétaire en EUR."
                          }
                        }
                      }
                    },
                    "invoice": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "uuid",
                        "number"
                      ],
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "number": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50,
                          "description": "Numéro métier lisible."
                        }
                      },
                      "description": "Document de vente public associé, lorsqu’il existe."
                    },
                    "createdAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "date-time",
                      "description": "Date de création au format ISO 8601."
                    },
                    "updatedAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "date-time",
                      "description": "Date de dernière modification au format ISO 8601."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "getSale",
        "description": "Retourne le détail consolidé de la vente, ses lignes, règlements et totaux. Les relations optionnelles se demandent avec `include` et restent filtrées selon les permissions du consommateur.\n\n**Permissions obligatoires (toutes)** : `sales:read`.\n\n**Permissions conditionnelles** :\n- `customers:pii:read` pour les coordonnées client.\n- `customer-credits:read` pour le détail des crédits utilisés.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "sales:read"
          ],
          "anyOf": [],
          "conditional": [
            "`customers:pii:read` pour les coordonnées client.",
            "`customer-credits:read` pour le détail des crédits utilisés."
          ]
        }
      }
    },
    "/v1/sales/{saleId}/invoice": {
      "get": {
        "summary": "Consulter les métadonnées de facture",
        "tags": [
          "Ventes"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "path",
            "name": "saleId",
            "required": true,
            "description": "Identifiant public stable de la vente.",
            "example": "sale_01HZX8K5M6"
          }
        ],
        "responses": {
          "200": {
            "description": "Métadonnées de facture.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "uuid",
                    "number",
                    "saleId",
                    "type",
                    "status",
                    "issuedAt",
                    "totalInclTax",
                    "totalExclTax",
                    "totalTaxes",
                    "currency",
                    "downloadAvailable"
                  ],
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 36,
                      "description": "Identifiant public stable de la ressource."
                    },
                    "number": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50,
                      "description": "Numéro métier lisible."
                    },
                    "saleId": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 36,
                      "description": "Identifiant public de la vente à laquelle rattacher l’utilisation, lorsqu’elle existe."
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "invoice"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "issued"
                      ],
                      "description": "Statut public normalisé."
                    },
                    "issuedAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "date-time"
                    },
                    "totalInclTax": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "totalExclTax": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "totalTaxes": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "EUR"
                      ],
                      "description": "Devise monétaire ISO 4217.",
                      "example": "EUR"
                    },
                    "downloadAvailable": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "getSaleInvoiceMetadata",
        "description": "Retourne les métadonnées publiques du document de vente officiel associé à la vente, notamment ses montants, son numéro et la possibilité de télécharger le PDF.\n\n**Permissions obligatoires (toutes)** : `sales:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "sales:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/sales/{saleId}/invoice/download": {
      "get": {
        "summary": "Télécharger la facture PDF",
        "tags": [
          "Ventes"
        ],
        "parameters": [
          {
            "schema": {
              "type": "boolean",
              "default": true
            },
            "in": "query",
            "name": "download",
            "required": false,
            "description": "Si vrai, demande `Content-Disposition: attachment` ; sinon `inline`.",
            "example": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "path",
            "name": "saleId",
            "required": true,
            "description": "Identifiant public stable de la vente.",
            "example": "sale_01HZX8K5M6"
          }
        ],
        "responses": {
          "200": {
            "description": "Flux PDF officiel de la facture.",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            },
            "headers": {
              "Content-Disposition": {
                "description": "`attachment` lorsque `download=true`, sinon `inline`.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Politique de cache appliquée au document privé.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Content-Type-Options": {
                "description": "Protection contre l’interprétation d’un autre type MIME.",
                "schema": {
                  "type": "string",
                  "example": "nosniff"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "downloadSaleInvoice",
        "description": "Génère ou récupère le document PDF officiel lié à la vente. `download=true` produit une pièce jointe ; `download=false` demande un affichage inline. Le contenu est binaire et ne doit pas être interprété comme du JSON.\n\n**Permissions obligatoires (toutes)** : `sales:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "sales:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/sav": {
      "get": {
        "summary": "Lister les dossiers SAV",
        "tags": [
          "SAV"
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "in": "query",
            "name": "page",
            "required": false,
            "description": "Numéro de page, à partir de 1.",
            "example": 1
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "in": "query",
            "name": "limit",
            "required": false,
            "description": "Nombre maximal de résultats retournés par page.",
            "example": 50
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "query",
            "name": "customerId",
            "required": false,
            "description": "Identifiant public stable du client.",
            "example": "customer_01HZX8K5M6"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "quoting",
                "quote",
                "quote_accepted",
                "refused",
                "in_progress",
                "ready",
                "done",
                "cancelled"
              ]
            },
            "in": "query",
            "name": "status",
            "required": false,
            "description": "Statut public utilisé comme filtre."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "query",
            "name": "shopId",
            "required": false,
            "description": "Identifiant public de la boutique."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "in": "query",
            "name": "search",
            "required": false,
            "description": "Recherche textuelle normalisée sur les champs métier exposés.",
            "example": "martin"
          },
          {
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "date"
                },
                {
                  "type": "string",
                  "format": "date-time"
                }
              ]
            },
            "in": "query",
            "name": "from",
            "required": false,
            "description": "Début de la période recherchée, au format ISO 8601.",
            "example": "2026-01-01T00:00:00.000Z"
          },
          {
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "date"
                },
                {
                  "type": "string",
                  "format": "date-time"
                }
              ]
            },
            "in": "query",
            "name": "to",
            "required": false,
            "description": "Fin de la période recherchée, au format ISO 8601.",
            "example": "2026-12-31T23:59:59.999Z"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "in": "query",
            "name": "updatedSince",
            "required": false,
            "description": "Ne retourne que les données modifiées depuis cet instant ISO 8601.",
            "example": "2026-07-01T00:00:00.000Z"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Valeurs autorisées : customer, shop, seller, quote, media"
          }
        ],
        "responses": {
          "200": {
            "description": "Page de dossiers SAV correspondant aux filtres.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "number",
                          "status",
                          "typeToDo",
                          "nameReference",
                          "reference",
                          "code",
                          "serialNumber",
                          "price",
                          "deposit",
                          "remainingAmount",
                          "paid",
                          "currency",
                          "availabilityDate",
                          "createdAt",
                          "updatedAt"
                        ],
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 36,
                            "description": "Identifiant public stable de la ressource."
                          },
                          "number": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50,
                            "description": "Numéro métier lisible."
                          },
                          "status": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 50,
                            "description": "Statut public normalisé."
                          },
                          "typeToDo": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "nameReference": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 300
                          },
                          "reference": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "code": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "serialNumber": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50
                          },
                          "price": {
                            "type": [
                              "null",
                              "number"
                            ],
                            "description": "Prix de base faisant foi sur l’article."
                          },
                          "deposit": {
                            "type": "number"
                          },
                          "remainingAmount": {
                            "type": [
                              "null",
                              "number"
                            ]
                          },
                          "paid": {
                            "type": "boolean"
                          },
                          "currency": {
                            "type": "string",
                            "enum": [
                              "EUR"
                            ],
                            "description": "Devise monétaire ISO 4217.",
                            "example": "EUR"
                          },
                          "availabilityDate": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "format": "date"
                          },
                          "customer": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "uuid",
                              "number",
                              "firstName",
                              "lastName"
                            ],
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 30,
                                "description": "Numéro métier lisible."
                              },
                              "firstName": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50
                              },
                              "lastName": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50
                              },
                              "email": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 254
                              },
                              "phone": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50
                              }
                            }
                          },
                          "shop": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "name"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "name": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50
                              }
                            },
                            "description": "Identifiant public historique de la boutique."
                          },
                          "seller": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "id",
                              "code",
                              "firstName",
                              "lastName"
                            ],
                            "properties": {
                              "id": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "code": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50
                              },
                              "firstName": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 150
                              },
                              "lastName": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 150
                              }
                            }
                          },
                          "quote": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "uuid",
                              "number",
                              "status",
                              "title",
                              "totalPrice",
                              "dueDate"
                            ],
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 30,
                                "description": "Numéro métier lisible."
                              },
                              "status": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50,
                                "description": "Statut public normalisé."
                              },
                              "title": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 250
                              },
                              "totalPrice": {
                                "type": [
                                  "null",
                                  "number"
                                ]
                              },
                              "dueDate": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "format": "date"
                              }
                            }
                          },
                          "media": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": false,
                              "required": [
                                "type",
                                "url",
                                "isMain"
                              ],
                              "properties": {
                                "type": {
                                  "type": "string",
                                  "enum": [
                                    "image"
                                  ]
                                },
                                "url": {
                                  "type": "string",
                                  "minLength": 1
                                },
                                "isMain": {
                                  "type": "boolean"
                                }
                              }
                            }
                          },
                          "createdAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "format": "date-time",
                            "description": "Date de création au format ISO 8601."
                          },
                          "updatedAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "format": "date-time",
                            "description": "Date de dernière modification au format ISO 8601."
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "page",
                        "limit",
                        "count",
                        "total",
                        "totalPages",
                        "hasNextPage"
                      ],
                      "properties": {
                        "page": {
                          "type": "integer",
                          "description": "Numéro de la page courante."
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Taille maximale de la page."
                        },
                        "count": {
                          "type": "integer",
                          "description": "Nombre d’éléments présents dans cette page."
                        },
                        "total": {
                          "type": "integer",
                          "description": "Nombre total d’éléments correspondant aux filtres."
                        },
                        "totalPages": {
                          "type": "integer",
                          "description": "Nombre total de pages."
                        },
                        "hasNextPage": {
                          "type": "boolean",
                          "description": "Indique si une page suivante existe."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listSavCases",
        "description": "Recherche paginée des dossiers SAV, notamment par client. Les filtres couvrent statut, boutique, texte, période et date de mise à jour. Les inclusions ajoutent les relations nécessaires au canal externe.\n\n**Permissions obligatoires (toutes)** : `sav:read`.\n\n**Permissions conditionnelles** :\n- `customers:pii:read` pour les coordonnées client.\n- `customer-credits:read` pour les acomptes détaillés.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "sav:read"
          ],
          "anyOf": [],
          "conditional": [
            "`customers:pii:read` pour les coordonnées client.",
            "`customer-credits:read` pour les acomptes détaillés."
          ]
        }
      }
    },
    "/v1/sav/{savId}": {
      "get": {
        "summary": "Consulter un dossier SAV",
        "tags": [
          "SAV"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 150
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Valeurs autorisées : customer, shop, seller, contact, quote, credits, media"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "path",
            "name": "savId",
            "required": true,
            "description": "Identifiant public stable du dossier SAV.",
            "example": "sav_01HZX8K5M6"
          }
        ],
        "responses": {
          "200": {
            "description": "Détail du dossier SAV.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "uuid",
                    "number",
                    "status",
                    "typeToDo",
                    "toDo",
                    "product",
                    "price",
                    "priceExclTax",
                    "deposit",
                    "remainingAmount",
                    "paid",
                    "currency",
                    "dates",
                    "warranty",
                    "createdAt",
                    "updatedAt"
                  ],
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 36,
                      "description": "Identifiant public stable de la ressource."
                    },
                    "number": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50,
                      "description": "Numéro métier lisible."
                    },
                    "status": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 50,
                      "description": "Statut public normalisé."
                    },
                    "typeToDo": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50
                    },
                    "toDo": {
                      "type": [
                        "null",
                        "string"
                      ]
                    },
                    "product": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "nameReference",
                        "reference",
                        "code",
                        "serialNumber",
                        "material",
                        "characteristics",
                        "weight",
                        "condition"
                      ],
                      "properties": {
                        "nameReference": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 300
                        },
                        "reference": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "code": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "serialNumber": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "material": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "characteristics": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 300
                        },
                        "weight": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "condition": {
                          "type": [
                            "null",
                            "string"
                          ]
                        }
                      }
                    },
                    "price": {
                      "type": [
                        "null",
                        "number"
                      ],
                      "description": "Prix de base faisant foi sur l’article."
                    },
                    "priceExclTax": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "deposit": {
                      "type": "number"
                    },
                    "remainingAmount": {
                      "type": [
                        "null",
                        "number"
                      ]
                    },
                    "paid": {
                      "type": "boolean"
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "EUR"
                      ],
                      "description": "Devise monétaire ISO 4217.",
                      "example": "EUR"
                    },
                    "dates": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "deposit",
                        "availability",
                        "delivery",
                        "reception",
                        "return",
                        "validation",
                        "warranty"
                      ],
                      "properties": {
                        "deposit": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "format": "date"
                        },
                        "availability": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "format": "date"
                        },
                        "delivery": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "format": "date"
                        },
                        "reception": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "format": "date"
                        },
                        "return": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "format": "date"
                        },
                        "validation": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "format": "date"
                        },
                        "warranty": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "format": "date"
                        }
                      }
                    },
                    "warranty": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 50
                    },
                    "customer": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "uuid",
                        "number",
                        "firstName",
                        "lastName"
                      ],
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "number": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 30,
                          "description": "Numéro métier lisible."
                        },
                        "firstName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "lastName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "email": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 254
                        },
                        "phone": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        }
                      }
                    },
                    "shop": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "name"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "name": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        }
                      },
                      "description": "Identifiant public historique de la boutique."
                    },
                    "seller": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "code",
                        "firstName",
                        "lastName"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "code": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "firstName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 150
                        },
                        "lastName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 150
                        }
                      }
                    },
                    "contact": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "id",
                        "firstName",
                        "lastName",
                        "function",
                        "supplier"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "firstName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "lastName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "function": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 150
                        },
                        "supplier": {
                          "type": [
                            "null",
                            "object"
                          ],
                          "additionalProperties": false,
                          "required": [
                            "id",
                            "name"
                          ],
                          "properties": {
                            "id": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 36,
                              "description": "Identifiant public stable de la ressource."
                            },
                            "name": {
                              "type": [
                                "null",
                                "string"
                              ],
                              "maxLength": 50
                            }
                          }
                        }
                      }
                    },
                    "quote": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "uuid",
                        "number",
                        "status",
                        "title",
                        "totalPrice",
                        "dueDate"
                      ],
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "number": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 30,
                          "description": "Numéro métier lisible."
                        },
                        "status": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50,
                          "description": "Statut public normalisé."
                        },
                        "title": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 250
                        },
                        "totalPrice": {
                          "type": [
                            "null",
                            "number"
                          ]
                        },
                        "dueDate": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "format": "date"
                        }
                      }
                    },
                    "credits": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "number",
                          "type",
                          "amount",
                          "amountLeft",
                          "status"
                        ],
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 36,
                            "description": "Identifiant public stable de la ressource."
                          },
                          "number": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 50,
                            "description": "Numéro métier lisible."
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "deposit"
                            ]
                          },
                          "amount": {
                            "type": "number",
                            "description": "Montant monétaire en EUR."
                          },
                          "amountLeft": {
                            "type": "number",
                            "description": "Solde encore consommable."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "used",
                              "expired",
                              "cancelled"
                            ],
                            "description": "Statut public normalisé."
                          }
                        }
                      }
                    },
                    "media": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "type",
                          "url",
                          "isMain"
                        ],
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "image"
                            ]
                          },
                          "url": {
                            "type": "string",
                            "minLength": 1
                          },
                          "isMain": {
                            "type": "boolean"
                          }
                        }
                      }
                    },
                    "createdAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "date-time",
                      "description": "Date de création au format ISO 8601."
                    },
                    "updatedAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "date-time",
                      "description": "Date de dernière modification au format ISO 8601."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "getSavCase",
        "description": "Retourne le suivi complet du dossier : statut public, produit, intervention, montants, dates, garantie et relations demandées. Les coordonnées et crédits restent conditionnés par leurs permissions dédiées.\n\n**Permissions obligatoires (toutes)** : `sav:read`.\n\n**Permissions conditionnelles** :\n- `customers:pii:read` pour les coordonnées client.\n- `customer-credits:read` pour les acomptes détaillés.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "sav:read"
          ],
          "anyOf": [],
          "conditional": [
            "`customers:pii:read` pour les coordonnées client.",
            "`customer-credits:read` pour les acomptes détaillés."
          ]
        }
      }
    },
    "/v1/sav/{savId}/log": {
      "get": {
        "summary": "Consulter le journal public d’un SAV",
        "tags": [
          "SAV"
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "in": "query",
            "name": "page",
            "required": false,
            "description": "Numéro de page, à partir de 1.",
            "example": 1
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "in": "query",
            "name": "limit",
            "required": false,
            "description": "Nombre maximal de résultats retournés par page.",
            "example": 50
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time",
              "maxLength": 50
            },
            "in": "query",
            "name": "from",
            "required": false,
            "description": "Début de la période recherchée, au format ISO 8601.",
            "example": "2026-01-01T00:00:00.000Z"
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time",
              "maxLength": 50
            },
            "in": "query",
            "name": "to",
            "required": false,
            "description": "Fin de la période recherchée, au format ISO 8601.",
            "example": "2026-12-31T23:59:59.999Z"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "path",
            "name": "savId",
            "required": true,
            "description": "Identifiant public stable du dossier SAV.",
            "example": "sav_01HZX8K5M6"
          }
        ],
        "responses": {
          "200": {
            "description": "Journal paginé des changements de statut.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "sav",
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "sav": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "uuid",
                        "number",
                        "status"
                      ],
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "number": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50,
                          "description": "Numéro métier lisible."
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "pending",
                            "quoting",
                            "quote",
                            "quote_accepted",
                            "refused",
                            "in_progress",
                            "ready",
                            "done",
                            "cancelled"
                          ],
                          "description": "Statut public normalisé."
                        }
                      }
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "occurredAt",
                          "type",
                          "previousStatus",
                          "status",
                          "label"
                        ],
                        "properties": {
                          "uuid": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 36,
                            "description": "Identifiant public stable de la ressource."
                          },
                          "occurredAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "status_changed"
                            ]
                          },
                          "previousStatus": {
                            "anyOf": [
                              {
                                "type": "null"
                              },
                              {
                                "type": "string",
                                "enum": [
                                  "pending",
                                  "quoting",
                                  "quote",
                                  "quote_accepted",
                                  "refused",
                                  "in_progress",
                                  "ready",
                                  "done",
                                  "cancelled"
                                ]
                              }
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "quoting",
                              "quote",
                              "quote_accepted",
                              "refused",
                              "in_progress",
                              "ready",
                              "done",
                              "cancelled"
                            ],
                            "description": "Statut public normalisé."
                          },
                          "label": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 100
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "additionalProperties": false,
                      "required": [
                        "page",
                        "limit",
                        "count",
                        "total",
                        "totalPages",
                        "hasNextPage"
                      ],
                      "properties": {
                        "page": {
                          "type": "integer",
                          "description": "Numéro de la page courante."
                        },
                        "limit": {
                          "type": "integer",
                          "description": "Taille maximale de la page."
                        },
                        "count": {
                          "type": "integer",
                          "description": "Nombre d’éléments présents dans cette page."
                        },
                        "total": {
                          "type": "integer",
                          "description": "Nombre total d’éléments correspondant aux filtres."
                        },
                        "totalPages": {
                          "type": "integer",
                          "description": "Nombre total de pages."
                        },
                        "hasNextPage": {
                          "type": "boolean",
                          "description": "Indique si une page suivante existe."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listSavStatusLog",
        "description": "Retourne les transitions de statut du dossier, de la plus récente à la plus ancienne. Les événements techniques et informations internes ne sont pas exposés.\n\n**Permissions obligatoires (toutes)** : `sav:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "sav:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/sav/{savId}/slip": {
      "get": {
        "summary": "Télécharger le bon SAV PDF",
        "tags": [
          "SAV"
        ],
        "parameters": [
          {
            "schema": {
              "type": "boolean",
              "default": true
            },
            "in": "query",
            "name": "download",
            "required": false,
            "description": "Si vrai, demande `Content-Disposition: attachment` ; sinon `inline`.",
            "example": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36
            },
            "in": "path",
            "name": "savId",
            "required": true,
            "description": "Identifiant public stable du dossier SAV.",
            "example": "sav_01HZX8K5M6"
          }
        ],
        "responses": {
          "200": {
            "description": "Flux PDF du bon SAV.",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            },
            "headers": {
              "Content-Disposition": {
                "description": "`attachment` lorsque `download=true`, sinon `inline`.",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "Politique de cache appliquée au document privé.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Content-Type-Options": {
                "description": "Protection contre l’interprétation d’un autre type MIME.",
                "schema": {
                  "type": "string",
                  "example": "nosniff"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "downloadSavSlip",
        "description": "Génère le bon SAV avec le moteur documentaire natif. `download=true` produit une pièce jointe ; `download=false` demande un affichage inline. Le flux est un PDF binaire privé et non mis en cache.\n\n**Permissions obligatoires (toutes)** : `sav:read`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "sav:read"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/gift-cards/{giftCardId}": {
      "get": {
        "summary": "Consulter une carte cadeau",
        "tags": [
          "Cartes cadeaux"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "in": "query",
            "name": "include",
            "required": false,
            "description": "Inclusions autorisées : customer, origin, usages, invoice."
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36,
              "pattern": "^[A-Za-z0-9_-]+$"
            },
            "in": "path",
            "name": "giftCardId",
            "required": true,
            "description": "Identifiant public stable de la carte cadeau.",
            "example": "gift_card_001"
          }
        ],
        "responses": {
          "200": {
            "description": "Détail public de la carte cadeau et relations explicitement autorisées.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "uuid",
                    "number",
                    "type",
                    "amount",
                    "amountLeft",
                    "currency",
                    "status",
                    "expiredAt",
                    "createdAt",
                    "updatedAt"
                  ],
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 36,
                      "description": "Identifiant public stable de la ressource."
                    },
                    "number": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 25,
                      "description": "Numéro métier lisible."
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "gift_card"
                      ]
                    },
                    "amount": {
                      "type": "number",
                      "description": "Montant monétaire en EUR."
                    },
                    "amountLeft": {
                      "type": "number",
                      "description": "Solde encore consommable."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "EUR"
                      ],
                      "description": "Devise monétaire ISO 4217.",
                      "example": "EUR"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "used",
                        "expired",
                        "cancelled"
                      ],
                      "description": "Statut public normalisé."
                    },
                    "expiredAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "date",
                      "description": "Date d’expiration au format ISO 8601, ou null lorsqu’aucune échéance ne s’applique."
                    },
                    "customer": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "uuid",
                        "number",
                        "firstName",
                        "lastName"
                      ],
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "number": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 30,
                          "description": "Numéro métier lisible."
                        },
                        "firstName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        },
                        "lastName": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50
                        }
                      }
                    },
                    "origin": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "type",
                        "uuid",
                        "number"
                      ],
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": [
                            "sale"
                          ]
                        },
                        "uuid": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "number": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50,
                          "description": "Numéro métier lisible."
                        }
                      },
                      "description": "Ressource métier à l’origine de la donnée."
                    },
                    "usages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "uuid",
                          "amount",
                          "usedAt",
                          "sale"
                        ],
                        "properties": {
                          "uuid": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "maxLength": 36,
                            "description": "Identifiant public stable de la ressource."
                          },
                          "amount": {
                            "type": "number",
                            "description": "Montant monétaire en EUR."
                          },
                          "usedAt": {
                            "type": [
                              "null",
                              "string"
                            ],
                            "format": "date-time",
                            "description": "Horodatage de l’utilisation de la carte cadeau."
                          },
                          "sale": {
                            "type": [
                              "null",
                              "object"
                            ],
                            "additionalProperties": false,
                            "required": [
                              "uuid",
                              "number"
                            ],
                            "properties": {
                              "uuid": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 36,
                                "description": "Identifiant public stable de la ressource."
                              },
                              "number": {
                                "type": [
                                  "null",
                                  "string"
                                ],
                                "maxLength": 50,
                                "description": "Numéro métier lisible."
                              }
                            }
                          }
                        },
                        "description": "Mouvements d’utilisation connus, ordonnés chronologiquement."
                      },
                      "description": "Mouvements d’utilisation connus, ordonnés chronologiquement."
                    },
                    "invoice": {
                      "type": [
                        "null",
                        "object"
                      ],
                      "additionalProperties": false,
                      "required": [
                        "uuid",
                        "number"
                      ],
                      "properties": {
                        "uuid": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 36,
                          "description": "Identifiant public stable de la ressource."
                        },
                        "number": {
                          "type": [
                            "null",
                            "string"
                          ],
                          "maxLength": 50,
                          "description": "Numéro métier lisible."
                        }
                      },
                      "description": "Document de vente public associé, lorsqu’il existe."
                    },
                    "createdAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "date-time",
                      "description": "Date de création au format ISO 8601."
                    },
                    "updatedAt": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "date-time",
                      "description": "Date de dernière modification au format ISO 8601."
                    }
                  }
                },
                "example": {
                  "uuid": "gift_card_001",
                  "number": "AB**-****-1842",
                  "type": "gift_card",
                  "amount": 200,
                  "amountLeft": 125,
                  "currency": "EUR",
                  "status": "active",
                  "expiredAt": "2027-07-31",
                  "customer": {
                    "uuid": "customer_001",
                    "number": "CLI-0001842",
                    "firstName": "Alice",
                    "lastName": "Martin"
                  },
                  "origin": {
                    "type": "sale",
                    "uuid": "sale_gift_001",
                    "number": "V-2026-00170"
                  },
                  "usages": [
                    {
                      "uuid": "gift_usage_001",
                      "amount": 75,
                      "usedAt": "2026-07-15T12:00:00.000Z",
                      "sale": {
                        "uuid": "sale_2026_001",
                        "number": "V-2026-00184"
                      }
                    }
                  ],
                  "invoice": {
                    "uuid": "invoice_gift_001",
                    "number": "F-2026-00170"
                  },
                  "createdAt": "2026-07-01T10:00:00.000Z",
                  "updatedAt": "2026-07-15T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "getGiftCard",
        "description": "Retourne une carte cadeau identifiée par son UUID public. Le numéro demeure partiellement masqué dans tous les cas et `amountLeft` constitue le solde de référence. Les relations sont absentes par défaut ; `include` permet de demander le bénéficiaire, la vente d’origine, les utilisations ou la facture sans exposer de code secret ni d’identifiant SQL.\n\n**Permissions obligatoires (toutes)** : `gift-cards:read`.\n\n**Permissions conditionnelles** :\n- `customers:read` pour `include=customer` ; le bloc est omis sans cette permission.\n- `sales:read` pour `include=origin`, `include=usages` ou `include=invoice` ; les blocs sont omis sans cette permission.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "gift-cards:read"
          ],
          "anyOf": [],
          "conditional": [
            "`customers:read` pour `include=customer` ; le bloc est omis sans cette permission.",
            "`sales:read` pour `include=origin`, `include=usages` ou `include=invoice` ; les blocs sont omis sans cette permission."
          ]
        }
      },
      "put": {
        "summary": "Débiter une carte cadeau",
        "tags": [
          "Cartes cadeaux"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "operation",
                  "amount",
                  "currency"
                ],
                "properties": {
                  "operation": {
                    "type": "string",
                    "enum": [
                      "debit"
                    ],
                    "description": "Nature de l’écriture demandée. Seule la valeur `debit` est acceptée sur cette route."
                  },
                  "amount": {
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "maximum": 99999999.99,
                    "multipleOf": 0.01,
                    "description": "Montant monétaire en EUR."
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "EUR"
                    ],
                    "description": "Devise monétaire ISO 4217.",
                    "example": "EUR"
                  },
                  "saleId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 36,
                    "pattern": "^[A-Za-z0-9_-]+$",
                    "description": "Identifiant public de la vente à laquelle rattacher l’utilisation, lorsqu’elle existe."
                  },
                  "externalReference": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100,
                    "pattern": "^[A-Za-z0-9][A-Za-z0-9._:/-]*$",
                    "description": "Référence stable fournie par le système consommateur."
                  }
                }
              },
              "example": {
                "operation": "debit",
                "amount": 25,
                "currency": "EUR",
                "saleId": "sale_01HZX8K5M6",
                "externalReference": "WEB-COMMANDE-58421"
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 36,
              "pattern": "^[A-Za-z0-9_-]+$"
            },
            "in": "path",
            "name": "giftCardId",
            "required": true,
            "description": "Identifiant public stable de la carte cadeau.",
            "example": "gift_card_001"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128,
              "pattern": "^[\\x21-\\x7E]+$"
            },
            "in": "header",
            "name": "idempotency-key",
            "required": true,
            "description": "Clé ASCII stable de 8 à 128 caractères. Pendant la fenêtre de rétention configurée (24 heures par défaut), la même clé avec le même corps rejoue la réponse et un corps différent provoque un conflit. Après expiration, la clé est considérée comme nouvelle.",
            "example": "web-transaction-58421"
          }
        ],
        "responses": {
          "200": {
            "description": "Carte débitée, ou réponse du premier débit rejouée de manière idempotente.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "uuid",
                    "number",
                    "type",
                    "debitedAmount",
                    "amountLeft",
                    "currency",
                    "status",
                    "updatedAt"
                  ],
                  "properties": {
                    "uuid": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 36,
                      "description": "Identifiant public stable de la ressource."
                    },
                    "number": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "maxLength": 25,
                      "description": "Numéro métier lisible."
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "gift_card"
                      ]
                    },
                    "debitedAmount": {
                      "type": "number",
                      "exclusiveMinimum": 0,
                      "description": "Montant effectivement débité par cette opération."
                    },
                    "amountLeft": {
                      "type": "number",
                      "minimum": 0,
                      "description": "Solde encore consommable."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "EUR"
                      ],
                      "description": "Devise monétaire ISO 4217.",
                      "example": "EUR"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "used"
                      ],
                      "description": "Statut public normalisé."
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Date de dernière modification au format ISO 8601."
                    }
                  }
                },
                "example": {
                  "uuid": "gift_card_001",
                  "number": "AB**-****-1842",
                  "type": "gift_card",
                  "debitedAmount": 25,
                  "amountLeft": 100,
                  "currency": "EUR",
                  "status": "active",
                  "updatedAt": "2026-07-19T15:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "debitGiftCard",
        "description": "Débite atomiquement le solde faisant foi d’une carte cadeau. Le service verrouille la carte, recalcule son statut et son expiration, puis recontrôle le solde avant de créer une ligne d’utilisation native Commerce 360. `saleId` permet d’associer cette utilisation à une vente compatible ; sans vente, le mouvement reste traçable sur la carte. Une même `Idempotency-Key` avec le même identifiant et le même corps rejoue exactement la première réponse sans nouveau débit. La même clé avec des données différentes retourne un conflit. Cette route ne permet ni crédit, ni remboursement, et n’expose jamais le code complet de la carte.\n\n**Permissions obligatoires (toutes)** : `gift-cards:write`.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [
            "gift-cards:write"
          ],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/auth": {
      "post": {
        "tags": [
          "Authentification"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "password"
                ],
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "email": "api@example.com",
                "password": "mot-de-passe"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authentification réussie. Le jeton JWT peut être utilisé jusqu’à son expiration.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "token"
                  ],
                  "properties": {
                    "token": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        },
        "operationId": "authenticateExternalApiConsumer",
        "summary": "Obtenir un jeton JWT",
        "description": "Authentifie un compte API Commerce 360 avec son adresse email et son mot de passe. Le jeton retourné doit être envoyé dans l’entête `Authorization: Bearer <token>` des routes protégées. Les permissions restent portées par le compte authentifié.",
        "security": [],
        "x-required-scopes": {
          "allOf": [],
          "anyOf": [],
          "conditional": []
        }
      }
    },
    "/v1/ping": {
      "get": {
        "tags": [
          "Système"
        ],
        "responses": {
          "200": {
            "description": "L’API V1 répond correctement.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "version",
                    "pong"
                  ],
                  "properties": {
                    "version": {
                      "type": "string"
                    },
                    "pong": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "version": "v1",
                  "pong": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "pingExternalApiV1",
        "summary": "Vérifier la version de l’API V1",
        "description": "Retourne une réponse minimale après authentification. Cette opération vérifie le routage V1 et le jeton, mais ne contrôle pas l’accès à une base métier particulière.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scopes": {
          "allOf": [],
          "anyOf": [],
          "conditional": []
        }
      }
    }
  },
  "servers": [
    {
      "url": "https://api.hbjo-online.com",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Authentification",
      "description": "Obtention du jeton JWT utilisé par toutes les opérations protégées."
    },
    {
      "name": "Système",
      "description": "Vérification simple de la version et de la disponibilité logique de l’API V1."
    },
    {
      "name": "Catalogue",
      "description": "Vue catalogue agrégée et flux incrémental pour synchroniser un canal de vente externe."
    },
    {
      "name": "Produits",
      "description": "Références produits, articles physiques, prix faisant foi et stock disponible calculé."
    },
    {
      "name": "Référentiels",
      "description": "Catégories, types, caractéristiques, valeurs et boutiques utiles à l’interprétation du catalogue."
    },
    {
      "name": "Clients",
      "description": "Recherche, consultation, création et remplacement de fiches clients et de leur historique."
    },
    {
      "name": "Ventes",
      "description": "Recherche et consultation des ventes, métadonnées de facture et téléchargement du PDF officiel."
    },
    {
      "name": "SAV",
      "description": "Recherche et suivi des dossiers SAV, journal public et génération du bon SAV."
    },
    {
      "name": "Cartes cadeaux",
      "description": "Consultation sécurisée des cartes cadeaux, de leur solde faisant foi et de leurs relations autorisées."
    }
  ],
  "externalDocs": {
    "description": "Guides d’intégration Commerce 360",
    "url": "https://developers.hbjo-online.com/docs/getting-started"
  },
  "security": [
    {
      "bearerAuth": []
    }
  ]
}
