{
  "openapi": "3.1.0",
  "info": {
    "title": "Cercla - API d'intégration",
    "version": "1.0.0",
    "description": "Surface REST v1 du CRM (docs/08-API.md). Deux modes d'auth : OAuth2 client_credentials (apps connectées, scopes) ou session utilisateur Better Auth portée en Bearer (app mobile - permissions et visibilité de l'utilisateur, §2bis). Erreurs problem+json (RFC 9457), pagination par curseur opaque, idempotence par header Idempotency-Key sur les POST d'app."
  },
  "servers": [
    {
      "url": "/api/v1"
    }
  ],
  "paths": {
    "/ping": {
      "get": {
        "summary": "Smoke-test intégrateur - contexte du token présenté",
        "description": "Retourne l'app authentifiée, son user d'intégration et les scopes du token. Premier appel à faire pour vérifier une intégration de bout en bout.",
        "tags": [
          "Diagnostic"
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Contexte de l'app authentifiée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "appName": {
                      "type": "string"
                    },
                    "integrationUser": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "name": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "email"
                      ],
                      "additionalProperties": false
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "referentials:read",
                          "referentials:write",
                          "companies:read",
                          "companies:write",
                          "contacts:read",
                          "contacts:write",
                          "products:read",
                          "products:write",
                          "quotes:read",
                          "quotes:write",
                          "invoices:read",
                          "invoices:write",
                          "requests:read",
                          "requests:write",
                          "sales_activities:read",
                          "sales_activities:write",
                          "signatures:read",
                          "signatures:write",
                          "webhooks:manage",
                          "exports:read",
                          "users:read",
                          "users:write",
                          "marketing:read",
                          "marketing:write",
                          "documents:read",
                          "settings:write"
                        ]
                      }
                    }
                  },
                  "required": [
                    "ok",
                    "appName",
                    "integrationUser",
                    "scopes"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/documents": {
      "get": {
        "summary": "Lister les documents rattachés et produits",
        "description": "Métadonnées sous documents:read et le scope de lecture de chaque porteur. Applications désactivées et fiches hors périmètre exclues. Tri croissant par date et identifiant. Dates de filtre en UTC. Aucun contenu ni lien public dans la réponse.",
        "tags": [
          "Documents"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "object",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "company",
                "contact",
                "quote",
                "contract",
                "request",
                "invoice",
                "order",
                "product"
              ]
            }
          },
          {
            "name": "id",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "minLength": 1,
              "maxLength": 40
            }
          },
          {
            "name": "authorId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            }
          },
          {
            "name": "shared",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "documents:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de documents",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "fileId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "filename": {
                            "type": "string"
                          },
                          "mime": {
                            "type": "string"
                          },
                          "size": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "type": {
                            "type": "string"
                          },
                          "objectType": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact",
                              "quote",
                              "contract",
                              "request",
                              "invoice",
                              "order",
                              "product"
                            ]
                          },
                          "objectId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "carrierLabel": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "authorId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "authorName": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "sharedAtPortal": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "id",
                          "fileId",
                          "filename",
                          "mime",
                          "size",
                          "label",
                          "type",
                          "objectType",
                          "objectId",
                          "carrierLabel",
                          "authorId",
                          "authorName",
                          "createdAt",
                          "sharedAtPortal"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/meta": {
      "get": {
        "summary": "Bootstrap metadata-driven de l'instance (ADR-104)",
        "description": "Sans Authorization : méta PUBLIQUE (identité visuelle du login + contrat de version) - aucune donnée métier, pas de liste de modules. Avec un Bearer valide (session utilisateur §2bis ou token d'app) : méta COMPLÈTE (modules actifs, branding et labels runtime, capacités, entités). Un Bearer invalide répond 401 - jamais de dégradation silencieuse vers la forme publique.",
        "tags": [
          "meta"
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Méta publique (anonyme) ou complète (authentifié)",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Nom de l'instance (productName)"
                        },
                        "version": {
                          "type": "string",
                          "description": "Version produit de l'instance (semver ADR-097)"
                        },
                        "minAppVersion": {
                          "type": "string",
                          "description": "Version minimale de l'app mobile supportée - l'app compare et dégrade explicitement"
                        },
                        "logo": {
                          "type": "string"
                        },
                        "logoOnBrand": {
                          "type": "string"
                        },
                        "colors": {
                          "type": "object",
                          "properties": {
                            "primary": {
                              "type": "string"
                            },
                            "primaryAccent": {
                              "type": "string"
                            },
                            "soft": {
                              "type": "string"
                            },
                            "dark": {
                              "type": "string"
                            },
                            "background": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "primary",
                            "primaryAccent",
                            "soft",
                            "dark",
                            "background"
                          ],
                          "additionalProperties": false
                        },
                        "sso": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "google",
                              "microsoft"
                            ]
                          },
                          "description": "Providers SSO actifs sur l'instance (T-762) - le login n'affiche que ceux-là"
                        },
                        "auth": {
                          "type": "object",
                          "properties": {
                            "loginUrl": {
                              "type": "string",
                              "description": "Entrée de la connexion mobile par le navigateur système (T-1020, ADR-141 D5) : GET <loginUrl>?redirect=<scheme de retour de l'app> ; au retour, POST /api/auth/handoff/mobile { token }"
                            }
                          },
                          "required": [
                            "loginUrl"
                          ],
                          "additionalProperties": false,
                          "description": "Connexion de l'app : aucun mot de passe, passkey ou code d'application dans le navigateur système"
                        }
                      },
                      "required": [
                        "name",
                        "version",
                        "minAppVersion",
                        "logo",
                        "logoOnBrand",
                        "colors",
                        "sso",
                        "auth"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Nom de l'instance (productName)"
                        },
                        "version": {
                          "type": "string",
                          "description": "Version produit de l'instance (semver ADR-097)"
                        },
                        "minAppVersion": {
                          "type": "string",
                          "description": "Version minimale de l'app mobile supportée - l'app compare et dégrade explicitement"
                        },
                        "logo": {
                          "type": "string"
                        },
                        "logoOnBrand": {
                          "type": "string"
                        },
                        "colors": {
                          "type": "object",
                          "properties": {
                            "primary": {
                              "type": "string"
                            },
                            "primaryAccent": {
                              "type": "string"
                            },
                            "soft": {
                              "type": "string"
                            },
                            "dark": {
                              "type": "string"
                            },
                            "background": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "primary",
                            "primaryAccent",
                            "soft",
                            "dark",
                            "background"
                          ],
                          "additionalProperties": false
                        },
                        "sso": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "google",
                              "microsoft"
                            ]
                          },
                          "description": "Providers SSO actifs sur l'instance (T-762) - le login n'affiche que ceux-là"
                        },
                        "auth": {
                          "type": "object",
                          "properties": {
                            "loginUrl": {
                              "type": "string"
                            },
                            "loginMethod": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "enum": [
                                    "passkey",
                                    "passkey_or_totp"
                                  ]
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Méthode de connexion du compte (T-1017, ADR-141 D3) : passkey (défaut) ou passkey_or_totp (mode élargi posé par un admin - l'app propose alors la gestion du code d'application). Null pour une app connectée."
                            }
                          },
                          "required": [
                            "loginUrl",
                            "loginMethod"
                          ],
                          "additionalProperties": false
                        },
                        "logoCompact": {
                          "type": "string"
                        },
                        "locale": {
                          "type": "string"
                        },
                        "currency": {
                          "type": "string"
                        },
                        "labels": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {
                            "type": "object",
                            "properties": {
                              "singular": {
                                "type": "string"
                              },
                              "plural": {
                                "type": "string"
                              },
                              "all": {
                                "type": "string"
                              },
                              "create": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "singular",
                              "plural"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Labels du glossaire (cycle, businessUnit, resource, objets renommables)"
                        },
                        "fieldLabels": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        },
                        "modules": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {
                            "type": "boolean"
                          },
                          "description": "Modules actifs de l'instance - la navigation de l'app s'en déduit"
                        },
                        "capabilities": {
                          "type": "object",
                          "properties": {
                            "pdfDownload": {
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "pdfDownload"
                          ],
                          "additionalProperties": false
                        },
                        "businessUnits": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              "name": {
                                "type": "string"
                              },
                              "shortName": {
                                "type": "string"
                              },
                              "color": {
                                "type": "string"
                              },
                              "logo": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "id",
                              "name",
                              "shortName",
                              "color",
                              "logo"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "quoteLossReasons": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Motifs de perte d'un devis de l'organisation (#651), dans l'ordre des réglages, « Autre » compris : la transition vers refused exige l'un d'eux en lossReason."
                        }
                      },
                      "required": [
                        "name",
                        "version",
                        "minAppVersion",
                        "logo",
                        "logoOnBrand",
                        "colors",
                        "sso",
                        "auth",
                        "logoCompact",
                        "locale",
                        "currency",
                        "labels",
                        "fieldLabels",
                        "modules",
                        "capabilities",
                        "businessUnits",
                        "quoteLossReasons"
                      ],
                      "additionalProperties": false
                    }
                  ]
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/cycles": {
      "get": {
        "summary": "Cycles de vente (référentiel, lecture seule)",
        "tags": [
          "Référentiels"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "referentials:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de cycles",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "endsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "upcoming",
                              "active",
                              "closed"
                            ],
                            "description": "Dérivé des bornes à la date du jour"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "startsOn",
                          "endsOn",
                          "status",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/business-units": {
      "get": {
        "summary": "Entités de vente (référentiel)",
        "tags": [
          "Référentiels"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "referentials:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page d'entités",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "shortName": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string"
                          },
                          "address": {
                            "type": "string"
                          },
                          "legalName": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "siret": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "vatNumber": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "iban": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "bic": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "legalMentions": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "shortName",
                          "color",
                          "address",
                          "legalName",
                          "siret",
                          "vatNumber",
                          "iban",
                          "bic",
                          "legalMentions",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/business-units/{id}": {
      "get": {
        "summary": "Détail d'une entité",
        "tags": [
          "Référentiels"
        ],
        "security": [
          {
            "oauth2": [
              "referentials:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Entité",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "shortName": {
                      "type": "string"
                    },
                    "color": {
                      "type": "string"
                    },
                    "address": {
                      "type": "string"
                    },
                    "legalName": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "siret": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "vatNumber": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "iban": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "bic": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "legalMentions": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "shortName",
                    "color",
                    "address",
                    "legalName",
                    "siret",
                    "vatNumber",
                    "iban",
                    "bic",
                    "legalMentions",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Identité légale & bancaire d'une entité (T-302)",
        "tags": [
          "Référentiels"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "legalName": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 120
                      }
                    ]
                  },
                  "siret": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 60
                      }
                    ]
                  },
                  "vatNumber": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 60
                      }
                    ]
                  },
                  "iban": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 60
                      }
                    ]
                  },
                  "bic": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 60
                      }
                    ]
                  },
                  "legalMentions": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 2000
                      }
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "referentials:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Entité modifiée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "shortName": {
                      "type": "string"
                    },
                    "color": {
                      "type": "string"
                    },
                    "address": {
                      "type": "string"
                    },
                    "legalName": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "siret": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "vatNumber": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "iban": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "bic": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "legalMentions": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "shortName",
                    "color",
                    "address",
                    "legalName",
                    "siret",
                    "vatNumber",
                    "iban",
                    "bic",
                    "legalMentions",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/sectors": {
      "get": {
        "summary": "Secteurs d'activité (référentiel court, une page complète)",
        "tags": [
          "Référentiels"
        ],
        "security": [
          {
            "oauth2": [
              "referentials:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Tous les secteurs du déploiement",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Libellés de secteurs - company.sector est un texte libre"
                    },
                    "nextCursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/company-relations": {
      "get": {
        "summary": "Natures de relation des sociétés (référentiel court, une page complète)",
        "tags": [
          "Référentiels"
        ],
        "security": [
          {
            "oauth2": [
              "referentials:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "La liste de l'organisation (défaut : partenaire, fournisseur, concurrent, prescripteur, sous-traitant)",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "key",
                          "label"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Natures de relation de l'organisation, dans l'ordre de la liste ; `key` est la valeur de company.relations"
                    },
                    "nextCursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/users": {
      "get": {
        "summary": "Utilisateurs (référentiel, lecture seule - sans email)",
        "tags": [
          "Référentiels"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "referentials:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page d'utilisateurs",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "title": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "admin",
                              "manager",
                              "sales",
                              "finance",
                              "reader",
                              "marketing",
                              "project",
                              "staff",
                              "integration"
                            ]
                          },
                          "active": {
                            "type": "boolean"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "title",
                          "role",
                          "active",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/companies": {
      "get": {
        "summary": "Lister les sociétés (hors corbeille)",
        "tags": [
          "Sociétés"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Jours (1 à 365) - objets dans leur statut courant depuis plus de N jours (status_changed_at), combinable avec status (T-1407)",
              "type": "integer",
              "minimum": 1,
              "maximum": 365
            }
          },
          {
            "name": "ids",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Répétable - restriction à une liste d'ids (max 200)",
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Recherche sur le nom (même logique que l'UI)",
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "prospect",
                "active",
                "inactive"
              ]
            }
          },
          {
            "name": "sector",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Secteur exact (référentiel /sectors)",
              "type": "string"
            }
          },
          {
            "name": "relation",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "#494 : porte cette nature de relation (clé du référentiel /company-relations)",
              "type": "string"
            }
          },
          {
            "name": "externalId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Objets qui portent cet identifiant externe (exact) - avec `externalSource` pour une source précise",
              "type": "string"
            }
          },
          {
            "name": "externalSource",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Source de l'identifiant externe (`tacto`…)",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "companies:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de sociétés",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "sector": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "prospect",
                              "active",
                              "inactive"
                            ]
                          },
                          "logo": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "logoFromReference": {
                            "type": "boolean"
                          },
                          "ownerId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "parentCompanyId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "siret": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "vatNumber": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "vatStatus": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "valid",
                                  "invalid",
                                  "unavailable"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "T-1401 : verdict VIES du numéro de TVA, null = jamais vérifié ; lecture seule"
                          },
                          "vatCheckedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "T-1401 : dernière vérification VIES, null = jamais"
                          },
                          "website": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "websiteFromReference": {
                            "type": "boolean"
                          },
                          "linkedin": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "x": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "instagram": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "billingAddress": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "paymentTerms": {
                            "description": "Note de règlement, texte libre (#998)",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "salesAlert": {
                            "description": "#971 : alerte commerciale interne, jamais montrée au client",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "creditLimitCents": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#978 : plafond d'encours TTC en centimes, null = sans plafond ; l'encours n'est jamais exposé"
                          },
                          "paymentCondition": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "days",
                                      "days_end_of_month",
                                      "end_of_month_then_day"
                                    ]
                                  },
                                  "days": {
                                    "type": "integer",
                                    "minimum": 0,
                                    "maximum": 365
                                  },
                                  "dayOfNextMonth": {
                                    "anyOf": [
                                      {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 31
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  }
                                },
                                "required": [
                                  "type",
                                  "days",
                                  "dayOfNextMonth"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#998 : condition de paiement propre { type, days, dayOfNextMonth }, null = celle de l'organisation"
                          },
                          "externalCodes": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          },
                          "customFields": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {
                              "type": [
                                "string",
                                "number",
                                "boolean"
                              ]
                            }
                          },
                          "relations": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "#494 (ADR-203 D3) : natures de relation déclarées (partenaire, concurrent…), indépendantes du statut calculé"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "statusChangedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                            "description": "Entrée dans le statut courant (T-1407)"
                          },
                          "engagedUntil": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Fin d'engagement : max ends_on des contrats vivants (T-1410), null sans contrat"
                          },
                          "externalRefs": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "source": {
                                  "type": "string",
                                  "description": "Système source (minuscules) - `tacto`, `erp`…"
                                },
                                "externalId": {
                                  "type": "string"
                                },
                                "sourceUpdatedAt": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "date-time",
                                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ],
                                  "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                                }
                              },
                              "required": [
                                "source",
                                "externalId",
                                "sourceUpdatedAt"
                              ],
                              "additionalProperties": false
                            },
                            "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                          },
                          "displayStatus": {
                            "type": "string",
                            "enum": [
                              "prospect",
                              "active",
                              "inactive",
                              "supplier"
                            ],
                            "description": "#921 : statut affiché. `supplier` = société sans fait client qui porte un profil fournisseur actif (module Achats) ; `status` reste le statut calculé d'ADR-193"
                          },
                          "supplier": {
                            "description": "#921 : profil fournisseur ; absent module Achats éteint ou sans droit de lecture sur `supplier`",
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "active": {
                                    "type": "boolean"
                                  },
                                  "paymentDays": {
                                    "anyOf": [
                                      {
                                        "type": "integer",
                                        "minimum": -9007199254740991,
                                        "maximum": 9007199254740991
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "currency": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "leadTimeDays": {
                                    "anyOf": [
                                      {
                                        "type": "integer",
                                        "minimum": -9007199254740991,
                                        "maximum": 9007199254740991
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "ourReference": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "auxCodes": {
                                    "type": "object",
                                    "propertyNames": {
                                      "type": "string",
                                      "format": "uuid",
                                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                    },
                                    "additionalProperties": {
                                      "type": "string"
                                    },
                                    "description": "Compte auxiliaire fournisseur (401) par entité"
                                  },
                                  "notes": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "createdAt": {
                                    "type": "string",
                                    "format": "date-time",
                                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                  }
                                },
                                "required": [
                                  "active",
                                  "paymentDays",
                                  "currency",
                                  "leadTimeDays",
                                  "ourReference",
                                  "auxCodes",
                                  "notes",
                                  "createdAt"
                                ],
                                "additionalProperties": false,
                                "description": "#921 : profil fournisseur de la société (module Achats), null si elle n'en porte pas"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "sector",
                          "status",
                          "logo",
                          "logoFromReference",
                          "parentCompanyId",
                          "siret",
                          "vatNumber",
                          "vatStatus",
                          "vatCheckedAt",
                          "website",
                          "websiteFromReference",
                          "linkedin",
                          "x",
                          "instagram",
                          "billingAddress",
                          "paymentTerms",
                          "salesAlert",
                          "creditLimitCents",
                          "paymentCondition",
                          "externalCodes",
                          "customFields",
                          "relations",
                          "createdAt",
                          "updatedAt",
                          "statusChangedAt",
                          "engagedUntil",
                          "displayStatus"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Créer une société (règles UI : dédup, champs custom, hiérarchie)",
        "description": "Naît en statut prospect. Dédup T-257 : en mode warn, la création aboutit avec `duplicateWarning` ; en mode block, un doublon fort (même SIREN) répond 409.",
        "tags": [
          "Sociétés"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 200
                  },
                  "ownerId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "sector": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 80
                      }
                    ]
                  },
                  "parentCompanyId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "siret": {
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "vatNumber": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 40
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "website": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 200
                      }
                    ]
                  },
                  "linkedin": {
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "x": {
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "instagram": {
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "billingAddress": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 300
                      }
                    ]
                  },
                  "customFields": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "maxLength": 80
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 2000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "externalCodes": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "null"
                        },
                        {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 40,
                          "pattern": "^[A-Za-z0-9._-]+$"
                        }
                      ]
                    }
                  },
                  "relations": {
                    "description": "#494 : natures de relation (clés de la liste d'organisation, GET /company-relations) ; remplace la liste, [] retire tout",
                    "maxItems": 30,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^[a-z0-9][a-z0-9-]{0,39}$"
                    }
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "companies:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Société créée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "sector": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "prospect",
                        "active",
                        "inactive"
                      ]
                    },
                    "logo": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "logoFromReference": {
                      "type": "boolean"
                    },
                    "ownerId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "parentCompanyId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "siret": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "vatNumber": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "vatStatus": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "valid",
                            "invalid",
                            "unavailable"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "T-1401 : verdict VIES du numéro de TVA, null = jamais vérifié ; lecture seule"
                    },
                    "vatCheckedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "T-1401 : dernière vérification VIES, null = jamais"
                    },
                    "website": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "websiteFromReference": {
                      "type": "boolean"
                    },
                    "linkedin": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "x": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "instagram": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "billingAddress": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "paymentTerms": {
                      "description": "Note de règlement, texte libre (#998)",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "salesAlert": {
                      "description": "#971 : alerte commerciale interne, jamais montrée au client",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "creditLimitCents": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#978 : plafond d'encours TTC en centimes, null = sans plafond ; l'encours n'est jamais exposé"
                    },
                    "paymentCondition": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "days",
                                "days_end_of_month",
                                "end_of_month_then_day"
                              ]
                            },
                            "days": {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 365
                            },
                            "dayOfNextMonth": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": 1,
                                  "maximum": 31
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "type",
                            "days",
                            "dayOfNextMonth"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#998 : condition de paiement propre { type, days, dayOfNextMonth }, null = celle de l'organisation"
                    },
                    "externalCodes": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      "additionalProperties": {
                        "type": "string"
                      }
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "relations": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "#494 (ADR-203 D3) : natures de relation déclarées (partenaire, concurrent…), indépendantes du statut calculé"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "engagedUntil": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Fin d'engagement : max ends_on des contrats vivants (T-1410), null sans contrat"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "displayStatus": {
                      "type": "string",
                      "enum": [
                        "prospect",
                        "active",
                        "inactive",
                        "supplier"
                      ],
                      "description": "#921 : statut affiché. `supplier` = société sans fait client qui porte un profil fournisseur actif (module Achats) ; `status` reste le statut calculé d'ADR-193"
                    },
                    "supplier": {
                      "description": "#921 : profil fournisseur ; absent module Achats éteint ou sans droit de lecture sur `supplier`",
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "active": {
                              "type": "boolean"
                            },
                            "paymentDays": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "currency": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "leadTimeDays": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "ourReference": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "auxCodes": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              "additionalProperties": {
                                "type": "string"
                              },
                              "description": "Compte auxiliaire fournisseur (401) par entité"
                            },
                            "notes": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "createdAt": {
                              "type": "string",
                              "format": "date-time",
                              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                            }
                          },
                          "required": [
                            "active",
                            "paymentDays",
                            "currency",
                            "leadTimeDays",
                            "ourReference",
                            "auxCodes",
                            "notes",
                            "createdAt"
                          ],
                          "additionalProperties": false,
                          "description": "#921 : profil fournisseur de la société (module Achats), null si elle n'en porte pas"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "duplicateWarning": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "name": {
                          "type": "string"
                        },
                        "severity": {
                          "type": "string",
                          "enum": [
                            "strong",
                            "medium"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "severity"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "sector",
                    "status",
                    "logo",
                    "logoFromReference",
                    "parentCompanyId",
                    "siret",
                    "vatNumber",
                    "vatStatus",
                    "vatCheckedAt",
                    "website",
                    "websiteFromReference",
                    "linkedin",
                    "x",
                    "instagram",
                    "billingAddress",
                    "paymentTerms",
                    "salesAlert",
                    "creditLimitCents",
                    "paymentCondition",
                    "externalCodes",
                    "customFields",
                    "relations",
                    "createdAt",
                    "updatedAt",
                    "statusChangedAt",
                    "engagedUntil",
                    "displayStatus"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/companies/{id}": {
      "get": {
        "summary": "Détail d'une société",
        "description": "`include` (répétable - T-687, fiche mobile) : contacts, quotes, activity, notes. Chaque bloc embarqué respecte la visibilité du principal ; absent = réponse historique inchangée.",
        "tags": [
          "Sociétés"
        ],
        "parameters": [
          {
            "name": "include",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Bloc à embarquer (répétable) - fiche en un appel",
              "type": "string",
              "enum": [
                "contacts",
                "quotes",
                "activity",
                "notes"
              ]
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "companies:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Société (+ blocs demandés)",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "sector": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "prospect",
                        "active",
                        "inactive"
                      ]
                    },
                    "logo": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "logoFromReference": {
                      "type": "boolean"
                    },
                    "ownerId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "parentCompanyId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "siret": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "vatNumber": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "vatStatus": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "valid",
                            "invalid",
                            "unavailable"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "T-1401 : verdict VIES du numéro de TVA, null = jamais vérifié ; lecture seule"
                    },
                    "vatCheckedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "T-1401 : dernière vérification VIES, null = jamais"
                    },
                    "website": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "websiteFromReference": {
                      "type": "boolean"
                    },
                    "linkedin": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "x": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "instagram": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "billingAddress": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "paymentTerms": {
                      "description": "Note de règlement, texte libre (#998)",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "salesAlert": {
                      "description": "#971 : alerte commerciale interne, jamais montrée au client",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "creditLimitCents": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#978 : plafond d'encours TTC en centimes, null = sans plafond ; l'encours n'est jamais exposé"
                    },
                    "paymentCondition": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "days",
                                "days_end_of_month",
                                "end_of_month_then_day"
                              ]
                            },
                            "days": {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 365
                            },
                            "dayOfNextMonth": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": 1,
                                  "maximum": 31
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "type",
                            "days",
                            "dayOfNextMonth"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#998 : condition de paiement propre { type, days, dayOfNextMonth }, null = celle de l'organisation"
                    },
                    "externalCodes": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      "additionalProperties": {
                        "type": "string"
                      }
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "relations": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "#494 (ADR-203 D3) : natures de relation déclarées (partenaire, concurrent…), indépendantes du statut calculé"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "engagedUntil": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Fin d'engagement : max ends_on des contrats vivants (T-1410), null sans contrat"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "displayStatus": {
                      "type": "string",
                      "enum": [
                        "prospect",
                        "active",
                        "inactive",
                        "supplier"
                      ],
                      "description": "#921 : statut affiché. `supplier` = société sans fait client qui porte un profil fournisseur actif (module Achats) ; `status` reste le statut calculé d'ADR-193"
                    },
                    "supplier": {
                      "description": "#921 : profil fournisseur ; absent module Achats éteint ou sans droit de lecture sur `supplier`",
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "active": {
                              "type": "boolean"
                            },
                            "paymentDays": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "currency": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "leadTimeDays": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "ourReference": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "auxCodes": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              "additionalProperties": {
                                "type": "string"
                              },
                              "description": "Compte auxiliaire fournisseur (401) par entité"
                            },
                            "notes": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "createdAt": {
                              "type": "string",
                              "format": "date-time",
                              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                            }
                          },
                          "required": [
                            "active",
                            "paymentDays",
                            "currency",
                            "leadTimeDays",
                            "ourReference",
                            "auxCodes",
                            "notes",
                            "createdAt"
                          ],
                          "additionalProperties": false,
                          "description": "#921 : profil fournisseur de la société (module Achats), null si elle n'en porte pas"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "contacts": {
                      "description": "Bloc `include=contacts` - contacts affiliés actifs",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "affiliationId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "contactId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "firstName": {
                            "type": "string"
                          },
                          "lastName": {
                            "type": "string"
                          },
                          "email": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "phone": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "title": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "principal",
                              "operational",
                              "billing",
                              "other"
                            ]
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          }
                        },
                        "required": [
                          "affiliationId",
                          "contactId",
                          "firstName",
                          "lastName",
                          "email",
                          "phone",
                          "title",
                          "role",
                          "startsOn"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "quotes": {
                      "description": "Bloc `include=quotes` - devis de la société, visibilité devis appliquée",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "tags": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                },
                                "name": {
                                  "type": "string"
                                },
                                "color": {
                                  "type": "string",
                                  "enum": [
                                    "brand",
                                    "comp",
                                    "blend",
                                    "muted",
                                    "deep"
                                  ]
                                }
                              },
                              "required": [
                                "id",
                                "name",
                                "color"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "number": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "sent",
                              "negotiation",
                              "signed",
                              "refused"
                            ]
                          },
                          "targetType": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact"
                            ]
                          },
                          "targetId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "ownerId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "lostToCompanyId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "expectedSignOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "forecastConfidence": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "possible",
                                  "probable",
                                  "quasi_certain"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "forecastComment": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "subject": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "commitment": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "Engagement pluriannuel - nombre de cycles couverts"
                          },
                          "priced": {
                            "type": "boolean",
                            "description": "#747 : faux = « Non chiffré », aucune ligne chiffrée (hors lignes de texte) ; les montants valent alors 0 et ne sont pas un vrai zéro"
                          },
                          "serviceOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Date de prestation d'un devis ponctuel (T-1412) - null : devis par cycle"
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "totalInclTax": {
                            "type": "string"
                          },
                          "currency": {
                            "type": "string",
                            "minLength": 3,
                            "maxLength": 3,
                            "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                          },
                          "fxRate": {
                            "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "fxRateDate": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Jour de publication du taux figé - null en euros"
                          },
                          "totalExclTaxEur": {
                            "type": "string",
                            "description": "Contre-valeur en euros du HT au taux figé"
                          },
                          "totalInclTaxEur": {
                            "type": "string",
                            "description": "Contre-valeur en euros du TTC au taux figé"
                          },
                          "createdOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "sentOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "signedOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "validUntil": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Date de validité de l'offre (E183 #511) - null : sans échéance"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "statusChangedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                            "description": "Entrée dans le statut courant (T-1407)"
                          },
                          "portalViewedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#758 : première consultation au portail par un contact du client ; null : jamais ouvert"
                          },
                          "portalLastViewedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#758 : dernière consultation au portail"
                          },
                          "portalViewCount": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "#758 : nombre de consultations au portail (fiche et PDF)"
                          },
                          "alternativeGroupId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#753 : groupe d'alternatives (propositions simultanées pour une même vente) ; null : vente seule"
                          },
                          "alternativeReference": {
                            "type": "boolean",
                            "description": "#753 : proposition qui compte au pipeline dans son groupe (une par groupe, choisie par le commercial)"
                          },
                          "externalRefs": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "source": {
                                  "type": "string",
                                  "description": "Système source (minuscules) - `tacto`, `erp`…"
                                },
                                "externalId": {
                                  "type": "string"
                                },
                                "sourceUpdatedAt": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "date-time",
                                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ],
                                  "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                                }
                              },
                              "required": [
                                "source",
                                "externalId",
                                "sourceUpdatedAt"
                              ],
                              "additionalProperties": false
                            },
                            "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                          }
                        },
                        "required": [
                          "tags",
                          "id",
                          "number",
                          "version",
                          "status",
                          "targetType",
                          "targetId",
                          "ownerId",
                          "lostToCompanyId",
                          "expectedSignOn",
                          "forecastConfidence",
                          "forecastComment",
                          "subject",
                          "commitment",
                          "priced",
                          "serviceOn",
                          "totalExclTax",
                          "totalInclTax",
                          "currency",
                          "fxRate",
                          "fxRateDate",
                          "totalExclTaxEur",
                          "totalInclTaxEur",
                          "createdOn",
                          "sentOn",
                          "signedOn",
                          "validUntil",
                          "updatedAt",
                          "statusChangedAt",
                          "portalViewedAt",
                          "portalLastViewedAt",
                          "portalViewCount",
                          "alternativeGroupId",
                          "alternativeReference"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "activity": {
                      "description": "Bloc `include=activity` - fil d'activité, 20 derniers",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "quote_created",
                              "quote_sent",
                              "quote_signed",
                              "invoice_issued",
                              "invoice_paid",
                              "invoice_late",
                              "mail_in",
                              "mail_out",
                              "note",
                              "record_updated",
                              "call_logged",
                              "meeting_held",
                              "task"
                            ]
                          },
                          "occurredAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "ref": {
                            "description": "N° du devis ou de la facture concerné",
                            "type": "string"
                          },
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "amount": {
                            "type": "number"
                          },
                          "note": {
                            "type": "string"
                          },
                          "title": {
                            "description": "Titre de l'activité commerciale",
                            "type": "string"
                          },
                          "outcome": {
                            "type": "string",
                            "enum": [
                              "done",
                              "cancelled"
                            ]
                          },
                          "author": {
                            "type": "string"
                          },
                          "mail": {
                            "type": "object",
                            "properties": {
                              "subject": {
                                "type": "string"
                              },
                              "from": {
                                "type": "string"
                              },
                              "to": {
                                "type": "string"
                              },
                              "preview": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "subject",
                              "from",
                              "to",
                              "preview"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "kind",
                          "occurredAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "notes": {
                      "description": "Bloc `include=notes` - notes de la fiche, même forme que /comments",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "authorId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "authorName": {
                            "type": "string"
                          },
                          "authorAvatar": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "body": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "authorId",
                          "authorName",
                          "authorAvatar",
                          "body",
                          "createdAt"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "sector",
                    "status",
                    "logo",
                    "logoFromReference",
                    "parentCompanyId",
                    "siret",
                    "vatNumber",
                    "vatStatus",
                    "vatCheckedAt",
                    "website",
                    "websiteFromReference",
                    "linkedin",
                    "x",
                    "instagram",
                    "billingAddress",
                    "paymentTerms",
                    "salesAlert",
                    "creditLimitCents",
                    "paymentCondition",
                    "externalCodes",
                    "customFields",
                    "relations",
                    "createdAt",
                    "updatedAt",
                    "statusChangedAt",
                    "engagedUntil",
                    "displayStatus"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Modifier une société (patch partiel - champs omis intacts)",
        "tags": [
          "Sociétés"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 200
                  },
                  "ownerId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "sector": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 80
                      }
                    ]
                  },
                  "parentCompanyId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "siret": {
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "vatNumber": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 40
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "website": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 200
                      }
                    ]
                  },
                  "linkedin": {
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "x": {
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "instagram": {
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "billingAddress": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 300
                      }
                    ]
                  },
                  "customFields": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "maxLength": 80
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 2000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "externalCodes": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "null"
                        },
                        {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 40,
                          "pattern": "^[A-Za-z0-9._-]+$"
                        }
                      ]
                    }
                  },
                  "relations": {
                    "description": "#494 : natures de relation (clés de la liste d'organisation, GET /company-relations) ; remplace la liste, [] retire tout",
                    "maxItems": 30,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^[a-z0-9][a-z0-9-]{0,39}$"
                    }
                  },
                  "paymentTerms": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 120
                      }
                    ]
                  },
                  "salesAlert": {
                    "description": "#971 : alerte commerciale interne, dite en tête des devis de la société ; null l'efface",
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 300
                      }
                    ]
                  },
                  "creditLimitCents": {
                    "anyOf": [
                      {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 2000000000,
                        "description": "Plafond d'encours TTC en centimes ; null = sans plafond (#978)"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "paymentCondition": {
                    "anyOf": [
                      {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "days",
                              "days_end_of_month",
                              "end_of_month_then_day"
                            ]
                          },
                          "days": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 365
                          },
                          "dayOfNextMonth": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": 1,
                                "maximum": 31
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "type",
                          "days",
                          "dayOfNextMonth"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "supplier": {
                    "description": "#921 : profil fournisseur, écriture partielle ; refusé module Achats éteint (422)",
                    "type": "object",
                    "properties": {
                      "active": {
                        "type": "boolean"
                      },
                      "paymentDays": {
                        "anyOf": [
                          {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 365
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "currency": {
                        "anyOf": [
                          {
                            "type": "string",
                            "enum": [
                              "EUR",
                              "USD",
                              "GBP",
                              "CHF"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "leadTimeDays": {
                        "anyOf": [
                          {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 365
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "ourReference": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 60
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "auxCodes": {
                        "type": "object",
                        "propertyNames": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "additionalProperties": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 40,
                          "pattern": "^[A-Za-z0-9._-]+$"
                        }
                      },
                      "notes": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 2000
                          },
                          {
                            "type": "null"
                          }
                        ]
                      }
                    },
                    "additionalProperties": false
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "companies:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Société modifiée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "sector": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "prospect",
                        "active",
                        "inactive"
                      ]
                    },
                    "logo": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "logoFromReference": {
                      "type": "boolean"
                    },
                    "ownerId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "parentCompanyId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "siret": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "vatNumber": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "vatStatus": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "valid",
                            "invalid",
                            "unavailable"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "T-1401 : verdict VIES du numéro de TVA, null = jamais vérifié ; lecture seule"
                    },
                    "vatCheckedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "T-1401 : dernière vérification VIES, null = jamais"
                    },
                    "website": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "websiteFromReference": {
                      "type": "boolean"
                    },
                    "linkedin": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "x": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "instagram": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "billingAddress": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "paymentTerms": {
                      "description": "Note de règlement, texte libre (#998)",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "salesAlert": {
                      "description": "#971 : alerte commerciale interne, jamais montrée au client",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "creditLimitCents": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#978 : plafond d'encours TTC en centimes, null = sans plafond ; l'encours n'est jamais exposé"
                    },
                    "paymentCondition": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "days",
                                "days_end_of_month",
                                "end_of_month_then_day"
                              ]
                            },
                            "days": {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 365
                            },
                            "dayOfNextMonth": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": 1,
                                  "maximum": 31
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "type",
                            "days",
                            "dayOfNextMonth"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#998 : condition de paiement propre { type, days, dayOfNextMonth }, null = celle de l'organisation"
                    },
                    "externalCodes": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      "additionalProperties": {
                        "type": "string"
                      }
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "relations": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "#494 (ADR-203 D3) : natures de relation déclarées (partenaire, concurrent…), indépendantes du statut calculé"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "engagedUntil": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Fin d'engagement : max ends_on des contrats vivants (T-1410), null sans contrat"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "displayStatus": {
                      "type": "string",
                      "enum": [
                        "prospect",
                        "active",
                        "inactive",
                        "supplier"
                      ],
                      "description": "#921 : statut affiché. `supplier` = société sans fait client qui porte un profil fournisseur actif (module Achats) ; `status` reste le statut calculé d'ADR-193"
                    },
                    "supplier": {
                      "description": "#921 : profil fournisseur ; absent module Achats éteint ou sans droit de lecture sur `supplier`",
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "active": {
                              "type": "boolean"
                            },
                            "paymentDays": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "currency": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "leadTimeDays": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "ourReference": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "auxCodes": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              "additionalProperties": {
                                "type": "string"
                              },
                              "description": "Compte auxiliaire fournisseur (401) par entité"
                            },
                            "notes": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "createdAt": {
                              "type": "string",
                              "format": "date-time",
                              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                            }
                          },
                          "required": [
                            "active",
                            "paymentDays",
                            "currency",
                            "leadTimeDays",
                            "ourReference",
                            "auxCodes",
                            "notes",
                            "createdAt"
                          ],
                          "additionalProperties": false,
                          "description": "#921 : profil fournisseur de la société (module Achats), null si elle n'en porte pas"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "duplicateWarning": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "name": {
                          "type": "string"
                        },
                        "severity": {
                          "type": "string",
                          "enum": [
                            "strong",
                            "medium"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "severity"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "sector",
                    "status",
                    "logo",
                    "logoFromReference",
                    "parentCompanyId",
                    "siret",
                    "vatNumber",
                    "vatStatus",
                    "vatCheckedAt",
                    "website",
                    "websiteFromReference",
                    "linkedin",
                    "x",
                    "instagram",
                    "billingAddress",
                    "paymentTerms",
                    "salesAlert",
                    "creditLimitCents",
                    "paymentCondition",
                    "externalCodes",
                    "customFields",
                    "relations",
                    "createdAt",
                    "updatedAt",
                    "statusChangedAt",
                    "engagedUntil",
                    "displayStatus"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Mettre à la corbeille (soft delete T-261 - jamais de hard delete)",
        "description": "Refusé (409) si des devis ou factures ciblent la société. Restauration dans Paramètres > Corbeille.",
        "tags": [
          "Sociétés"
        ],
        "security": [
          {
            "oauth2": [
              "companies:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Société mise à la corbeille",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/contacts": {
      "get": {
        "summary": "Lister les contacts (hors corbeille)",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          },
          {
            "name": "ids",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Répétable - restriction à une liste d'ids (max 200)",
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Recherche sur prénom, nom ou email",
              "type": "string"
            }
          },
          {
            "name": "externalId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Objets qui portent cet identifiant externe (exact) - avec `externalSource` pour une source précise",
              "type": "string"
            }
          },
          {
            "name": "externalSource",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Source de l'identifiant externe (`tacto`…)",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "contacts:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de contacts",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "salutation": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "mr",
                                  "mrs"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "firstName": {
                            "type": "string"
                          },
                          "lastName": {
                            "type": "string"
                          },
                          "email": {
                            "description": "Adresse PRINCIPALE du contact (T-809 : multi-emails - la fiche peut porter d'autres adresses, ce champ reste le miroir de la principale).",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "phone": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "title": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "avatar": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "linkedin": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "birthday": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Date de naissance « YYYY-MM-DD », null = inconnue"
                          },
                          "timeZone": {
                            "description": "Fuseau IANA explicitement connu ; null = inconnu, jamais déduit du pays",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "addressLine1": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "addressLine2": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "postalCode": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "city": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "country": {
                            "description": "Code pays ISO 3166-1 alpha-2",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "customFields": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {
                              "type": [
                                "string",
                                "number",
                                "boolean"
                              ]
                            }
                          },
                          "doNotContact": {
                            "type": "boolean",
                            "description": "Opposition RGPD : le contact ne doit pas être sollicité (E183 #514, badge « Ne pas contacter » à côté de l'email)"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "externalRefs": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "source": {
                                  "type": "string",
                                  "description": "Système source (minuscules) - `tacto`, `erp`…"
                                },
                                "externalId": {
                                  "type": "string"
                                },
                                "sourceUpdatedAt": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "date-time",
                                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ],
                                  "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                                }
                              },
                              "required": [
                                "source",
                                "externalId",
                                "sourceUpdatedAt"
                              ],
                              "additionalProperties": false
                            },
                            "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                          }
                        },
                        "required": [
                          "id",
                          "salutation",
                          "firstName",
                          "lastName",
                          "email",
                          "phone",
                          "title",
                          "avatar",
                          "linkedin",
                          "birthday",
                          "timeZone",
                          "addressLine1",
                          "addressLine2",
                          "postalCode",
                          "city",
                          "country",
                          "customFields",
                          "doNotContact",
                          "createdAt",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Créer un contact (affiliation initiale optionnelle, transactionnelle)",
        "description": "Dédup T-257 : fort = même email (409 en mode block), sinon `duplicateWarning`. companyId + role créent l'affiliation initiale dans la même transaction.",
        "tags": [
          "Contacts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "salutation": {
                    "anyOf": [
                      {
                        "type": "string",
                        "const": ""
                      },
                      {
                        "type": "string",
                        "enum": [
                          "mr",
                          "mrs"
                        ]
                      }
                    ]
                  },
                  "firstName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "lastName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                  },
                  "phone": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 30
                      }
                    ]
                  },
                  "title": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 120
                      }
                    ]
                  },
                  "linkedin": {
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "birthday": {
                    "description": "Date de naissance « YYYY-MM-DD », jamais future ; null = inconnue",
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "timeZone": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 100
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "addressLine1": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 160
                      }
                    ]
                  },
                  "addressLine2": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 160
                      }
                    ]
                  },
                  "postalCode": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 16
                      }
                    ]
                  },
                  "city": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 120
                      }
                    ]
                  },
                  "country": {
                    "description": "Code pays ISO 3166-1 alpha-2",
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "companyId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "principal",
                      "operational",
                      "billing",
                      "other"
                    ]
                  },
                  "startsOn": {
                    "type": "string",
                    "format": "date",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                  },
                  "customFields": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "maxLength": 80
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 2000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  }
                },
                "required": [
                  "firstName",
                  "lastName",
                  "email"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "contacts:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Contact créé",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "salutation": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "mr",
                            "mrs"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "firstName": {
                      "type": "string"
                    },
                    "lastName": {
                      "type": "string"
                    },
                    "email": {
                      "description": "Adresse PRINCIPALE du contact (T-809 : multi-emails - la fiche peut porter d'autres adresses, ce champ reste le miroir de la principale).",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "phone": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "title": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "avatar": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "linkedin": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "birthday": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de naissance « YYYY-MM-DD », null = inconnue"
                    },
                    "timeZone": {
                      "description": "Fuseau IANA explicitement connu ; null = inconnu, jamais déduit du pays",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "addressLine1": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "addressLine2": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "postalCode": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "city": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "country": {
                      "description": "Code pays ISO 3166-1 alpha-2",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "doNotContact": {
                      "type": "boolean",
                      "description": "Opposition RGPD : le contact ne doit pas être sollicité (E183 #514, badge « Ne pas contacter » à côté de l'email)"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "duplicateWarning": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "name": {
                          "type": "string"
                        },
                        "severity": {
                          "type": "string",
                          "enum": [
                            "strong",
                            "medium"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "severity"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "salutation",
                    "firstName",
                    "lastName",
                    "email",
                    "phone",
                    "title",
                    "avatar",
                    "linkedin",
                    "birthday",
                    "timeZone",
                    "addressLine1",
                    "addressLine2",
                    "postalCode",
                    "city",
                    "country",
                    "customFields",
                    "doNotContact",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/contacts/{id}": {
      "get": {
        "summary": "Détail d'un contact",
        "description": "`include` (répétable - T-687, fiche mobile) : affiliations (sociétés hors visibilité masquées), activity, notes (répond sous `noteEntries`, nom historique gardé pour les clients existants). Absent = réponse historique inchangée.",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "include",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Bloc à embarquer (répétable) - fiche en un appel",
              "type": "string",
              "enum": [
                "affiliations",
                "activity",
                "notes"
              ]
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "contacts:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Contact (+ blocs demandés)",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "salutation": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "mr",
                            "mrs"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "firstName": {
                      "type": "string"
                    },
                    "lastName": {
                      "type": "string"
                    },
                    "email": {
                      "description": "Adresse PRINCIPALE du contact (T-809 : multi-emails - la fiche peut porter d'autres adresses, ce champ reste le miroir de la principale).",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "phone": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "title": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "avatar": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "linkedin": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "birthday": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de naissance « YYYY-MM-DD », null = inconnue"
                    },
                    "timeZone": {
                      "description": "Fuseau IANA explicitement connu ; null = inconnu, jamais déduit du pays",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "addressLine1": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "addressLine2": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "postalCode": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "city": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "country": {
                      "description": "Code pays ISO 3166-1 alpha-2",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "doNotContact": {
                      "type": "boolean",
                      "description": "Opposition RGPD : le contact ne doit pas être sollicité (E183 #514, badge « Ne pas contacter » à côté de l'email)"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "affiliations": {
                      "description": "Bloc `include=affiliations` - sociétés hors visibilité masquées",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "affiliationId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "companyId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "companyName": {
                            "type": "string"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "principal",
                              "operational",
                              "billing",
                              "other"
                            ]
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "endsOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "affiliationId",
                          "companyId",
                          "companyName",
                          "role",
                          "startsOn",
                          "endsOn"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "activity": {
                      "description": "Bloc `include=activity` - fil d'activité, 20 derniers",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "quote_created",
                              "quote_sent",
                              "quote_signed",
                              "invoice_issued",
                              "invoice_paid",
                              "invoice_late",
                              "mail_in",
                              "mail_out",
                              "note",
                              "record_updated",
                              "call_logged",
                              "meeting_held",
                              "task"
                            ]
                          },
                          "occurredAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "ref": {
                            "description": "N° du devis ou de la facture concerné",
                            "type": "string"
                          },
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "amount": {
                            "type": "number"
                          },
                          "note": {
                            "type": "string"
                          },
                          "title": {
                            "description": "Titre de l'activité commerciale",
                            "type": "string"
                          },
                          "outcome": {
                            "type": "string",
                            "enum": [
                              "done",
                              "cancelled"
                            ]
                          },
                          "author": {
                            "type": "string"
                          },
                          "mail": {
                            "type": "object",
                            "properties": {
                              "subject": {
                                "type": "string"
                              },
                              "from": {
                                "type": "string"
                              },
                              "to": {
                                "type": "string"
                              },
                              "preview": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "subject",
                              "from",
                              "to",
                              "preview"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "kind",
                          "occurredAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "noteEntries": {
                      "description": "Bloc `include=notes` - notes de la fiche (même forme que /comments) ; répond sous `noteEntries` (nom historique, gardé pour les clients existants)",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "authorId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "authorName": {
                            "type": "string"
                          },
                          "authorAvatar": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "body": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "authorId",
                          "authorName",
                          "authorAvatar",
                          "body",
                          "createdAt"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "id",
                    "salutation",
                    "firstName",
                    "lastName",
                    "email",
                    "phone",
                    "title",
                    "avatar",
                    "linkedin",
                    "birthday",
                    "timeZone",
                    "addressLine1",
                    "addressLine2",
                    "postalCode",
                    "city",
                    "country",
                    "customFields",
                    "doNotContact",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Modifier un contact (patch partiel - champs omis intacts)",
        "tags": [
          "Contacts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "salutation": {
                    "anyOf": [
                      {
                        "type": "string",
                        "const": ""
                      },
                      {
                        "type": "string",
                        "enum": [
                          "mr",
                          "mrs"
                        ]
                      }
                    ]
                  },
                  "firstName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "lastName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                  },
                  "phone": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 30
                      }
                    ]
                  },
                  "title": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 120
                      }
                    ]
                  },
                  "linkedin": {
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "birthday": {
                    "description": "Date de naissance « YYYY-MM-DD », jamais future ; null = inconnue",
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "timeZone": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 100
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "addressLine1": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 160
                      }
                    ]
                  },
                  "addressLine2": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 160
                      }
                    ]
                  },
                  "postalCode": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 16
                      }
                    ]
                  },
                  "city": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 120
                      }
                    ]
                  },
                  "country": {
                    "description": "Code pays ISO 3166-1 alpha-2",
                    "type": [
                      "null",
                      "string"
                    ]
                  },
                  "customFields": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "maxLength": 80
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 2000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "contacts:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Contact modifié",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "salutation": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "mr",
                            "mrs"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "firstName": {
                      "type": "string"
                    },
                    "lastName": {
                      "type": "string"
                    },
                    "email": {
                      "description": "Adresse PRINCIPALE du contact (T-809 : multi-emails - la fiche peut porter d'autres adresses, ce champ reste le miroir de la principale).",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "phone": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "title": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "avatar": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "linkedin": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "birthday": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de naissance « YYYY-MM-DD », null = inconnue"
                    },
                    "timeZone": {
                      "description": "Fuseau IANA explicitement connu ; null = inconnu, jamais déduit du pays",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "addressLine1": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "addressLine2": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "postalCode": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "city": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "country": {
                      "description": "Code pays ISO 3166-1 alpha-2",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "doNotContact": {
                      "type": "boolean",
                      "description": "Opposition RGPD : le contact ne doit pas être sollicité (E183 #514, badge « Ne pas contacter » à côté de l'email)"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "duplicateWarning": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "name": {
                          "type": "string"
                        },
                        "severity": {
                          "type": "string",
                          "enum": [
                            "strong",
                            "medium"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "severity"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "salutation",
                    "firstName",
                    "lastName",
                    "email",
                    "phone",
                    "title",
                    "avatar",
                    "linkedin",
                    "birthday",
                    "timeZone",
                    "addressLine1",
                    "addressLine2",
                    "postalCode",
                    "city",
                    "country",
                    "customFields",
                    "doNotContact",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Mettre à la corbeille (soft delete T-261)",
        "description": "Refusé (409) si des devis ou factures référencent le contact.",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "oauth2": [
              "contacts:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Contact mis à la corbeille",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/affiliations": {
      "get": {
        "summary": "Lister les affiliations (hors corbeille)",
        "tags": [
          "Affiliations"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          },
          {
            "name": "ids",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Répétable - restriction à une liste d'ids (max 200)",
              "type": "string"
            }
          },
          {
            "name": "companyId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          },
          {
            "name": "contactId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "contacts:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page d'affiliations",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "contactId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "companyId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "principal",
                              "operational",
                              "billing",
                              "other"
                            ]
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "endsOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          }
                        },
                        "required": [
                          "id",
                          "contactId",
                          "companyId",
                          "role",
                          "startsOn",
                          "endsOn",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Créer une affiliation (doublon actif refusé, chevauchement 409)",
        "tags": [
          "Affiliations"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "contactId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "companyId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "principal",
                      "operational",
                      "billing",
                      "other"
                    ]
                  },
                  "startsOn": {
                    "description": "Défaut : date du jour",
                    "type": "string",
                    "format": "date",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                  }
                },
                "required": [
                  "contactId",
                  "companyId",
                  "role"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "contacts:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Affiliation créée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "contactId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "companyId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "role": {
                      "type": "string",
                      "enum": [
                        "principal",
                        "operational",
                        "billing",
                        "other"
                      ]
                    },
                    "startsOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                    },
                    "endsOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "contactId",
                    "companyId",
                    "role",
                    "startsOn",
                    "endsOn",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/affiliations/{id}": {
      "patch": {
        "summary": "Terminer une affiliation (poser endsOn - jamais supprimer)",
        "tags": [
          "Affiliations"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "endsOn": {
                    "type": "string",
                    "format": "date",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                  }
                },
                "required": [
                  "endsOn"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "contacts:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Affiliation terminée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "contactId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "companyId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "role": {
                      "type": "string",
                      "enum": [
                        "principal",
                        "operational",
                        "billing",
                        "other"
                      ]
                    },
                    "startsOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                    },
                    "endsOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "contactId",
                    "companyId",
                    "role",
                    "startsOn",
                    "endsOn",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Mettre à la corbeille (corriger une erreur de saisie)",
        "tags": [
          "Affiliations"
        ],
        "security": [
          {
            "oauth2": [
              "contacts:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Affiliation mise à la corbeille",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/products": {
      "get": {
        "summary": "Lister les produits du catalogue (hors corbeille)",
        "tags": [
          "Produits"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          },
          {
            "name": "ids",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Répétable - restriction à une liste d'ids (max 200)",
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Recherche sur le nom ou la référence",
              "type": "string"
            }
          },
          {
            "name": "businessUnitId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          },
          {
            "name": "active",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "products:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de produits",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "code": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "capacity": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "saleMode": {
                            "type": "string",
                            "enum": [
                              "per_cycle",
                              "one_off"
                            ],
                            "description": "T-1412 : par cycle ou ponctuel"
                          },
                          "active": {
                            "type": "boolean"
                          },
                          "prices": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                },
                                "label": {
                                  "type": "string"
                                },
                                "unitPrice": {
                                  "type": "string",
                                  "description": "HT, chaîne décimale à 2 décimales"
                                },
                                "vatRate": {
                                  "description": "Fraction stockée (0.20000) - null : taux du déploiement",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "description": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "quantityTiers": {
                                  "anyOf": [
                                    {
                                      "type": "array",
                                      "items": {
                                        "type": "object",
                                        "properties": {
                                          "minQuantity": {
                                            "type": "integer",
                                            "minimum": -9007199254740991,
                                            "maximum": 9007199254740991
                                          },
                                          "unitPrice": {
                                            "type": "number"
                                          },
                                          "discountPercent": {
                                            "type": "number"
                                          }
                                        },
                                        "required": [
                                          "minQuantity"
                                        ],
                                        "additionalProperties": false
                                      }
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ],
                                  "description": "#761 : paliers par quantité triés par seuil - null : aucun"
                                },
                                "sortOrder": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                "active": {
                                  "type": "boolean"
                                }
                              },
                              "required": [
                                "id",
                                "label",
                                "unitPrice",
                                "vatRate",
                                "description",
                                "quantityTiers",
                                "sortOrder",
                                "active"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "code",
                          "businessUnitId",
                          "capacity",
                          "saleMode",
                          "active",
                          "prices",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Créer un produit avec ses tarifs (≥ 1)",
        "tags": [
          "Produits"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "businessUnitId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "code": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 60
                      }
                    ]
                  },
                  "capacity": {
                    "anyOf": [
                      {
                        "type": "integer",
                        "exclusiveMinimum": 0,
                        "maximum": 9007199254740991
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "saleMode": {
                    "description": "T-1412 : par cycle (défaut) ou ponctuel, vendu à une date de prestation",
                    "type": "string",
                    "enum": [
                      "per_cycle",
                      "one_off"
                    ]
                  },
                  "active": {
                    "type": "boolean"
                  },
                  "prices": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "Présent = mise à jour du tarif, absent = création",
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "label": {
                          "type": "string",
                          "minLength": 1
                        },
                        "unitPrice": {
                          "type": "number",
                          "minimum": 0
                        },
                        "vatRatePercent": {
                          "description": "En POURCENT (20, 5.5) - null : taux du déploiement",
                          "anyOf": [
                            {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 100
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "description": {
                          "anyOf": [
                            {
                              "type": "null"
                            },
                            {
                              "type": "string",
                              "maxLength": 500
                            }
                          ]
                        },
                        "active": {
                          "type": "boolean"
                        },
                        "quantityTiers": {
                          "description": "#761 : paliers par quantité [{ minQuantity ≥ 2, unitPrice | discountPercent }] ; absent : grille gardée, null ou [] : aucun palier",
                          "anyOf": [
                            {
                              "maxItems": 20,
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "minQuantity": {
                                    "type": "integer",
                                    "minimum": 2,
                                    "maximum": 1000000
                                  },
                                  "unitPrice": {
                                    "type": "number",
                                    "exclusiveMinimum": 0,
                                    "maximum": 9999999999
                                  },
                                  "discountPercent": {
                                    "type": "number",
                                    "exclusiveMinimum": 0,
                                    "maximum": 100
                                  }
                                },
                                "required": [
                                  "minQuantity"
                                ],
                                "additionalProperties": false
                              }
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "label",
                        "unitPrice"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "name",
                  "businessUnitId",
                  "prices"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "products:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Produit créé",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "code": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "businessUnitId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "capacity": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "saleMode": {
                      "type": "string",
                      "enum": [
                        "per_cycle",
                        "one_off"
                      ],
                      "description": "T-1412 : par cycle ou ponctuel"
                    },
                    "active": {
                      "type": "boolean"
                    },
                    "prices": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "unitPrice": {
                            "type": "string",
                            "description": "HT, chaîne décimale à 2 décimales"
                          },
                          "vatRate": {
                            "description": "Fraction stockée (0.20000) - null : taux du déploiement",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "quantityTiers": {
                            "anyOf": [
                              {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "minQuantity": {
                                      "type": "integer",
                                      "minimum": -9007199254740991,
                                      "maximum": 9007199254740991
                                    },
                                    "unitPrice": {
                                      "type": "number"
                                    },
                                    "discountPercent": {
                                      "type": "number"
                                    }
                                  },
                                  "required": [
                                    "minQuantity"
                                  ],
                                  "additionalProperties": false
                                }
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#761 : paliers par quantité triés par seuil - null : aucun"
                          },
                          "sortOrder": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "active": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "unitPrice",
                          "vatRate",
                          "description",
                          "quantityTiers",
                          "sortOrder",
                          "active"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "code",
                    "businessUnitId",
                    "capacity",
                    "saleMode",
                    "active",
                    "prices",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/products/{id}": {
      "get": {
        "summary": "Détail d'un produit (tarifs inclus)",
        "tags": [
          "Produits"
        ],
        "security": [
          {
            "oauth2": [
              "products:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Produit",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "code": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "businessUnitId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "capacity": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "saleMode": {
                      "type": "string",
                      "enum": [
                        "per_cycle",
                        "one_off"
                      ],
                      "description": "T-1412 : par cycle ou ponctuel"
                    },
                    "active": {
                      "type": "boolean"
                    },
                    "prices": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "unitPrice": {
                            "type": "string",
                            "description": "HT, chaîne décimale à 2 décimales"
                          },
                          "vatRate": {
                            "description": "Fraction stockée (0.20000) - null : taux du déploiement",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "quantityTiers": {
                            "anyOf": [
                              {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "minQuantity": {
                                      "type": "integer",
                                      "minimum": -9007199254740991,
                                      "maximum": 9007199254740991
                                    },
                                    "unitPrice": {
                                      "type": "number"
                                    },
                                    "discountPercent": {
                                      "type": "number"
                                    }
                                  },
                                  "required": [
                                    "minQuantity"
                                  ],
                                  "additionalProperties": false
                                }
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#761 : paliers par quantité triés par seuil - null : aucun"
                          },
                          "sortOrder": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "active": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "unitPrice",
                          "vatRate",
                          "description",
                          "quantityTiers",
                          "sortOrder",
                          "active"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "code",
                    "businessUnitId",
                    "capacity",
                    "saleMode",
                    "active",
                    "prices",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Modifier un produit - `prices` fourni = l'ensemble des tarifs est remplacé",
        "description": "Patch partiel sur les champs du produit. Le tableau `prices`, s'il est fourni, devient l'ensemble complet (id présent = mise à jour, absent = création, manquant = retrait - refusé 409 si le tarif est référencé par un devis).",
        "tags": [
          "Produits"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "businessUnitId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "code": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 60
                      }
                    ]
                  },
                  "capacity": {
                    "anyOf": [
                      {
                        "type": "integer",
                        "exclusiveMinimum": 0,
                        "maximum": 9007199254740991
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "saleMode": {
                    "description": "T-1412 : par cycle (défaut) ou ponctuel, vendu à une date de prestation",
                    "type": "string",
                    "enum": [
                      "per_cycle",
                      "one_off"
                    ]
                  },
                  "active": {
                    "type": "boolean"
                  },
                  "prices": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "Présent = mise à jour du tarif, absent = création",
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "label": {
                          "type": "string",
                          "minLength": 1
                        },
                        "unitPrice": {
                          "type": "number",
                          "minimum": 0
                        },
                        "vatRatePercent": {
                          "description": "En POURCENT (20, 5.5) - null : taux du déploiement",
                          "anyOf": [
                            {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 100
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "description": {
                          "anyOf": [
                            {
                              "type": "null"
                            },
                            {
                              "type": "string",
                              "maxLength": 500
                            }
                          ]
                        },
                        "active": {
                          "type": "boolean"
                        },
                        "quantityTiers": {
                          "description": "#761 : paliers par quantité [{ minQuantity ≥ 2, unitPrice | discountPercent }] ; absent : grille gardée, null ou [] : aucun palier",
                          "anyOf": [
                            {
                              "maxItems": 20,
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "minQuantity": {
                                    "type": "integer",
                                    "minimum": 2,
                                    "maximum": 1000000
                                  },
                                  "unitPrice": {
                                    "type": "number",
                                    "exclusiveMinimum": 0,
                                    "maximum": 9999999999
                                  },
                                  "discountPercent": {
                                    "type": "number",
                                    "exclusiveMinimum": 0,
                                    "maximum": 100
                                  }
                                },
                                "required": [
                                  "minQuantity"
                                ],
                                "additionalProperties": false
                              }
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "label",
                        "unitPrice"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "products:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Produit modifié",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "code": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "businessUnitId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "capacity": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "saleMode": {
                      "type": "string",
                      "enum": [
                        "per_cycle",
                        "one_off"
                      ],
                      "description": "T-1412 : par cycle ou ponctuel"
                    },
                    "active": {
                      "type": "boolean"
                    },
                    "prices": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "unitPrice": {
                            "type": "string",
                            "description": "HT, chaîne décimale à 2 décimales"
                          },
                          "vatRate": {
                            "description": "Fraction stockée (0.20000) - null : taux du déploiement",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "quantityTiers": {
                            "anyOf": [
                              {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "minQuantity": {
                                      "type": "integer",
                                      "minimum": -9007199254740991,
                                      "maximum": 9007199254740991
                                    },
                                    "unitPrice": {
                                      "type": "number"
                                    },
                                    "discountPercent": {
                                      "type": "number"
                                    }
                                  },
                                  "required": [
                                    "minQuantity"
                                  ],
                                  "additionalProperties": false
                                }
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#761 : paliers par quantité triés par seuil - null : aucun"
                          },
                          "sortOrder": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "active": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "unitPrice",
                          "vatRate",
                          "description",
                          "quantityTiers",
                          "sortOrder",
                          "active"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "code",
                    "businessUnitId",
                    "capacity",
                    "saleMode",
                    "active",
                    "prices",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes/{id}/options/retain": {
      "post": {
        "summary": "Retenir des options d’un devis",
        "description": "Brouillon : options transformées en lignes fermes. Envoyé ou négocié : nouvelle version brouillon, source inchangée. Aucun envoi ou signature automatique. Retourne le devis cible ; optionIds désigne uniquement les options de la source.",
        "tags": [
          "Devis"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "optionIds": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "expectedUpdatedAt": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                      },
                      {
                        "type": "string",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z))$"
                      }
                    ]
                  }
                },
                "required": [
                  "optionIds"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Devis cible après reprise des options",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string",
                            "enum": [
                              "brand",
                              "comp",
                              "blend",
                              "muted",
                              "deep"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "color"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "number": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "sent",
                        "negotiation",
                        "signed",
                        "refused"
                      ]
                    },
                    "targetType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "contact"
                      ]
                    },
                    "targetId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "ownerId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "lostToCompanyId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "expectedSignOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastConfidence": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "possible",
                            "probable",
                            "quasi_certain"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastComment": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subject": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "commitment": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Engagement pluriannuel - nombre de cycles couverts"
                    },
                    "priced": {
                      "type": "boolean",
                      "description": "#747 : faux = « Non chiffré », aucune ligne chiffrée (hors lignes de texte) ; les montants valent alors 0 et ne sont pas un vrai zéro"
                    },
                    "serviceOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de prestation d'un devis ponctuel (T-1412) - null : devis par cycle"
                    },
                    "totalExclTax": {
                      "type": "string"
                    },
                    "totalInclTax": {
                      "type": "string"
                    },
                    "currency": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 3,
                      "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                    },
                    "fxRate": {
                      "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "fxRateDate": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Jour de publication du taux figé - null en euros"
                    },
                    "totalExclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du HT au taux figé"
                    },
                    "totalInclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du TTC au taux figé"
                    },
                    "createdOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                    },
                    "sentOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "signedOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "validUntil": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de validité de l'offre (E183 #511) - null : sans échéance"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "portalViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : première consultation au portail par un contact du client ; null : jamais ouvert"
                    },
                    "portalLastViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : dernière consultation au portail"
                    },
                    "portalViewCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "#758 : nombre de consultations au portail (fiche et PDF)"
                    },
                    "alternativeGroupId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : groupe d'alternatives (propositions simultanées pour une même vente) ; null : vente seule"
                    },
                    "alternativeReference": {
                      "type": "boolean",
                      "description": "#753 : proposition qui compte au pipeline dans son groupe (une par groupe, choisie par le commercial)"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "options": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "productPriceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "vatRate": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "totalInclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "productPriceId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "vatRate",
                          "priceSource",
                          "totalExclTax",
                          "totalInclTax",
                          "exclByCycle"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "forecastHistory": {
                      "maxItems": 100,
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "version": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "expectedSignOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "confidence": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "possible",
                                  "probable",
                                  "quasi_certain"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "comment": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "sent",
                              "negotiation",
                              "signed",
                              "refused"
                            ]
                          },
                          "recordedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "actorName": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "quoteId",
                          "version",
                          "expectedSignOn",
                          "confidence",
                          "comment",
                          "totalExclTax",
                          "status",
                          "recordedAt",
                          "actorName"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Les 100 dernières photographies internes de la lignée, de la plus récente à la plus ancienne"
                    },
                    "targetName": {
                      "description": "Nom de la cible (société ou contact) - T-687bis",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subtotalExclTax": {
                      "type": "string"
                    },
                    "discountAmount": {
                      "type": "string"
                    },
                    "discount": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "percent",
                                "amount"
                              ]
                            },
                            "value": {
                              "type": "number",
                              "minimum": 0
                            }
                          },
                          "required": [
                            "type",
                            "value"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "vatBreakdown": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "rate": {
                            "type": "string"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "vat": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "rate",
                          "exclTax",
                          "vat"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "lines": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sectionId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "number"
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          },
                          "isText": {
                            "type": "boolean",
                            "description": "Ligne de texte (#973) : libellé seul, hors de tout total"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "sectionId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "priceSource",
                          "totalExclTax",
                          "exclByCycle",
                          "isText"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "billingPlan": {
                      "anyOf": [
                        {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "label": {
                                "type": "string",
                                "minLength": 1
                              },
                              "percentage": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "maximum": 100
                              },
                              "offsetDays": {
                                "type": "integer",
                                "minimum": -3650,
                                "maximum": 3650
                              },
                              "anchor": {
                                "type": "string",
                                "enum": [
                                  "signature",
                                  "cycle_start"
                                ]
                              }
                            },
                            "required": [
                              "label",
                              "percentage",
                              "offsetDays"
                            ],
                            "additionalProperties": false
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "sections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "isBundle": {
                            "type": "boolean"
                          },
                          "subtotalExclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "isBundle",
                          "subtotalExclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "cycles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "endsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "inclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "startsOn",
                          "endsOn",
                          "exclTax",
                          "inclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "schedule": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "installmentId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "cycleId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleLabel": {
                            "type": "string"
                          },
                          "dueOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "amountInclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "provisional",
                              "to_invoice",
                              "invoiced",
                              "paid",
                              "late",
                              "cancelled"
                            ]
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "invoiceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "invoiceNumber": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "installmentId",
                          "cycleId",
                          "cycleLabel",
                          "dueOn",
                          "amountInclTax",
                          "status",
                          "label",
                          "invoiceId",
                          "invoiceNumber"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "contacts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "contactId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "principal",
                              "operational",
                              "billing",
                              "other"
                            ]
                          }
                        },
                        "required": [
                          "contactId",
                          "role"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "sales_alert",
                              "late_invoices",
                              "contract_terminated",
                              "contract_notice"
                            ]
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "message"
                        ],
                        "additionalProperties": false
                      },
                      "description": "#971 : faits de la société à connaître avant d'envoyer (alerte commerciale, factures en retard, contrat résilié ou en préavis) ; vide si rien ou devis clos"
                    },
                    "alternatives": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "groupId": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "members": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                  },
                                  "number": {
                                    "type": "string"
                                  },
                                  "version": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "status": {
                                    "type": "string",
                                    "enum": [
                                      "draft",
                                      "sent",
                                      "negotiation",
                                      "signed",
                                      "refused"
                                    ]
                                  },
                                  "totalExclTax": {
                                    "type": "string"
                                  },
                                  "reference": {
                                    "type": "boolean",
                                    "description": "Référence du pipeline : seule proposition comptée tant qu'aucune n'est signée"
                                  },
                                  "retained": {
                                    "description": "null : aucune signée ; true : la proposition signée ; false : non retenue, plus acceptable",
                                    "type": [
                                      "boolean",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "id",
                                  "number",
                                  "version",
                                  "status",
                                  "totalExclTax",
                                  "reference",
                                  "retained"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "groupId",
                            "members"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : le groupe d'alternatives du devis ; null : vente seule"
                    }
                  },
                  "required": [
                    "tags",
                    "id",
                    "number",
                    "version",
                    "status",
                    "targetType",
                    "targetId",
                    "ownerId",
                    "lostToCompanyId",
                    "expectedSignOn",
                    "forecastConfidence",
                    "forecastComment",
                    "subject",
                    "commitment",
                    "priced",
                    "serviceOn",
                    "totalExclTax",
                    "totalInclTax",
                    "currency",
                    "fxRate",
                    "fxRateDate",
                    "totalExclTaxEur",
                    "totalInclTaxEur",
                    "createdOn",
                    "sentOn",
                    "signedOn",
                    "validUntil",
                    "updatedAt",
                    "statusChangedAt",
                    "portalViewedAt",
                    "portalLastViewedAt",
                    "portalViewCount",
                    "alternativeGroupId",
                    "alternativeReference",
                    "options",
                    "forecastHistory",
                    "targetName",
                    "subtotalExclTax",
                    "discountAmount",
                    "discount",
                    "vatBreakdown",
                    "customFields",
                    "lines",
                    "billingPlan",
                    "sections",
                    "cycles",
                    "schedule",
                    "contacts",
                    "warnings",
                    "alternatives"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes/{id}/tags": {
      "post": {
        "summary": "Remplacer les étiquettes d’un devis",
        "description": "Identifiants du dictionnaire partagé. Liste vide : retrait de toutes les poses. Ventes active, modification et périmètre du devis requis ; Marketing facultatif. expectedUpdatedAt protège une sélection préparée.",
        "tags": [
          "Devis"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "tags": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "description": "Identifiants des étiquettes à conserver ; vide retire toutes les poses du devis"
                  },
                  "expectedUpdatedAt": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                      },
                      {
                        "type": "string",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z))$"
                      }
                    ]
                  }
                },
                "required": [
                  "tags"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Étiquettes du devis",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string",
                            "enum": [
                              "brand",
                              "comp",
                              "blend",
                              "muted",
                              "deep"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "color"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "tags"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes/{id}/forecast": {
      "post": {
        "summary": "Modifier l'estimation de signature du devis courant ouvert",
        "description": "Date prévue, confiance et commentaire internes ; aucune pondération ni transition. Les champs omis sont conservés, null les efface. Un devis signé, refusé ou remplacé est en lecture seule.",
        "tags": [
          "Devis"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "expectedSignOn": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "forecastConfidence": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "possible",
                          "probable",
                          "quasi_certain"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "forecastComment": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 2000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "expectedUpdatedAt": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                      },
                      {
                        "type": "string",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z))$"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Devis et estimation",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string",
                            "enum": [
                              "brand",
                              "comp",
                              "blend",
                              "muted",
                              "deep"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "color"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "number": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "sent",
                        "negotiation",
                        "signed",
                        "refused"
                      ]
                    },
                    "targetType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "contact"
                      ]
                    },
                    "targetId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "ownerId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "lostToCompanyId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "expectedSignOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastConfidence": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "possible",
                            "probable",
                            "quasi_certain"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastComment": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subject": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "commitment": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Engagement pluriannuel - nombre de cycles couverts"
                    },
                    "priced": {
                      "type": "boolean",
                      "description": "#747 : faux = « Non chiffré », aucune ligne chiffrée (hors lignes de texte) ; les montants valent alors 0 et ne sont pas un vrai zéro"
                    },
                    "serviceOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de prestation d'un devis ponctuel (T-1412) - null : devis par cycle"
                    },
                    "totalExclTax": {
                      "type": "string"
                    },
                    "totalInclTax": {
                      "type": "string"
                    },
                    "currency": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 3,
                      "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                    },
                    "fxRate": {
                      "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "fxRateDate": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Jour de publication du taux figé - null en euros"
                    },
                    "totalExclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du HT au taux figé"
                    },
                    "totalInclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du TTC au taux figé"
                    },
                    "createdOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                    },
                    "sentOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "signedOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "validUntil": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de validité de l'offre (E183 #511) - null : sans échéance"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "portalViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : première consultation au portail par un contact du client ; null : jamais ouvert"
                    },
                    "portalLastViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : dernière consultation au portail"
                    },
                    "portalViewCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "#758 : nombre de consultations au portail (fiche et PDF)"
                    },
                    "alternativeGroupId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : groupe d'alternatives (propositions simultanées pour une même vente) ; null : vente seule"
                    },
                    "alternativeReference": {
                      "type": "boolean",
                      "description": "#753 : proposition qui compte au pipeline dans son groupe (une par groupe, choisie par le commercial)"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "options": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "productPriceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "vatRate": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "totalInclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "productPriceId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "vatRate",
                          "priceSource",
                          "totalExclTax",
                          "totalInclTax",
                          "exclByCycle"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "forecastHistory": {
                      "maxItems": 100,
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "version": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "expectedSignOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "confidence": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "possible",
                                  "probable",
                                  "quasi_certain"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "comment": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "sent",
                              "negotiation",
                              "signed",
                              "refused"
                            ]
                          },
                          "recordedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "actorName": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "quoteId",
                          "version",
                          "expectedSignOn",
                          "confidence",
                          "comment",
                          "totalExclTax",
                          "status",
                          "recordedAt",
                          "actorName"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Les 100 dernières photographies internes de la lignée, de la plus récente à la plus ancienne"
                    },
                    "targetName": {
                      "description": "Nom de la cible (société ou contact) - T-687bis",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subtotalExclTax": {
                      "type": "string"
                    },
                    "discountAmount": {
                      "type": "string"
                    },
                    "discount": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "percent",
                                "amount"
                              ]
                            },
                            "value": {
                              "type": "number",
                              "minimum": 0
                            }
                          },
                          "required": [
                            "type",
                            "value"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "vatBreakdown": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "rate": {
                            "type": "string"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "vat": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "rate",
                          "exclTax",
                          "vat"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "lines": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sectionId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "number"
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          },
                          "isText": {
                            "type": "boolean",
                            "description": "Ligne de texte (#973) : libellé seul, hors de tout total"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "sectionId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "priceSource",
                          "totalExclTax",
                          "exclByCycle",
                          "isText"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "billingPlan": {
                      "anyOf": [
                        {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "label": {
                                "type": "string",
                                "minLength": 1
                              },
                              "percentage": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "maximum": 100
                              },
                              "offsetDays": {
                                "type": "integer",
                                "minimum": -3650,
                                "maximum": 3650
                              },
                              "anchor": {
                                "type": "string",
                                "enum": [
                                  "signature",
                                  "cycle_start"
                                ]
                              }
                            },
                            "required": [
                              "label",
                              "percentage",
                              "offsetDays"
                            ],
                            "additionalProperties": false
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "sections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "isBundle": {
                            "type": "boolean"
                          },
                          "subtotalExclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "isBundle",
                          "subtotalExclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "cycles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "endsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "inclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "startsOn",
                          "endsOn",
                          "exclTax",
                          "inclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "schedule": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "installmentId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "cycleId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleLabel": {
                            "type": "string"
                          },
                          "dueOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "amountInclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "provisional",
                              "to_invoice",
                              "invoiced",
                              "paid",
                              "late",
                              "cancelled"
                            ]
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "invoiceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "invoiceNumber": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "installmentId",
                          "cycleId",
                          "cycleLabel",
                          "dueOn",
                          "amountInclTax",
                          "status",
                          "label",
                          "invoiceId",
                          "invoiceNumber"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "contacts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "contactId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "principal",
                              "operational",
                              "billing",
                              "other"
                            ]
                          }
                        },
                        "required": [
                          "contactId",
                          "role"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "sales_alert",
                              "late_invoices",
                              "contract_terminated",
                              "contract_notice"
                            ]
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "message"
                        ],
                        "additionalProperties": false
                      },
                      "description": "#971 : faits de la société à connaître avant d'envoyer (alerte commerciale, factures en retard, contrat résilié ou en préavis) ; vide si rien ou devis clos"
                    },
                    "alternatives": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "groupId": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "members": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                  },
                                  "number": {
                                    "type": "string"
                                  },
                                  "version": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "status": {
                                    "type": "string",
                                    "enum": [
                                      "draft",
                                      "sent",
                                      "negotiation",
                                      "signed",
                                      "refused"
                                    ]
                                  },
                                  "totalExclTax": {
                                    "type": "string"
                                  },
                                  "reference": {
                                    "type": "boolean",
                                    "description": "Référence du pipeline : seule proposition comptée tant qu'aucune n'est signée"
                                  },
                                  "retained": {
                                    "description": "null : aucune signée ; true : la proposition signée ; false : non retenue, plus acceptable",
                                    "type": [
                                      "boolean",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "id",
                                  "number",
                                  "version",
                                  "status",
                                  "totalExclTax",
                                  "reference",
                                  "retained"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "groupId",
                            "members"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : le groupe d'alternatives du devis ; null : vente seule"
                    }
                  },
                  "required": [
                    "tags",
                    "id",
                    "number",
                    "version",
                    "status",
                    "targetType",
                    "targetId",
                    "ownerId",
                    "lostToCompanyId",
                    "expectedSignOn",
                    "forecastConfidence",
                    "forecastComment",
                    "subject",
                    "commitment",
                    "priced",
                    "serviceOn",
                    "totalExclTax",
                    "totalInclTax",
                    "currency",
                    "fxRate",
                    "fxRateDate",
                    "totalExclTaxEur",
                    "totalInclTaxEur",
                    "createdOn",
                    "sentOn",
                    "signedOn",
                    "validUntil",
                    "updatedAt",
                    "statusChangedAt",
                    "portalViewedAt",
                    "portalLastViewedAt",
                    "portalViewCount",
                    "alternativeGroupId",
                    "alternativeReference",
                    "options",
                    "forecastHistory",
                    "targetName",
                    "subtotalExclTax",
                    "discountAmount",
                    "discount",
                    "vatBreakdown",
                    "customFields",
                    "lines",
                    "billingPlan",
                    "sections",
                    "cycles",
                    "schedule",
                    "contacts",
                    "warnings",
                    "alternatives"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes": {
      "get": {
        "summary": "Lister les devis (hors corbeille)",
        "tags": [
          "Devis"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Jours (1 à 365) - objets dans leur statut courant depuis plus de N jours (status_changed_at), combinable avec status (T-1407)",
              "type": "integer",
              "minimum": 1,
              "maximum": 365
            }
          },
          {
            "name": "ids",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Répétable - restriction à une liste d'ids (max 200)",
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "draft",
                "sent",
                "negotiation",
                "signed",
                "refused"
              ]
            }
          },
          {
            "name": "companyId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          },
          {
            "name": "ownerId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          },
          {
            "name": "externalId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Objets qui portent cet identifiant externe (exact) - avec `externalSource` pour une source précise",
              "type": "string"
            }
          },
          {
            "name": "externalSource",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Source de l'identifiant externe (`tacto`…)",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "quotes:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de devis",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "tags": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                },
                                "name": {
                                  "type": "string"
                                },
                                "color": {
                                  "type": "string",
                                  "enum": [
                                    "brand",
                                    "comp",
                                    "blend",
                                    "muted",
                                    "deep"
                                  ]
                                }
                              },
                              "required": [
                                "id",
                                "name",
                                "color"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "number": {
                            "type": "string"
                          },
                          "version": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "sent",
                              "negotiation",
                              "signed",
                              "refused"
                            ]
                          },
                          "targetType": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact"
                            ]
                          },
                          "targetId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "ownerId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "lostToCompanyId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "expectedSignOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "forecastConfidence": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "possible",
                                  "probable",
                                  "quasi_certain"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "forecastComment": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "subject": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "commitment": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "Engagement pluriannuel - nombre de cycles couverts"
                          },
                          "priced": {
                            "type": "boolean",
                            "description": "#747 : faux = « Non chiffré », aucune ligne chiffrée (hors lignes de texte) ; les montants valent alors 0 et ne sont pas un vrai zéro"
                          },
                          "serviceOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Date de prestation d'un devis ponctuel (T-1412) - null : devis par cycle"
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "totalInclTax": {
                            "type": "string"
                          },
                          "currency": {
                            "type": "string",
                            "minLength": 3,
                            "maxLength": 3,
                            "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                          },
                          "fxRate": {
                            "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "fxRateDate": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Jour de publication du taux figé - null en euros"
                          },
                          "totalExclTaxEur": {
                            "type": "string",
                            "description": "Contre-valeur en euros du HT au taux figé"
                          },
                          "totalInclTaxEur": {
                            "type": "string",
                            "description": "Contre-valeur en euros du TTC au taux figé"
                          },
                          "createdOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "sentOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "signedOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "validUntil": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Date de validité de l'offre (E183 #511) - null : sans échéance"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "statusChangedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                            "description": "Entrée dans le statut courant (T-1407)"
                          },
                          "portalViewedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#758 : première consultation au portail par un contact du client ; null : jamais ouvert"
                          },
                          "portalLastViewedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#758 : dernière consultation au portail"
                          },
                          "portalViewCount": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "#758 : nombre de consultations au portail (fiche et PDF)"
                          },
                          "alternativeGroupId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#753 : groupe d'alternatives (propositions simultanées pour une même vente) ; null : vente seule"
                          },
                          "alternativeReference": {
                            "type": "boolean",
                            "description": "#753 : proposition qui compte au pipeline dans son groupe (une par groupe, choisie par le commercial)"
                          },
                          "externalRefs": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "source": {
                                  "type": "string",
                                  "description": "Système source (minuscules) - `tacto`, `erp`…"
                                },
                                "externalId": {
                                  "type": "string"
                                },
                                "sourceUpdatedAt": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "date-time",
                                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ],
                                  "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                                }
                              },
                              "required": [
                                "source",
                                "externalId",
                                "sourceUpdatedAt"
                              ],
                              "additionalProperties": false
                            },
                            "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                          }
                        },
                        "required": [
                          "tags",
                          "id",
                          "number",
                          "version",
                          "status",
                          "targetType",
                          "targetId",
                          "ownerId",
                          "lostToCompanyId",
                          "expectedSignOn",
                          "forecastConfidence",
                          "forecastComment",
                          "subject",
                          "commitment",
                          "priced",
                          "serviceOn",
                          "totalExclTax",
                          "totalInclTax",
                          "currency",
                          "fxRate",
                          "fxRateDate",
                          "totalExclTaxEur",
                          "totalInclTaxEur",
                          "createdOn",
                          "sentOn",
                          "signedOn",
                          "validUntil",
                          "updatedAt",
                          "statusChangedAt",
                          "portalViewedAt",
                          "portalLastViewedAt",
                          "portalViewCount",
                          "alternativeGroupId",
                          "alternativeReference"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Créer un devis (brouillon) - numéro et totaux calculés serveur",
        "tags": [
          "Devis"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "options": {
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "productId": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "productPriceId": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "businessUnitId": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "unitPrice": {
                          "type": "number",
                          "exclusiveMinimum": 0
                        },
                        "quantity": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 9007199254740991
                        },
                        "label": {
                          "type": "string",
                          "minLength": 1
                        },
                        "discountPercent": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 100
                        },
                        "amountsByCycle": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "additionalProperties": {
                            "type": "number",
                            "minimum": 0
                          }
                        },
                        "cycleIds": {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          }
                        }
                      },
                      "required": [
                        "productId",
                        "businessUnitId",
                        "unitPrice",
                        "quantity"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "targetType": {
                    "type": "string",
                    "enum": [
                      "company",
                      "contact"
                    ]
                  },
                  "targetId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "cycleIds": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "description": "Cycles couverts - vide seulement avec serviceOn (devis ponctuel, T-1412)"
                  },
                  "serviceOn": {
                    "description": "Date de prestation d'un devis PONCTUEL (T-1412) ; null ou absent : devis par cycle",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "currency": {
                    "description": "Devise du devis (T-1404, ADR-184) : EUR, ou une devise activée par l'organisation ; absent : EUR à la création, inchangée à l'édition",
                    "type": "string",
                    "enum": [
                      "EUR",
                      "USD",
                      "GBP",
                      "CHF"
                    ]
                  },
                  "fxRate": {
                    "description": "Taux saisi à la main, « 1 EUR = fxRate devise » ; absent : taux BCE du jour figé à la création",
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "maximum": 999999
                  },
                  "subject": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 300
                      }
                    ]
                  },
                  "discount": {
                    "anyOf": [
                      {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "percent",
                              "amount"
                            ]
                          },
                          "value": {
                            "type": "number",
                            "minimum": 0
                          }
                        },
                        "required": [
                          "type",
                          "value"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "indexPercent": {
                    "description": "#968 : indexation de N % par cycle appliquée aux montants, tracée dans le fil du devis",
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "lines": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "productId": {
                          "description": "null/absent = ligne libre (label requis)",
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "productPriceId": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "sectionIndex": {
                          "description": "Index de la section dans sections (à partir de 0) ; absent : ligne à plat",
                          "anyOf": [
                            {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 9007199254740991
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "businessUnitId": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "unitPrice": {
                          "type": "number",
                          "minimum": 0
                        },
                        "quantity": {
                          "type": "number",
                          "exclusiveMinimum": 0
                        },
                        "label": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 2000
                        },
                        "discountPercent": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 100
                        },
                        "isText": {
                          "description": "Ligne de texte (#973) : libellé seul, sans produit ; prix 0, quantité 1, aucun cycle, hors de tout total",
                          "type": "boolean"
                        },
                        "amountsByCycle": {
                          "description": "#968 : montant HT de la ligne par cycle couvert, AVANT remise de ligne ({ cycleId: montant }) ; absent : PU × quantité à chaque cycle",
                          "type": "object",
                          "propertyNames": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "additionalProperties": {
                            "type": "number",
                            "minimum": 0
                          }
                        }
                      },
                      "required": [
                        "businessUnitId",
                        "unitPrice",
                        "quantity"
                      ],
                      "additionalProperties": false
                    },
                    "description": "#747 : vide permis - le brouillon est « Non chiffré » (priced = false) et ne s'envoie ni ne se signe tant qu'aucune ligne chiffrée n'existe"
                  },
                  "sections": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "label": {
                          "type": "string",
                          "minLength": 1
                        },
                        "isBundle": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "label"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "billingPlan": {
                    "description": "Plan de facturation par cycle : pourcentages totalisant 100, décalage en jours depuis la signature ou le début du cycle. Aucune facture créée avant signature.",
                    "anyOf": [
                      {
                        "minItems": 1,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "label": {
                              "type": "string",
                              "minLength": 1
                            },
                            "percentage": {
                              "type": "number",
                              "exclusiveMinimum": 0,
                              "maximum": 100
                            },
                            "offsetDays": {
                              "type": "integer",
                              "minimum": -3650,
                              "maximum": 3650
                            },
                            "anchor": {
                              "type": "string",
                              "enum": [
                                "signature",
                                "cycle_start"
                              ]
                            }
                          },
                          "required": [
                            "label",
                            "percentage",
                            "offsetDays"
                          ]
                        }
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "contacts": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "contactId": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "role": {
                          "type": "string",
                          "enum": [
                            "principal",
                            "operational",
                            "billing",
                            "other"
                          ]
                        }
                      },
                      "required": [
                        "contactId",
                        "role"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "ownerId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  }
                },
                "required": [
                  "targetType",
                  "targetId",
                  "cycleIds",
                  "lines",
                  "ownerId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Devis créé",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string",
                            "enum": [
                              "brand",
                              "comp",
                              "blend",
                              "muted",
                              "deep"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "color"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "number": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "sent",
                        "negotiation",
                        "signed",
                        "refused"
                      ]
                    },
                    "targetType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "contact"
                      ]
                    },
                    "targetId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "ownerId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "lostToCompanyId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "expectedSignOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastConfidence": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "possible",
                            "probable",
                            "quasi_certain"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastComment": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subject": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "commitment": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Engagement pluriannuel - nombre de cycles couverts"
                    },
                    "priced": {
                      "type": "boolean",
                      "description": "#747 : faux = « Non chiffré », aucune ligne chiffrée (hors lignes de texte) ; les montants valent alors 0 et ne sont pas un vrai zéro"
                    },
                    "serviceOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de prestation d'un devis ponctuel (T-1412) - null : devis par cycle"
                    },
                    "totalExclTax": {
                      "type": "string"
                    },
                    "totalInclTax": {
                      "type": "string"
                    },
                    "currency": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 3,
                      "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                    },
                    "fxRate": {
                      "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "fxRateDate": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Jour de publication du taux figé - null en euros"
                    },
                    "totalExclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du HT au taux figé"
                    },
                    "totalInclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du TTC au taux figé"
                    },
                    "createdOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                    },
                    "sentOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "signedOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "validUntil": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de validité de l'offre (E183 #511) - null : sans échéance"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "portalViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : première consultation au portail par un contact du client ; null : jamais ouvert"
                    },
                    "portalLastViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : dernière consultation au portail"
                    },
                    "portalViewCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "#758 : nombre de consultations au portail (fiche et PDF)"
                    },
                    "alternativeGroupId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : groupe d'alternatives (propositions simultanées pour une même vente) ; null : vente seule"
                    },
                    "alternativeReference": {
                      "type": "boolean",
                      "description": "#753 : proposition qui compte au pipeline dans son groupe (une par groupe, choisie par le commercial)"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "options": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "productPriceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "vatRate": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "totalInclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "productPriceId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "vatRate",
                          "priceSource",
                          "totalExclTax",
                          "totalInclTax",
                          "exclByCycle"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "forecastHistory": {
                      "maxItems": 100,
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "version": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "expectedSignOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "confidence": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "possible",
                                  "probable",
                                  "quasi_certain"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "comment": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "sent",
                              "negotiation",
                              "signed",
                              "refused"
                            ]
                          },
                          "recordedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "actorName": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "quoteId",
                          "version",
                          "expectedSignOn",
                          "confidence",
                          "comment",
                          "totalExclTax",
                          "status",
                          "recordedAt",
                          "actorName"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Les 100 dernières photographies internes de la lignée, de la plus récente à la plus ancienne"
                    },
                    "targetName": {
                      "description": "Nom de la cible (société ou contact) - T-687bis",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subtotalExclTax": {
                      "type": "string"
                    },
                    "discountAmount": {
                      "type": "string"
                    },
                    "discount": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "percent",
                                "amount"
                              ]
                            },
                            "value": {
                              "type": "number",
                              "minimum": 0
                            }
                          },
                          "required": [
                            "type",
                            "value"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "vatBreakdown": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "rate": {
                            "type": "string"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "vat": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "rate",
                          "exclTax",
                          "vat"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "lines": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sectionId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "number"
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          },
                          "isText": {
                            "type": "boolean",
                            "description": "Ligne de texte (#973) : libellé seul, hors de tout total"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "sectionId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "priceSource",
                          "totalExclTax",
                          "exclByCycle",
                          "isText"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "billingPlan": {
                      "anyOf": [
                        {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "label": {
                                "type": "string",
                                "minLength": 1
                              },
                              "percentage": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "maximum": 100
                              },
                              "offsetDays": {
                                "type": "integer",
                                "minimum": -3650,
                                "maximum": 3650
                              },
                              "anchor": {
                                "type": "string",
                                "enum": [
                                  "signature",
                                  "cycle_start"
                                ]
                              }
                            },
                            "required": [
                              "label",
                              "percentage",
                              "offsetDays"
                            ],
                            "additionalProperties": false
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "sections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "isBundle": {
                            "type": "boolean"
                          },
                          "subtotalExclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "isBundle",
                          "subtotalExclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "cycles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "endsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "inclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "startsOn",
                          "endsOn",
                          "exclTax",
                          "inclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "schedule": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "installmentId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "cycleId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleLabel": {
                            "type": "string"
                          },
                          "dueOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "amountInclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "provisional",
                              "to_invoice",
                              "invoiced",
                              "paid",
                              "late",
                              "cancelled"
                            ]
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "invoiceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "invoiceNumber": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "installmentId",
                          "cycleId",
                          "cycleLabel",
                          "dueOn",
                          "amountInclTax",
                          "status",
                          "label",
                          "invoiceId",
                          "invoiceNumber"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "contacts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "contactId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "principal",
                              "operational",
                              "billing",
                              "other"
                            ]
                          }
                        },
                        "required": [
                          "contactId",
                          "role"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "sales_alert",
                              "late_invoices",
                              "contract_terminated",
                              "contract_notice"
                            ]
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "message"
                        ],
                        "additionalProperties": false
                      },
                      "description": "#971 : faits de la société à connaître avant d'envoyer (alerte commerciale, factures en retard, contrat résilié ou en préavis) ; vide si rien ou devis clos"
                    },
                    "alternatives": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "groupId": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "members": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                  },
                                  "number": {
                                    "type": "string"
                                  },
                                  "version": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "status": {
                                    "type": "string",
                                    "enum": [
                                      "draft",
                                      "sent",
                                      "negotiation",
                                      "signed",
                                      "refused"
                                    ]
                                  },
                                  "totalExclTax": {
                                    "type": "string"
                                  },
                                  "reference": {
                                    "type": "boolean",
                                    "description": "Référence du pipeline : seule proposition comptée tant qu'aucune n'est signée"
                                  },
                                  "retained": {
                                    "description": "null : aucune signée ; true : la proposition signée ; false : non retenue, plus acceptable",
                                    "type": [
                                      "boolean",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "id",
                                  "number",
                                  "version",
                                  "status",
                                  "totalExclTax",
                                  "reference",
                                  "retained"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "groupId",
                            "members"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : le groupe d'alternatives du devis ; null : vente seule"
                    }
                  },
                  "required": [
                    "tags",
                    "id",
                    "number",
                    "version",
                    "status",
                    "targetType",
                    "targetId",
                    "ownerId",
                    "lostToCompanyId",
                    "expectedSignOn",
                    "forecastConfidence",
                    "forecastComment",
                    "subject",
                    "commitment",
                    "priced",
                    "serviceOn",
                    "totalExclTax",
                    "totalInclTax",
                    "currency",
                    "fxRate",
                    "fxRateDate",
                    "totalExclTaxEur",
                    "totalInclTaxEur",
                    "createdOn",
                    "sentOn",
                    "signedOn",
                    "validUntil",
                    "updatedAt",
                    "statusChangedAt",
                    "portalViewedAt",
                    "portalLastViewedAt",
                    "portalViewCount",
                    "alternativeGroupId",
                    "alternativeReference",
                    "options",
                    "forecastHistory",
                    "targetName",
                    "subtotalExclTax",
                    "discountAmount",
                    "discount",
                    "vatBreakdown",
                    "customFields",
                    "lines",
                    "billingPlan",
                    "sections",
                    "cycles",
                    "schedule",
                    "contacts",
                    "warnings",
                    "alternatives"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes/{id}": {
      "get": {
        "summary": "Détail d'un devis - lignes, totaux, échéancier, engagement",
        "tags": [
          "Devis"
        ],
        "security": [
          {
            "oauth2": [
              "quotes:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Devis",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string",
                            "enum": [
                              "brand",
                              "comp",
                              "blend",
                              "muted",
                              "deep"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "color"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "number": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "sent",
                        "negotiation",
                        "signed",
                        "refused"
                      ]
                    },
                    "targetType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "contact"
                      ]
                    },
                    "targetId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "ownerId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "lostToCompanyId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "expectedSignOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastConfidence": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "possible",
                            "probable",
                            "quasi_certain"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastComment": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subject": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "commitment": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Engagement pluriannuel - nombre de cycles couverts"
                    },
                    "priced": {
                      "type": "boolean",
                      "description": "#747 : faux = « Non chiffré », aucune ligne chiffrée (hors lignes de texte) ; les montants valent alors 0 et ne sont pas un vrai zéro"
                    },
                    "serviceOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de prestation d'un devis ponctuel (T-1412) - null : devis par cycle"
                    },
                    "totalExclTax": {
                      "type": "string"
                    },
                    "totalInclTax": {
                      "type": "string"
                    },
                    "currency": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 3,
                      "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                    },
                    "fxRate": {
                      "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "fxRateDate": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Jour de publication du taux figé - null en euros"
                    },
                    "totalExclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du HT au taux figé"
                    },
                    "totalInclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du TTC au taux figé"
                    },
                    "createdOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                    },
                    "sentOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "signedOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "validUntil": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de validité de l'offre (E183 #511) - null : sans échéance"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "portalViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : première consultation au portail par un contact du client ; null : jamais ouvert"
                    },
                    "portalLastViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : dernière consultation au portail"
                    },
                    "portalViewCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "#758 : nombre de consultations au portail (fiche et PDF)"
                    },
                    "alternativeGroupId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : groupe d'alternatives (propositions simultanées pour une même vente) ; null : vente seule"
                    },
                    "alternativeReference": {
                      "type": "boolean",
                      "description": "#753 : proposition qui compte au pipeline dans son groupe (une par groupe, choisie par le commercial)"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "options": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "productPriceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "vatRate": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "totalInclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "productPriceId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "vatRate",
                          "priceSource",
                          "totalExclTax",
                          "totalInclTax",
                          "exclByCycle"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "forecastHistory": {
                      "maxItems": 100,
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "version": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "expectedSignOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "confidence": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "possible",
                                  "probable",
                                  "quasi_certain"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "comment": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "sent",
                              "negotiation",
                              "signed",
                              "refused"
                            ]
                          },
                          "recordedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "actorName": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "quoteId",
                          "version",
                          "expectedSignOn",
                          "confidence",
                          "comment",
                          "totalExclTax",
                          "status",
                          "recordedAt",
                          "actorName"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Les 100 dernières photographies internes de la lignée, de la plus récente à la plus ancienne"
                    },
                    "targetName": {
                      "description": "Nom de la cible (société ou contact) - T-687bis",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subtotalExclTax": {
                      "type": "string"
                    },
                    "discountAmount": {
                      "type": "string"
                    },
                    "discount": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "percent",
                                "amount"
                              ]
                            },
                            "value": {
                              "type": "number",
                              "minimum": 0
                            }
                          },
                          "required": [
                            "type",
                            "value"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "vatBreakdown": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "rate": {
                            "type": "string"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "vat": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "rate",
                          "exclTax",
                          "vat"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "lines": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sectionId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "number"
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          },
                          "isText": {
                            "type": "boolean",
                            "description": "Ligne de texte (#973) : libellé seul, hors de tout total"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "sectionId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "priceSource",
                          "totalExclTax",
                          "exclByCycle",
                          "isText"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "billingPlan": {
                      "anyOf": [
                        {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "label": {
                                "type": "string",
                                "minLength": 1
                              },
                              "percentage": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "maximum": 100
                              },
                              "offsetDays": {
                                "type": "integer",
                                "minimum": -3650,
                                "maximum": 3650
                              },
                              "anchor": {
                                "type": "string",
                                "enum": [
                                  "signature",
                                  "cycle_start"
                                ]
                              }
                            },
                            "required": [
                              "label",
                              "percentage",
                              "offsetDays"
                            ],
                            "additionalProperties": false
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "sections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "isBundle": {
                            "type": "boolean"
                          },
                          "subtotalExclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "isBundle",
                          "subtotalExclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "cycles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "endsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "inclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "startsOn",
                          "endsOn",
                          "exclTax",
                          "inclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "schedule": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "installmentId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "cycleId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleLabel": {
                            "type": "string"
                          },
                          "dueOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "amountInclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "provisional",
                              "to_invoice",
                              "invoiced",
                              "paid",
                              "late",
                              "cancelled"
                            ]
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "invoiceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "invoiceNumber": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "installmentId",
                          "cycleId",
                          "cycleLabel",
                          "dueOn",
                          "amountInclTax",
                          "status",
                          "label",
                          "invoiceId",
                          "invoiceNumber"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "contacts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "contactId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "principal",
                              "operational",
                              "billing",
                              "other"
                            ]
                          }
                        },
                        "required": [
                          "contactId",
                          "role"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "sales_alert",
                              "late_invoices",
                              "contract_terminated",
                              "contract_notice"
                            ]
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "message"
                        ],
                        "additionalProperties": false
                      },
                      "description": "#971 : faits de la société à connaître avant d'envoyer (alerte commerciale, factures en retard, contrat résilié ou en préavis) ; vide si rien ou devis clos"
                    },
                    "alternatives": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "groupId": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "members": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                  },
                                  "number": {
                                    "type": "string"
                                  },
                                  "version": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "status": {
                                    "type": "string",
                                    "enum": [
                                      "draft",
                                      "sent",
                                      "negotiation",
                                      "signed",
                                      "refused"
                                    ]
                                  },
                                  "totalExclTax": {
                                    "type": "string"
                                  },
                                  "reference": {
                                    "type": "boolean",
                                    "description": "Référence du pipeline : seule proposition comptée tant qu'aucune n'est signée"
                                  },
                                  "retained": {
                                    "description": "null : aucune signée ; true : la proposition signée ; false : non retenue, plus acceptable",
                                    "type": [
                                      "boolean",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "id",
                                  "number",
                                  "version",
                                  "status",
                                  "totalExclTax",
                                  "reference",
                                  "retained"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "groupId",
                            "members"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : le groupe d'alternatives du devis ; null : vente seule"
                    }
                  },
                  "required": [
                    "tags",
                    "id",
                    "number",
                    "version",
                    "status",
                    "targetType",
                    "targetId",
                    "ownerId",
                    "lostToCompanyId",
                    "expectedSignOn",
                    "forecastConfidence",
                    "forecastComment",
                    "subject",
                    "commitment",
                    "priced",
                    "serviceOn",
                    "totalExclTax",
                    "totalInclTax",
                    "currency",
                    "fxRate",
                    "fxRateDate",
                    "totalExclTaxEur",
                    "totalInclTaxEur",
                    "createdOn",
                    "sentOn",
                    "signedOn",
                    "validUntil",
                    "updatedAt",
                    "statusChangedAt",
                    "portalViewedAt",
                    "portalLastViewedAt",
                    "portalViewCount",
                    "alternativeGroupId",
                    "alternativeReference",
                    "options",
                    "forecastHistory",
                    "targetName",
                    "subtotalExclTax",
                    "discountAmount",
                    "discount",
                    "vatBreakdown",
                    "customFields",
                    "lines",
                    "billingPlan",
                    "sections",
                    "cycles",
                    "schedule",
                    "contacts",
                    "warnings",
                    "alternatives"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Recomposer un devis BROUILLON (jeton expectedUpdatedAt requis)",
        "description": "Remplace la composition (lignes, cycles, cible, remise) - brouillon uniquement, mêmes règles que le builder UI. Hors brouillon : 409.",
        "tags": [
          "Devis"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "options": {
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "productId": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "productPriceId": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "businessUnitId": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "unitPrice": {
                          "type": "number",
                          "exclusiveMinimum": 0
                        },
                        "quantity": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 9007199254740991
                        },
                        "label": {
                          "type": "string",
                          "minLength": 1
                        },
                        "discountPercent": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 100
                        },
                        "amountsByCycle": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "additionalProperties": {
                            "type": "number",
                            "minimum": 0
                          }
                        },
                        "cycleIds": {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          }
                        }
                      },
                      "required": [
                        "productId",
                        "businessUnitId",
                        "unitPrice",
                        "quantity"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "targetType": {
                    "type": "string",
                    "enum": [
                      "company",
                      "contact"
                    ]
                  },
                  "targetId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "cycleIds": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "description": "Cycles couverts - vide seulement avec serviceOn (devis ponctuel, T-1412)"
                  },
                  "serviceOn": {
                    "description": "Date de prestation d'un devis PONCTUEL (T-1412) ; null ou absent : devis par cycle",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "currency": {
                    "description": "Devise du devis (T-1404, ADR-184) : EUR, ou une devise activée par l'organisation ; absent : EUR à la création, inchangée à l'édition",
                    "type": "string",
                    "enum": [
                      "EUR",
                      "USD",
                      "GBP",
                      "CHF"
                    ]
                  },
                  "fxRate": {
                    "description": "Taux saisi à la main, « 1 EUR = fxRate devise » ; absent : taux BCE du jour figé à la création",
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "maximum": 999999
                  },
                  "subject": {
                    "anyOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "string",
                        "maxLength": 300
                      }
                    ]
                  },
                  "discount": {
                    "anyOf": [
                      {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "percent",
                              "amount"
                            ]
                          },
                          "value": {
                            "type": "number",
                            "minimum": 0
                          }
                        },
                        "required": [
                          "type",
                          "value"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "indexPercent": {
                    "description": "#968 : indexation de N % par cycle appliquée aux montants, tracée dans le fil du devis",
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "lines": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "productId": {
                          "description": "null/absent = ligne libre (label requis)",
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "productPriceId": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "sectionIndex": {
                          "description": "Index de la section dans sections (à partir de 0) ; absent : ligne à plat",
                          "anyOf": [
                            {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 9007199254740991
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "businessUnitId": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "unitPrice": {
                          "type": "number",
                          "minimum": 0
                        },
                        "quantity": {
                          "type": "number",
                          "exclusiveMinimum": 0
                        },
                        "label": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 2000
                        },
                        "discountPercent": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 100
                        },
                        "isText": {
                          "description": "Ligne de texte (#973) : libellé seul, sans produit ; prix 0, quantité 1, aucun cycle, hors de tout total",
                          "type": "boolean"
                        },
                        "amountsByCycle": {
                          "description": "#968 : montant HT de la ligne par cycle couvert, AVANT remise de ligne ({ cycleId: montant }) ; absent : PU × quantité à chaque cycle",
                          "type": "object",
                          "propertyNames": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "additionalProperties": {
                            "type": "number",
                            "minimum": 0
                          }
                        }
                      },
                      "required": [
                        "businessUnitId",
                        "unitPrice",
                        "quantity"
                      ],
                      "additionalProperties": false
                    },
                    "description": "#747 : vide permis - le brouillon est « Non chiffré » (priced = false) et ne s'envoie ni ne se signe tant qu'aucune ligne chiffrée n'existe"
                  },
                  "sections": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "label": {
                          "type": "string",
                          "minLength": 1
                        },
                        "isBundle": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "label"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "billingPlan": {
                    "description": "Plan de facturation par cycle : pourcentages totalisant 100, décalage en jours depuis la signature ou le début du cycle. Aucune facture créée avant signature.",
                    "anyOf": [
                      {
                        "minItems": 1,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "label": {
                              "type": "string",
                              "minLength": 1
                            },
                            "percentage": {
                              "type": "number",
                              "exclusiveMinimum": 0,
                              "maximum": 100
                            },
                            "offsetDays": {
                              "type": "integer",
                              "minimum": -3650,
                              "maximum": 3650
                            },
                            "anchor": {
                              "type": "string",
                              "enum": [
                                "signature",
                                "cycle_start"
                              ]
                            }
                          },
                          "required": [
                            "label",
                            "percentage",
                            "offsetDays"
                          ]
                        }
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "contacts": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "contactId": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "role": {
                          "type": "string",
                          "enum": [
                            "principal",
                            "operational",
                            "billing",
                            "other"
                          ]
                        }
                      },
                      "required": [
                        "contactId",
                        "role"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "expectedUpdatedAt": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                      },
                      {
                        "type": "string",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z))$"
                      }
                    ],
                    "description": "updatedAt lu au GET - jeton de concurrence"
                  }
                },
                "required": [
                  "targetType",
                  "targetId",
                  "cycleIds",
                  "lines",
                  "expectedUpdatedAt"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Devis recomposé",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string",
                            "enum": [
                              "brand",
                              "comp",
                              "blend",
                              "muted",
                              "deep"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "color"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "number": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "sent",
                        "negotiation",
                        "signed",
                        "refused"
                      ]
                    },
                    "targetType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "contact"
                      ]
                    },
                    "targetId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "ownerId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "lostToCompanyId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "expectedSignOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastConfidence": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "possible",
                            "probable",
                            "quasi_certain"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastComment": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subject": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "commitment": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Engagement pluriannuel - nombre de cycles couverts"
                    },
                    "priced": {
                      "type": "boolean",
                      "description": "#747 : faux = « Non chiffré », aucune ligne chiffrée (hors lignes de texte) ; les montants valent alors 0 et ne sont pas un vrai zéro"
                    },
                    "serviceOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de prestation d'un devis ponctuel (T-1412) - null : devis par cycle"
                    },
                    "totalExclTax": {
                      "type": "string"
                    },
                    "totalInclTax": {
                      "type": "string"
                    },
                    "currency": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 3,
                      "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                    },
                    "fxRate": {
                      "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "fxRateDate": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Jour de publication du taux figé - null en euros"
                    },
                    "totalExclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du HT au taux figé"
                    },
                    "totalInclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du TTC au taux figé"
                    },
                    "createdOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                    },
                    "sentOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "signedOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "validUntil": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de validité de l'offre (E183 #511) - null : sans échéance"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "portalViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : première consultation au portail par un contact du client ; null : jamais ouvert"
                    },
                    "portalLastViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : dernière consultation au portail"
                    },
                    "portalViewCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "#758 : nombre de consultations au portail (fiche et PDF)"
                    },
                    "alternativeGroupId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : groupe d'alternatives (propositions simultanées pour une même vente) ; null : vente seule"
                    },
                    "alternativeReference": {
                      "type": "boolean",
                      "description": "#753 : proposition qui compte au pipeline dans son groupe (une par groupe, choisie par le commercial)"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "options": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "productPriceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "vatRate": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "totalInclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "productPriceId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "vatRate",
                          "priceSource",
                          "totalExclTax",
                          "totalInclTax",
                          "exclByCycle"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "forecastHistory": {
                      "maxItems": 100,
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "version": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "expectedSignOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "confidence": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "possible",
                                  "probable",
                                  "quasi_certain"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "comment": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "sent",
                              "negotiation",
                              "signed",
                              "refused"
                            ]
                          },
                          "recordedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "actorName": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "quoteId",
                          "version",
                          "expectedSignOn",
                          "confidence",
                          "comment",
                          "totalExclTax",
                          "status",
                          "recordedAt",
                          "actorName"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Les 100 dernières photographies internes de la lignée, de la plus récente à la plus ancienne"
                    },
                    "targetName": {
                      "description": "Nom de la cible (société ou contact) - T-687bis",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subtotalExclTax": {
                      "type": "string"
                    },
                    "discountAmount": {
                      "type": "string"
                    },
                    "discount": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "percent",
                                "amount"
                              ]
                            },
                            "value": {
                              "type": "number",
                              "minimum": 0
                            }
                          },
                          "required": [
                            "type",
                            "value"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "vatBreakdown": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "rate": {
                            "type": "string"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "vat": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "rate",
                          "exclTax",
                          "vat"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "lines": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sectionId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "number"
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          },
                          "isText": {
                            "type": "boolean",
                            "description": "Ligne de texte (#973) : libellé seul, hors de tout total"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "sectionId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "priceSource",
                          "totalExclTax",
                          "exclByCycle",
                          "isText"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "billingPlan": {
                      "anyOf": [
                        {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "label": {
                                "type": "string",
                                "minLength": 1
                              },
                              "percentage": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "maximum": 100
                              },
                              "offsetDays": {
                                "type": "integer",
                                "minimum": -3650,
                                "maximum": 3650
                              },
                              "anchor": {
                                "type": "string",
                                "enum": [
                                  "signature",
                                  "cycle_start"
                                ]
                              }
                            },
                            "required": [
                              "label",
                              "percentage",
                              "offsetDays"
                            ],
                            "additionalProperties": false
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "sections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "isBundle": {
                            "type": "boolean"
                          },
                          "subtotalExclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "isBundle",
                          "subtotalExclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "cycles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "endsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "inclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "startsOn",
                          "endsOn",
                          "exclTax",
                          "inclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "schedule": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "installmentId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "cycleId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleLabel": {
                            "type": "string"
                          },
                          "dueOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "amountInclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "provisional",
                              "to_invoice",
                              "invoiced",
                              "paid",
                              "late",
                              "cancelled"
                            ]
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "invoiceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "invoiceNumber": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "installmentId",
                          "cycleId",
                          "cycleLabel",
                          "dueOn",
                          "amountInclTax",
                          "status",
                          "label",
                          "invoiceId",
                          "invoiceNumber"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "contacts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "contactId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "principal",
                              "operational",
                              "billing",
                              "other"
                            ]
                          }
                        },
                        "required": [
                          "contactId",
                          "role"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "sales_alert",
                              "late_invoices",
                              "contract_terminated",
                              "contract_notice"
                            ]
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "message"
                        ],
                        "additionalProperties": false
                      },
                      "description": "#971 : faits de la société à connaître avant d'envoyer (alerte commerciale, factures en retard, contrat résilié ou en préavis) ; vide si rien ou devis clos"
                    },
                    "alternatives": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "groupId": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "members": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                  },
                                  "number": {
                                    "type": "string"
                                  },
                                  "version": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "status": {
                                    "type": "string",
                                    "enum": [
                                      "draft",
                                      "sent",
                                      "negotiation",
                                      "signed",
                                      "refused"
                                    ]
                                  },
                                  "totalExclTax": {
                                    "type": "string"
                                  },
                                  "reference": {
                                    "type": "boolean",
                                    "description": "Référence du pipeline : seule proposition comptée tant qu'aucune n'est signée"
                                  },
                                  "retained": {
                                    "description": "null : aucune signée ; true : la proposition signée ; false : non retenue, plus acceptable",
                                    "type": [
                                      "boolean",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "id",
                                  "number",
                                  "version",
                                  "status",
                                  "totalExclTax",
                                  "reference",
                                  "retained"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "groupId",
                            "members"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : le groupe d'alternatives du devis ; null : vente seule"
                    }
                  },
                  "required": [
                    "tags",
                    "id",
                    "number",
                    "version",
                    "status",
                    "targetType",
                    "targetId",
                    "ownerId",
                    "lostToCompanyId",
                    "expectedSignOn",
                    "forecastConfidence",
                    "forecastComment",
                    "subject",
                    "commitment",
                    "priced",
                    "serviceOn",
                    "totalExclTax",
                    "totalInclTax",
                    "currency",
                    "fxRate",
                    "fxRateDate",
                    "totalExclTaxEur",
                    "totalInclTaxEur",
                    "createdOn",
                    "sentOn",
                    "signedOn",
                    "validUntil",
                    "updatedAt",
                    "statusChangedAt",
                    "portalViewedAt",
                    "portalLastViewedAt",
                    "portalViewCount",
                    "alternativeGroupId",
                    "alternativeReference",
                    "options",
                    "forecastHistory",
                    "targetName",
                    "subtotalExclTax",
                    "discountAmount",
                    "discount",
                    "vatBreakdown",
                    "customFields",
                    "lines",
                    "billingPlan",
                    "sections",
                    "cycles",
                    "schedule",
                    "contacts",
                    "warnings",
                    "alternatives"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes/{id}/transition": {
      "post": {
        "summary": "Changer le statut - machine à états stricte",
        "description": "Transitions permises : draft→sent, sent→negotiation|signed, negotiation→signed|refused. signed et refused sont terminaux. Une transition illégale répond 422 en nommant les transitions permises. Le passage à signed génère l'échéancier et notifie le commercial (règles UI).",
        "tags": [
          "Devis"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "enum": [
                      "sent",
                      "negotiation",
                      "signed",
                      "refused"
                    ]
                  },
                  "lossReason": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "lossComment": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "lostToCompanyId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "to"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Devis après transition",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string",
                            "enum": [
                              "brand",
                              "comp",
                              "blend",
                              "muted",
                              "deep"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "color"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "number": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "sent",
                        "negotiation",
                        "signed",
                        "refused"
                      ]
                    },
                    "targetType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "contact"
                      ]
                    },
                    "targetId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "ownerId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "lostToCompanyId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "expectedSignOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastConfidence": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "possible",
                            "probable",
                            "quasi_certain"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastComment": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subject": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "commitment": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Engagement pluriannuel - nombre de cycles couverts"
                    },
                    "priced": {
                      "type": "boolean",
                      "description": "#747 : faux = « Non chiffré », aucune ligne chiffrée (hors lignes de texte) ; les montants valent alors 0 et ne sont pas un vrai zéro"
                    },
                    "serviceOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de prestation d'un devis ponctuel (T-1412) - null : devis par cycle"
                    },
                    "totalExclTax": {
                      "type": "string"
                    },
                    "totalInclTax": {
                      "type": "string"
                    },
                    "currency": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 3,
                      "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                    },
                    "fxRate": {
                      "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "fxRateDate": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Jour de publication du taux figé - null en euros"
                    },
                    "totalExclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du HT au taux figé"
                    },
                    "totalInclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du TTC au taux figé"
                    },
                    "createdOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                    },
                    "sentOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "signedOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "validUntil": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de validité de l'offre (E183 #511) - null : sans échéance"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "portalViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : première consultation au portail par un contact du client ; null : jamais ouvert"
                    },
                    "portalLastViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : dernière consultation au portail"
                    },
                    "portalViewCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "#758 : nombre de consultations au portail (fiche et PDF)"
                    },
                    "alternativeGroupId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : groupe d'alternatives (propositions simultanées pour une même vente) ; null : vente seule"
                    },
                    "alternativeReference": {
                      "type": "boolean",
                      "description": "#753 : proposition qui compte au pipeline dans son groupe (une par groupe, choisie par le commercial)"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "options": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "productPriceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "vatRate": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "totalInclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "productPriceId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "vatRate",
                          "priceSource",
                          "totalExclTax",
                          "totalInclTax",
                          "exclByCycle"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "forecastHistory": {
                      "maxItems": 100,
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "version": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "expectedSignOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "confidence": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "possible",
                                  "probable",
                                  "quasi_certain"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "comment": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "sent",
                              "negotiation",
                              "signed",
                              "refused"
                            ]
                          },
                          "recordedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "actorName": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "quoteId",
                          "version",
                          "expectedSignOn",
                          "confidence",
                          "comment",
                          "totalExclTax",
                          "status",
                          "recordedAt",
                          "actorName"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Les 100 dernières photographies internes de la lignée, de la plus récente à la plus ancienne"
                    },
                    "targetName": {
                      "description": "Nom de la cible (société ou contact) - T-687bis",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subtotalExclTax": {
                      "type": "string"
                    },
                    "discountAmount": {
                      "type": "string"
                    },
                    "discount": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "percent",
                                "amount"
                              ]
                            },
                            "value": {
                              "type": "number",
                              "minimum": 0
                            }
                          },
                          "required": [
                            "type",
                            "value"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "vatBreakdown": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "rate": {
                            "type": "string"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "vat": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "rate",
                          "exclTax",
                          "vat"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "lines": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sectionId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "number"
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          },
                          "isText": {
                            "type": "boolean",
                            "description": "Ligne de texte (#973) : libellé seul, hors de tout total"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "sectionId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "priceSource",
                          "totalExclTax",
                          "exclByCycle",
                          "isText"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "billingPlan": {
                      "anyOf": [
                        {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "label": {
                                "type": "string",
                                "minLength": 1
                              },
                              "percentage": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "maximum": 100
                              },
                              "offsetDays": {
                                "type": "integer",
                                "minimum": -3650,
                                "maximum": 3650
                              },
                              "anchor": {
                                "type": "string",
                                "enum": [
                                  "signature",
                                  "cycle_start"
                                ]
                              }
                            },
                            "required": [
                              "label",
                              "percentage",
                              "offsetDays"
                            ],
                            "additionalProperties": false
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "sections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "isBundle": {
                            "type": "boolean"
                          },
                          "subtotalExclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "isBundle",
                          "subtotalExclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "cycles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "endsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "inclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "startsOn",
                          "endsOn",
                          "exclTax",
                          "inclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "schedule": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "installmentId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "cycleId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleLabel": {
                            "type": "string"
                          },
                          "dueOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "amountInclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "provisional",
                              "to_invoice",
                              "invoiced",
                              "paid",
                              "late",
                              "cancelled"
                            ]
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "invoiceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "invoiceNumber": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "installmentId",
                          "cycleId",
                          "cycleLabel",
                          "dueOn",
                          "amountInclTax",
                          "status",
                          "label",
                          "invoiceId",
                          "invoiceNumber"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "contacts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "contactId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "principal",
                              "operational",
                              "billing",
                              "other"
                            ]
                          }
                        },
                        "required": [
                          "contactId",
                          "role"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "sales_alert",
                              "late_invoices",
                              "contract_terminated",
                              "contract_notice"
                            ]
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "message"
                        ],
                        "additionalProperties": false
                      },
                      "description": "#971 : faits de la société à connaître avant d'envoyer (alerte commerciale, factures en retard, contrat résilié ou en préavis) ; vide si rien ou devis clos"
                    },
                    "alternatives": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "groupId": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "members": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                  },
                                  "number": {
                                    "type": "string"
                                  },
                                  "version": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "status": {
                                    "type": "string",
                                    "enum": [
                                      "draft",
                                      "sent",
                                      "negotiation",
                                      "signed",
                                      "refused"
                                    ]
                                  },
                                  "totalExclTax": {
                                    "type": "string"
                                  },
                                  "reference": {
                                    "type": "boolean",
                                    "description": "Référence du pipeline : seule proposition comptée tant qu'aucune n'est signée"
                                  },
                                  "retained": {
                                    "description": "null : aucune signée ; true : la proposition signée ; false : non retenue, plus acceptable",
                                    "type": [
                                      "boolean",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "id",
                                  "number",
                                  "version",
                                  "status",
                                  "totalExclTax",
                                  "reference",
                                  "retained"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "groupId",
                            "members"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : le groupe d'alternatives du devis ; null : vente seule"
                    }
                  },
                  "required": [
                    "tags",
                    "id",
                    "number",
                    "version",
                    "status",
                    "targetType",
                    "targetId",
                    "ownerId",
                    "lostToCompanyId",
                    "expectedSignOn",
                    "forecastConfidence",
                    "forecastComment",
                    "subject",
                    "commitment",
                    "priced",
                    "serviceOn",
                    "totalExclTax",
                    "totalInclTax",
                    "currency",
                    "fxRate",
                    "fxRateDate",
                    "totalExclTaxEur",
                    "totalInclTaxEur",
                    "createdOn",
                    "sentOn",
                    "signedOn",
                    "validUntil",
                    "updatedAt",
                    "statusChangedAt",
                    "portalViewedAt",
                    "portalLastViewedAt",
                    "portalViewCount",
                    "alternativeGroupId",
                    "alternativeReference",
                    "options",
                    "forecastHistory",
                    "targetName",
                    "subtotalExclTax",
                    "discountAmount",
                    "discount",
                    "vatBreakdown",
                    "customFields",
                    "lines",
                    "billingPlan",
                    "sections",
                    "cycles",
                    "schedule",
                    "contacts",
                    "warnings",
                    "alternatives"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes/{id}/alternatives": {
      "post": {
        "summary": "Proposer une alternative (formule A ou B pour la même vente)",
        "description": "Même geste que la fiche (#753, ADR-225) : un brouillon copié du devis, numéro neuf, dans le groupe d'alternatives du devis. Au premier geste, le devis devient la référence du pipeline ; l'alternative ne l'est jamais d'office. Un groupe ouvert compte une fois (sa référence) dans le pipeline et les indicateurs. Devis clos ou groupe déjà signé : 409.",
        "tags": [
          "Devis"
        ],
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "L'alternative créée (brouillon), avec son groupe",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string",
                            "enum": [
                              "brand",
                              "comp",
                              "blend",
                              "muted",
                              "deep"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "color"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "number": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "sent",
                        "negotiation",
                        "signed",
                        "refused"
                      ]
                    },
                    "targetType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "contact"
                      ]
                    },
                    "targetId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "ownerId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "lostToCompanyId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "expectedSignOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastConfidence": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "possible",
                            "probable",
                            "quasi_certain"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastComment": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subject": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "commitment": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Engagement pluriannuel - nombre de cycles couverts"
                    },
                    "priced": {
                      "type": "boolean",
                      "description": "#747 : faux = « Non chiffré », aucune ligne chiffrée (hors lignes de texte) ; les montants valent alors 0 et ne sont pas un vrai zéro"
                    },
                    "serviceOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de prestation d'un devis ponctuel (T-1412) - null : devis par cycle"
                    },
                    "totalExclTax": {
                      "type": "string"
                    },
                    "totalInclTax": {
                      "type": "string"
                    },
                    "currency": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 3,
                      "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                    },
                    "fxRate": {
                      "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "fxRateDate": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Jour de publication du taux figé - null en euros"
                    },
                    "totalExclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du HT au taux figé"
                    },
                    "totalInclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du TTC au taux figé"
                    },
                    "createdOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                    },
                    "sentOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "signedOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "validUntil": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de validité de l'offre (E183 #511) - null : sans échéance"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "portalViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : première consultation au portail par un contact du client ; null : jamais ouvert"
                    },
                    "portalLastViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : dernière consultation au portail"
                    },
                    "portalViewCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "#758 : nombre de consultations au portail (fiche et PDF)"
                    },
                    "alternativeGroupId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : groupe d'alternatives (propositions simultanées pour une même vente) ; null : vente seule"
                    },
                    "alternativeReference": {
                      "type": "boolean",
                      "description": "#753 : proposition qui compte au pipeline dans son groupe (une par groupe, choisie par le commercial)"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "options": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "productPriceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "vatRate": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "totalInclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "productPriceId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "vatRate",
                          "priceSource",
                          "totalExclTax",
                          "totalInclTax",
                          "exclByCycle"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "forecastHistory": {
                      "maxItems": 100,
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "version": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "expectedSignOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "confidence": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "possible",
                                  "probable",
                                  "quasi_certain"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "comment": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "sent",
                              "negotiation",
                              "signed",
                              "refused"
                            ]
                          },
                          "recordedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "actorName": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "quoteId",
                          "version",
                          "expectedSignOn",
                          "confidence",
                          "comment",
                          "totalExclTax",
                          "status",
                          "recordedAt",
                          "actorName"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Les 100 dernières photographies internes de la lignée, de la plus récente à la plus ancienne"
                    },
                    "targetName": {
                      "description": "Nom de la cible (société ou contact) - T-687bis",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subtotalExclTax": {
                      "type": "string"
                    },
                    "discountAmount": {
                      "type": "string"
                    },
                    "discount": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "percent",
                                "amount"
                              ]
                            },
                            "value": {
                              "type": "number",
                              "minimum": 0
                            }
                          },
                          "required": [
                            "type",
                            "value"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "vatBreakdown": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "rate": {
                            "type": "string"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "vat": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "rate",
                          "exclTax",
                          "vat"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "lines": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sectionId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "number"
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          },
                          "isText": {
                            "type": "boolean",
                            "description": "Ligne de texte (#973) : libellé seul, hors de tout total"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "sectionId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "priceSource",
                          "totalExclTax",
                          "exclByCycle",
                          "isText"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "billingPlan": {
                      "anyOf": [
                        {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "label": {
                                "type": "string",
                                "minLength": 1
                              },
                              "percentage": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "maximum": 100
                              },
                              "offsetDays": {
                                "type": "integer",
                                "minimum": -3650,
                                "maximum": 3650
                              },
                              "anchor": {
                                "type": "string",
                                "enum": [
                                  "signature",
                                  "cycle_start"
                                ]
                              }
                            },
                            "required": [
                              "label",
                              "percentage",
                              "offsetDays"
                            ],
                            "additionalProperties": false
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "sections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "isBundle": {
                            "type": "boolean"
                          },
                          "subtotalExclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "isBundle",
                          "subtotalExclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "cycles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "endsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "inclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "startsOn",
                          "endsOn",
                          "exclTax",
                          "inclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "schedule": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "installmentId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "cycleId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleLabel": {
                            "type": "string"
                          },
                          "dueOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "amountInclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "provisional",
                              "to_invoice",
                              "invoiced",
                              "paid",
                              "late",
                              "cancelled"
                            ]
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "invoiceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "invoiceNumber": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "installmentId",
                          "cycleId",
                          "cycleLabel",
                          "dueOn",
                          "amountInclTax",
                          "status",
                          "label",
                          "invoiceId",
                          "invoiceNumber"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "contacts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "contactId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "principal",
                              "operational",
                              "billing",
                              "other"
                            ]
                          }
                        },
                        "required": [
                          "contactId",
                          "role"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "sales_alert",
                              "late_invoices",
                              "contract_terminated",
                              "contract_notice"
                            ]
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "message"
                        ],
                        "additionalProperties": false
                      },
                      "description": "#971 : faits de la société à connaître avant d'envoyer (alerte commerciale, factures en retard, contrat résilié ou en préavis) ; vide si rien ou devis clos"
                    },
                    "alternatives": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "groupId": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "members": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                  },
                                  "number": {
                                    "type": "string"
                                  },
                                  "version": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "status": {
                                    "type": "string",
                                    "enum": [
                                      "draft",
                                      "sent",
                                      "negotiation",
                                      "signed",
                                      "refused"
                                    ]
                                  },
                                  "totalExclTax": {
                                    "type": "string"
                                  },
                                  "reference": {
                                    "type": "boolean",
                                    "description": "Référence du pipeline : seule proposition comptée tant qu'aucune n'est signée"
                                  },
                                  "retained": {
                                    "description": "null : aucune signée ; true : la proposition signée ; false : non retenue, plus acceptable",
                                    "type": [
                                      "boolean",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "id",
                                  "number",
                                  "version",
                                  "status",
                                  "totalExclTax",
                                  "reference",
                                  "retained"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "groupId",
                            "members"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : le groupe d'alternatives du devis ; null : vente seule"
                    }
                  },
                  "required": [
                    "tags",
                    "id",
                    "number",
                    "version",
                    "status",
                    "targetType",
                    "targetId",
                    "ownerId",
                    "lostToCompanyId",
                    "expectedSignOn",
                    "forecastConfidence",
                    "forecastComment",
                    "subject",
                    "commitment",
                    "priced",
                    "serviceOn",
                    "totalExclTax",
                    "totalInclTax",
                    "currency",
                    "fxRate",
                    "fxRateDate",
                    "totalExclTaxEur",
                    "totalInclTaxEur",
                    "createdOn",
                    "sentOn",
                    "signedOn",
                    "validUntil",
                    "updatedAt",
                    "statusChangedAt",
                    "portalViewedAt",
                    "portalLastViewedAt",
                    "portalViewCount",
                    "alternativeGroupId",
                    "alternativeReference",
                    "options",
                    "forecastHistory",
                    "targetName",
                    "subtotalExclTax",
                    "discountAmount",
                    "discount",
                    "vatBreakdown",
                    "customFields",
                    "lines",
                    "billingPlan",
                    "sections",
                    "cycles",
                    "schedule",
                    "contacts",
                    "warnings",
                    "alternatives"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes/{id}/alternative-reference": {
      "post": {
        "summary": "Désigner le devis comme référence du pipeline dans son groupe d'alternatives",
        "description": "Geste explicite du commercial, tracé dans le fil des deux devis (ADR-225 D4). Seule une proposition ouverte d'un groupe sans membre signé devient la référence ; après le refus de la référence, c'est le geste qui rend la vente au pipeline. Devis hors groupe, clos ou groupe signé : 409.",
        "tags": [
          "Devis"
        ],
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Le devis, désormais référence",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string",
                            "enum": [
                              "brand",
                              "comp",
                              "blend",
                              "muted",
                              "deep"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "color"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "number": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "sent",
                        "negotiation",
                        "signed",
                        "refused"
                      ]
                    },
                    "targetType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "contact"
                      ]
                    },
                    "targetId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "ownerId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "lostToCompanyId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "expectedSignOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastConfidence": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "possible",
                            "probable",
                            "quasi_certain"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastComment": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subject": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "commitment": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Engagement pluriannuel - nombre de cycles couverts"
                    },
                    "priced": {
                      "type": "boolean",
                      "description": "#747 : faux = « Non chiffré », aucune ligne chiffrée (hors lignes de texte) ; les montants valent alors 0 et ne sont pas un vrai zéro"
                    },
                    "serviceOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de prestation d'un devis ponctuel (T-1412) - null : devis par cycle"
                    },
                    "totalExclTax": {
                      "type": "string"
                    },
                    "totalInclTax": {
                      "type": "string"
                    },
                    "currency": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 3,
                      "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                    },
                    "fxRate": {
                      "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "fxRateDate": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Jour de publication du taux figé - null en euros"
                    },
                    "totalExclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du HT au taux figé"
                    },
                    "totalInclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du TTC au taux figé"
                    },
                    "createdOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                    },
                    "sentOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "signedOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "validUntil": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de validité de l'offre (E183 #511) - null : sans échéance"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "portalViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : première consultation au portail par un contact du client ; null : jamais ouvert"
                    },
                    "portalLastViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : dernière consultation au portail"
                    },
                    "portalViewCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "#758 : nombre de consultations au portail (fiche et PDF)"
                    },
                    "alternativeGroupId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : groupe d'alternatives (propositions simultanées pour une même vente) ; null : vente seule"
                    },
                    "alternativeReference": {
                      "type": "boolean",
                      "description": "#753 : proposition qui compte au pipeline dans son groupe (une par groupe, choisie par le commercial)"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "options": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "productPriceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "vatRate": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "totalInclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "productPriceId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "vatRate",
                          "priceSource",
                          "totalExclTax",
                          "totalInclTax",
                          "exclByCycle"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "forecastHistory": {
                      "maxItems": 100,
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "version": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "expectedSignOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "confidence": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "possible",
                                  "probable",
                                  "quasi_certain"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "comment": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "sent",
                              "negotiation",
                              "signed",
                              "refused"
                            ]
                          },
                          "recordedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "actorName": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "quoteId",
                          "version",
                          "expectedSignOn",
                          "confidence",
                          "comment",
                          "totalExclTax",
                          "status",
                          "recordedAt",
                          "actorName"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Les 100 dernières photographies internes de la lignée, de la plus récente à la plus ancienne"
                    },
                    "targetName": {
                      "description": "Nom de la cible (société ou contact) - T-687bis",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subtotalExclTax": {
                      "type": "string"
                    },
                    "discountAmount": {
                      "type": "string"
                    },
                    "discount": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "percent",
                                "amount"
                              ]
                            },
                            "value": {
                              "type": "number",
                              "minimum": 0
                            }
                          },
                          "required": [
                            "type",
                            "value"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "vatBreakdown": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "rate": {
                            "type": "string"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "vat": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "rate",
                          "exclTax",
                          "vat"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "lines": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sectionId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "number"
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          },
                          "isText": {
                            "type": "boolean",
                            "description": "Ligne de texte (#973) : libellé seul, hors de tout total"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "sectionId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "priceSource",
                          "totalExclTax",
                          "exclByCycle",
                          "isText"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "billingPlan": {
                      "anyOf": [
                        {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "label": {
                                "type": "string",
                                "minLength": 1
                              },
                              "percentage": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "maximum": 100
                              },
                              "offsetDays": {
                                "type": "integer",
                                "minimum": -3650,
                                "maximum": 3650
                              },
                              "anchor": {
                                "type": "string",
                                "enum": [
                                  "signature",
                                  "cycle_start"
                                ]
                              }
                            },
                            "required": [
                              "label",
                              "percentage",
                              "offsetDays"
                            ],
                            "additionalProperties": false
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "sections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "isBundle": {
                            "type": "boolean"
                          },
                          "subtotalExclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "isBundle",
                          "subtotalExclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "cycles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "endsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "inclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "startsOn",
                          "endsOn",
                          "exclTax",
                          "inclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "schedule": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "installmentId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "cycleId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleLabel": {
                            "type": "string"
                          },
                          "dueOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "amountInclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "provisional",
                              "to_invoice",
                              "invoiced",
                              "paid",
                              "late",
                              "cancelled"
                            ]
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "invoiceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "invoiceNumber": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "installmentId",
                          "cycleId",
                          "cycleLabel",
                          "dueOn",
                          "amountInclTax",
                          "status",
                          "label",
                          "invoiceId",
                          "invoiceNumber"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "contacts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "contactId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "principal",
                              "operational",
                              "billing",
                              "other"
                            ]
                          }
                        },
                        "required": [
                          "contactId",
                          "role"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "sales_alert",
                              "late_invoices",
                              "contract_terminated",
                              "contract_notice"
                            ]
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "message"
                        ],
                        "additionalProperties": false
                      },
                      "description": "#971 : faits de la société à connaître avant d'envoyer (alerte commerciale, factures en retard, contrat résilié ou en préavis) ; vide si rien ou devis clos"
                    },
                    "alternatives": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "groupId": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "members": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                  },
                                  "number": {
                                    "type": "string"
                                  },
                                  "version": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "status": {
                                    "type": "string",
                                    "enum": [
                                      "draft",
                                      "sent",
                                      "negotiation",
                                      "signed",
                                      "refused"
                                    ]
                                  },
                                  "totalExclTax": {
                                    "type": "string"
                                  },
                                  "reference": {
                                    "type": "boolean",
                                    "description": "Référence du pipeline : seule proposition comptée tant qu'aucune n'est signée"
                                  },
                                  "retained": {
                                    "description": "null : aucune signée ; true : la proposition signée ; false : non retenue, plus acceptable",
                                    "type": [
                                      "boolean",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "id",
                                  "number",
                                  "version",
                                  "status",
                                  "totalExclTax",
                                  "reference",
                                  "retained"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "groupId",
                            "members"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : le groupe d'alternatives du devis ; null : vente seule"
                    }
                  },
                  "required": [
                    "tags",
                    "id",
                    "number",
                    "version",
                    "status",
                    "targetType",
                    "targetId",
                    "ownerId",
                    "lostToCompanyId",
                    "expectedSignOn",
                    "forecastConfidence",
                    "forecastComment",
                    "subject",
                    "commitment",
                    "priced",
                    "serviceOn",
                    "totalExclTax",
                    "totalInclTax",
                    "currency",
                    "fxRate",
                    "fxRateDate",
                    "totalExclTaxEur",
                    "totalInclTaxEur",
                    "createdOn",
                    "sentOn",
                    "signedOn",
                    "validUntil",
                    "updatedAt",
                    "statusChangedAt",
                    "portalViewedAt",
                    "portalLastViewedAt",
                    "portalViewCount",
                    "alternativeGroupId",
                    "alternativeReference",
                    "options",
                    "forecastHistory",
                    "targetName",
                    "subtotalExclTax",
                    "discountAmount",
                    "discount",
                    "vatBreakdown",
                    "customFields",
                    "lines",
                    "billingPlan",
                    "sections",
                    "cycles",
                    "schedule",
                    "contacts",
                    "warnings",
                    "alternatives"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes/{id}/alternative-leave": {
      "post": {
        "summary": "Retirer le devis de son groupe d'alternatives (le client achète les deux)",
        "description": "Le devis redevient une vente indépendante, comptée pour elle-même (ADR-225 D6). La référence ne sort pas tant que d'autres membres restent (en désigner une autre d'abord) ; un membre signé ne sort pas. Refus : 409.",
        "tags": [
          "Devis"
        ],
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Le devis, hors groupe",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string",
                            "enum": [
                              "brand",
                              "comp",
                              "blend",
                              "muted",
                              "deep"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "color"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "number": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "sent",
                        "negotiation",
                        "signed",
                        "refused"
                      ]
                    },
                    "targetType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "contact"
                      ]
                    },
                    "targetId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "ownerId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "lostToCompanyId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "expectedSignOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastConfidence": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "possible",
                            "probable",
                            "quasi_certain"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "forecastComment": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subject": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "commitment": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Engagement pluriannuel - nombre de cycles couverts"
                    },
                    "priced": {
                      "type": "boolean",
                      "description": "#747 : faux = « Non chiffré », aucune ligne chiffrée (hors lignes de texte) ; les montants valent alors 0 et ne sont pas un vrai zéro"
                    },
                    "serviceOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de prestation d'un devis ponctuel (T-1412) - null : devis par cycle"
                    },
                    "totalExclTax": {
                      "type": "string"
                    },
                    "totalInclTax": {
                      "type": "string"
                    },
                    "currency": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 3,
                      "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                    },
                    "fxRate": {
                      "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "fxRateDate": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Jour de publication du taux figé - null en euros"
                    },
                    "totalExclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du HT au taux figé"
                    },
                    "totalInclTaxEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros du TTC au taux figé"
                    },
                    "createdOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                    },
                    "sentOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "signedOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "validUntil": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Date de validité de l'offre (E183 #511) - null : sans échéance"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "portalViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : première consultation au portail par un contact du client ; null : jamais ouvert"
                    },
                    "portalLastViewedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#758 : dernière consultation au portail"
                    },
                    "portalViewCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "#758 : nombre de consultations au portail (fiche et PDF)"
                    },
                    "alternativeGroupId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : groupe d'alternatives (propositions simultanées pour une même vente) ; null : vente seule"
                    },
                    "alternativeReference": {
                      "type": "boolean",
                      "description": "#753 : proposition qui compte au pipeline dans son groupe (une par groupe, choisie par le commercial)"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "options": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "productPriceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "vatRate": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "totalInclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "productPriceId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "vatRate",
                          "priceSource",
                          "totalExclTax",
                          "totalInclTax",
                          "exclByCycle"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "forecastHistory": {
                      "maxItems": 100,
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "version": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "expectedSignOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "confidence": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "possible",
                                  "probable",
                                  "quasi_certain"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "comment": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "sent",
                              "negotiation",
                              "signed",
                              "refused"
                            ]
                          },
                          "recordedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "actorName": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "quoteId",
                          "version",
                          "expectedSignOn",
                          "confidence",
                          "comment",
                          "totalExclTax",
                          "status",
                          "recordedAt",
                          "actorName"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Les 100 dernières photographies internes de la lignée, de la plus récente à la plus ancienne"
                    },
                    "targetName": {
                      "description": "Nom de la cible (société ou contact) - T-687bis",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subtotalExclTax": {
                      "type": "string"
                    },
                    "discountAmount": {
                      "type": "string"
                    },
                    "discount": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "percent",
                                "amount"
                              ]
                            },
                            "value": {
                              "type": "number",
                              "minimum": 0
                            }
                          },
                          "required": [
                            "type",
                            "value"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "vatBreakdown": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "rate": {
                            "type": "string"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "vat": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "rate",
                          "exclTax",
                          "vat"
                        ],
                        "additionalProperties": {}
                      }
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "lines": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "productId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sectionId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "unitPrice": {
                            "type": "string"
                          },
                          "quantity": {
                            "type": "number"
                          },
                          "cycleIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "discountPercent": {
                            "type": "string"
                          },
                          "priceSource": {
                            "type": "string",
                            "enum": [
                              "list",
                              "negotiated",
                              "rule",
                              "manual"
                            ]
                          },
                          "totalExclTax": {
                            "type": "string"
                          },
                          "exclByCycle": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "additionalProperties": {
                              "type": "string"
                            }
                          },
                          "isText": {
                            "type": "boolean",
                            "description": "Ligne de texte (#973) : libellé seul, hors de tout total"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "productId",
                          "sectionId",
                          "businessUnitId",
                          "unitPrice",
                          "quantity",
                          "cycleIds",
                          "discountPercent",
                          "priceSource",
                          "totalExclTax",
                          "exclByCycle",
                          "isText"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "billingPlan": {
                      "anyOf": [
                        {
                          "minItems": 1,
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "label": {
                                "type": "string",
                                "minLength": 1
                              },
                              "percentage": {
                                "type": "number",
                                "exclusiveMinimum": 0,
                                "maximum": 100
                              },
                              "offsetDays": {
                                "type": "integer",
                                "minimum": -3650,
                                "maximum": 3650
                              },
                              "anchor": {
                                "type": "string",
                                "enum": [
                                  "signature",
                                  "cycle_start"
                                ]
                              }
                            },
                            "required": [
                              "label",
                              "percentage",
                              "offsetDays"
                            ],
                            "additionalProperties": false
                          }
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "sections": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "isBundle": {
                            "type": "boolean"
                          },
                          "subtotalExclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "isBundle",
                          "subtotalExclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "cycles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "label": {
                            "type": "string"
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "endsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "exclTax": {
                            "type": "string"
                          },
                          "inclTax": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "label",
                          "startsOn",
                          "endsOn",
                          "exclTax",
                          "inclTax"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "schedule": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "installmentId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "cycleId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleLabel": {
                            "type": "string"
                          },
                          "dueOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "amountInclTax": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "provisional",
                              "to_invoice",
                              "invoiced",
                              "paid",
                              "late",
                              "cancelled"
                            ]
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "invoiceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "invoiceNumber": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "installmentId",
                          "cycleId",
                          "cycleLabel",
                          "dueOn",
                          "amountInclTax",
                          "status",
                          "label",
                          "invoiceId",
                          "invoiceNumber"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "contacts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "contactId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "principal",
                              "operational",
                              "billing",
                              "other"
                            ]
                          }
                        },
                        "required": [
                          "contactId",
                          "role"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "sales_alert",
                              "late_invoices",
                              "contract_terminated",
                              "contract_notice"
                            ]
                          },
                          "message": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "message"
                        ],
                        "additionalProperties": false
                      },
                      "description": "#971 : faits de la société à connaître avant d'envoyer (alerte commerciale, factures en retard, contrat résilié ou en préavis) ; vide si rien ou devis clos"
                    },
                    "alternatives": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "groupId": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "members": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                  },
                                  "number": {
                                    "type": "string"
                                  },
                                  "version": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "status": {
                                    "type": "string",
                                    "enum": [
                                      "draft",
                                      "sent",
                                      "negotiation",
                                      "signed",
                                      "refused"
                                    ]
                                  },
                                  "totalExclTax": {
                                    "type": "string"
                                  },
                                  "reference": {
                                    "type": "boolean",
                                    "description": "Référence du pipeline : seule proposition comptée tant qu'aucune n'est signée"
                                  },
                                  "retained": {
                                    "description": "null : aucune signée ; true : la proposition signée ; false : non retenue, plus acceptable",
                                    "type": [
                                      "boolean",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "id",
                                  "number",
                                  "version",
                                  "status",
                                  "totalExclTax",
                                  "reference",
                                  "retained"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "groupId",
                            "members"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#753 : le groupe d'alternatives du devis ; null : vente seule"
                    }
                  },
                  "required": [
                    "tags",
                    "id",
                    "number",
                    "version",
                    "status",
                    "targetType",
                    "targetId",
                    "ownerId",
                    "lostToCompanyId",
                    "expectedSignOn",
                    "forecastConfidence",
                    "forecastComment",
                    "subject",
                    "commitment",
                    "priced",
                    "serviceOn",
                    "totalExclTax",
                    "totalInclTax",
                    "currency",
                    "fxRate",
                    "fxRateDate",
                    "totalExclTaxEur",
                    "totalInclTaxEur",
                    "createdOn",
                    "sentOn",
                    "signedOn",
                    "validUntil",
                    "updatedAt",
                    "statusChangedAt",
                    "portalViewedAt",
                    "portalLastViewedAt",
                    "portalViewCount",
                    "alternativeGroupId",
                    "alternativeReference",
                    "options",
                    "forecastHistory",
                    "targetName",
                    "subtotalExclTax",
                    "discountAmount",
                    "discount",
                    "vatBreakdown",
                    "customFields",
                    "lines",
                    "billingPlan",
                    "sections",
                    "cycles",
                    "schedule",
                    "contacts",
                    "warnings",
                    "alternatives"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes/{id}/pdf": {
      "get": {
        "summary": "PDF du devis (si PDF_RENDERER=chromium est actif - 404 sinon)",
        "tags": [
          "Devis"
        ],
        "security": [
          {
            "oauth2": [
              "quotes:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Document PDF (application/pdf, attachment)"
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes/{id}/approval-request": {
      "post": {
        "summary": "Demander l’accord d’un devis",
        "description": "Personne authentifiée et droit de modification requis ; les comptes techniques sont refusés. Le même dossier est rendu au rejeu si les faits et règles restent identiques. Aucun accord, signature ou envoi du devis : la décision reste humaine à l’écran.",
        "tags": [
          "Devis"
        ],
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Dossier d’accord créé ou déjà en cours.",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "caseId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "required": [
                    "ok",
                    "caseId"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes/variations": {
      "get": {
        "summary": "Explique la variation de l'encours entre deux instants (#749)",
        "description": "Une ligne par lignée, montants HT en centimes. Une sortie devenue invisible ne livre ni identifiant, ni état final. Les activités nécessitent leur propre droit de lecture. Période inversée ou future : 422. Avant la collecte : bridge null.",
        "tags": [
          "Devis"
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "ownerId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "businessUnitId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "quotes:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Comparaison datée et réconciliation",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "from": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "to": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "since": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "unavailableReason": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "history",
                            "visibility"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "bridge": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "before": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Montant HT en centimes, sans pondération"
                            },
                            "after": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Montant HT en centimes, sans pondération"
                            },
                            "delta": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Montant HT en centimes, sans pondération"
                            },
                            "movements": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "rootId": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "format": "uuid",
                                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "quoteId": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "format": "uuid",
                                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "kind": {
                                    "type": "string",
                                    "enum": [
                                      "new",
                                      "increase",
                                      "decrease",
                                      "won",
                                      "lost",
                                      "entered",
                                      "exited",
                                      "postponed",
                                      "reassigned"
                                    ]
                                  },
                                  "before": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Montant HT en centimes, sans pondération"
                                  },
                                  "after": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Montant HT en centimes, sans pondération"
                                  },
                                  "delta": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Montant HT en centimes, sans pondération"
                                  },
                                  "postponed": {
                                    "type": "boolean"
                                  },
                                  "reassigned": {
                                    "type": "boolean"
                                  },
                                  "previousDate": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "format": "date",
                                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "expectedDate": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "format": "date",
                                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "previousOwnerId": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "format": "uuid",
                                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "ownerId": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "format": "uuid",
                                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "number": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "ownerName": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "previousOwnerName": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "nextActivity": {
                                    "anyOf": [
                                      {
                                        "type": "object",
                                        "properties": {
                                          "id": {
                                            "type": "string",
                                            "format": "uuid",
                                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                          },
                                          "title": {
                                            "type": "string"
                                          },
                                          "at": {
                                            "anyOf": [
                                              {
                                                "type": "string",
                                                "format": "date-time",
                                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                              },
                                              {
                                                "type": "null"
                                              }
                                            ]
                                          }
                                        },
                                        "required": [
                                          "id",
                                          "title",
                                          "at"
                                        ],
                                        "additionalProperties": false
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  }
                                },
                                "required": [
                                  "rootId",
                                  "quoteId",
                                  "kind",
                                  "before",
                                  "after",
                                  "delta",
                                  "postponed",
                                  "reassigned",
                                  "previousDate",
                                  "expectedDate",
                                  "previousOwnerId",
                                  "ownerId",
                                  "number",
                                  "ownerName",
                                  "previousOwnerName",
                                  "nextActivity"
                                ],
                                "additionalProperties": false
                              }
                            },
                            "categories": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string",
                                "enum": [
                                  "new",
                                  "increase",
                                  "decrease",
                                  "won",
                                  "lost",
                                  "entered",
                                  "exited",
                                  "postponed",
                                  "reassigned"
                                ]
                              },
                              "additionalProperties": {
                                "type": "object",
                                "properties": {
                                  "count": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "cents": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Montant HT en centimes, sans pondération"
                                  }
                                },
                                "required": [
                                  "count",
                                  "cents"
                                ],
                                "additionalProperties": false
                              },
                              "required": [
                                "new",
                                "increase",
                                "decrease",
                                "won",
                                "lost",
                                "entered",
                                "exited",
                                "postponed",
                                "reassigned"
                              ]
                            }
                          },
                          "required": [
                            "before",
                            "after",
                            "delta",
                            "movements",
                            "categories"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Null avant le début de collecte, jamais un zéro reconstitué"
                    }
                  },
                  "required": [
                    "from",
                    "to",
                    "since",
                    "unavailableReason",
                    "bridge"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes/cohort": {
      "get": {
        "summary": "Conversions d’une cohorte de propositions envoyées",
        "description": "Une vente par versions et alternatives, premier envoi attesté dans la période, situation à measuredAt. Le dénominateur comprend les ventes ouvertes. Historique insuffisant dans incomplete, hors taux et délais. Les filtres commercial, entité et famille portent sur les attributs actuels. Même visibilité que l’écran ; aucune donnée écrite.",
        "tags": [
          "Ventes"
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "ownerId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "businessUnitId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "family",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "quotes:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Cohorte et détail réconciliés",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "measuredAt": {
                      "type": "string"
                    },
                    "total": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "signed": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "refused": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "open": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "signatureRate": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "medianSignatureDays": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "datedSignatures": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "families": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "reasons": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "reason": {
                            "type": "string"
                          },
                          "count": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "reason",
                          "count"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "incomplete": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "number": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "quoteId",
                          "number"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "rows": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "number": {
                            "type": "string"
                          },
                          "ownerId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "ownerName": {
                            "type": "string"
                          },
                          "unitIds": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "families": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "versions": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "alternatives": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "outcome": {
                            "type": "string",
                            "enum": [
                              "signed",
                              "refused",
                              "open"
                            ]
                          },
                          "sentAt": {
                            "type": "string"
                          },
                          "signedAt": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "signatureDays": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "reason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "stages": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "draft",
                                    "sent",
                                    "negotiation",
                                    "signed",
                                    "refused"
                                  ]
                                },
                                "from": {
                                  "type": "string"
                                },
                                "to": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "days": {
                                  "type": [
                                    "number",
                                    "null"
                                  ]
                                }
                              },
                              "required": [
                                "status",
                                "from",
                                "to",
                                "days"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "id",
                          "quoteId",
                          "number",
                          "ownerId",
                          "ownerName",
                          "unitIds",
                          "families",
                          "versions",
                          "alternatives",
                          "outcome",
                          "sentAt",
                          "signedAt",
                          "signatureDays",
                          "reason",
                          "stages"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "from",
                    "to",
                    "measuredAt",
                    "total",
                    "signed",
                    "refused",
                    "open",
                    "signatureRate",
                    "medianSignatureDays",
                    "datedSignatures",
                    "families",
                    "reasons",
                    "incomplete",
                    "rows"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/requests": {
      "get": {
        "summary": "Lister les requêtes (hors corbeille)",
        "tags": [
          "Requêtes"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Jours (1 à 365) - objets dans leur statut courant depuis plus de N jours (status_changed_at), combinable avec status (T-1407)",
              "type": "integer",
              "minimum": 1,
              "maximum": 365
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "new",
                "in_progress",
                "waiting_client",
                "resolved",
                "closed"
              ]
            }
          },
          {
            "name": "priority",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "low",
                "normal",
                "high"
              ]
            }
          },
          {
            "name": "companyId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          },
          {
            "name": "contactId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          },
          {
            "name": "ownerId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Id d'un commercial, ou `none` = non attribuées",
              "type": "string"
            }
          },
          {
            "name": "quoteId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "requests:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de requêtes",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "number": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "companyId": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "contactId": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "quoteId": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "reason": {
                            "type": "string"
                          },
                          "priority": {
                            "type": "string",
                            "enum": [
                              "low",
                              "normal",
                              "high"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "new",
                              "in_progress",
                              "waiting_client",
                              "resolved",
                              "closed"
                            ]
                          },
                          "ownerId": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdBy": {
                            "type": "string"
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "customFields": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {
                              "type": [
                                "string",
                                "number",
                                "boolean"
                              ]
                            }
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "statusChangedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                            "description": "Entrée dans le statut courant (T-1407)"
                          },
                          "mergedIntoId": {
                            "description": "#1058 : fermée par fusion dans cette requête (irréversible)",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "possibleDuplicateOfId": {
                            "description": "#1058 : doublon possible d'une requête ouverte du même sujet et motif (moins de sept jours), marqué à la création, jamais fusionné d'office",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "firstResponseDueAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#1056 : échéance de première réponse, en heures ouvrées depuis la création (null sans règle de délai)"
                          },
                          "resolutionDueAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#1056 : échéance de résolution, temps gelé en attente client ajouté"
                          },
                          "firstRespondedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#1056 : première réponse publique de l'équipe"
                          },
                          "slaPausedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#1056 : début du gel en attente client, null hors gel"
                          },
                          "slaBreached": {
                            "type": "boolean",
                            "description": "#1056 : une échéance est passée sans être tenue (dérivé à la lecture)"
                          }
                        },
                        "required": [
                          "id",
                          "number",
                          "title",
                          "companyId",
                          "contactId",
                          "quoteId",
                          "reason",
                          "priority",
                          "status",
                          "ownerId",
                          "createdBy",
                          "description",
                          "customFields",
                          "createdAt",
                          "updatedAt",
                          "statusChangedAt",
                          "mergedIntoId",
                          "possibleDuplicateOfId",
                          "firstResponseDueAt",
                          "resolutionDueAt",
                          "firstRespondedAt",
                          "slaPausedAt",
                          "slaBreached"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Créer une requête - numéro RQ- calculé serveur",
        "description": "Le sujet (société ou contact) doit être vivant ; le devis lié, s'il est fourni, doit cibler le même sujet. Sans ownerId : non attribuée (file commune).",
        "tags": [
          "Requêtes"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "title": {
                    "description": "Requis sans `emailMessageId`",
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 200
                  },
                  "companyId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "contactId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "quoteId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "reason": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "low",
                      "normal",
                      "high"
                    ]
                  },
                  "ownerId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 5000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "customFields": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "maxLength": 80
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 2000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "emailMessageId": {
                    "description": "#1060 : identifiant d'un email synchronisé (module Messagerie) : la requête naît de l'email (objet, corps, pièces jointes, sujet) ; un email déjà lié est refusé (409)",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  }
                },
                "required": [
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "requests:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Requête créée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "number": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "companyId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contactId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "reason": {
                      "type": "string"
                    },
                    "priority": {
                      "type": "string",
                      "enum": [
                        "low",
                        "normal",
                        "high"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "new",
                        "in_progress",
                        "waiting_client",
                        "resolved",
                        "closed"
                      ]
                    },
                    "ownerId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "createdBy": {
                      "type": "string"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "mergedIntoId": {
                      "description": "#1058 : fermée par fusion dans cette requête (irréversible)",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "possibleDuplicateOfId": {
                      "description": "#1058 : doublon possible d'une requête ouverte du même sujet et motif (moins de sept jours), marqué à la création, jamais fusionné d'office",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "firstResponseDueAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : échéance de première réponse, en heures ouvrées depuis la création (null sans règle de délai)"
                    },
                    "resolutionDueAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : échéance de résolution, temps gelé en attente client ajouté"
                    },
                    "firstRespondedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : première réponse publique de l'équipe"
                    },
                    "slaPausedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : début du gel en attente client, null hors gel"
                    },
                    "slaBreached": {
                      "type": "boolean",
                      "description": "#1056 : une échéance est passée sans être tenue (dérivé à la lecture)"
                    }
                  },
                  "required": [
                    "id",
                    "number",
                    "title",
                    "companyId",
                    "contactId",
                    "quoteId",
                    "reason",
                    "priority",
                    "status",
                    "ownerId",
                    "createdBy",
                    "description",
                    "customFields",
                    "createdAt",
                    "updatedAt",
                    "statusChangedAt",
                    "mergedIntoId",
                    "possibleDuplicateOfId",
                    "firstResponseDueAt",
                    "resolutionDueAt",
                    "firstRespondedAt",
                    "slaPausedAt",
                    "slaBreached"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/requests/{id}": {
      "get": {
        "summary": "Détail d'une requête",
        "tags": [
          "Requêtes"
        ],
        "security": [
          {
            "oauth2": [
              "requests:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Requête",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "number": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "companyId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contactId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "reason": {
                      "type": "string"
                    },
                    "priority": {
                      "type": "string",
                      "enum": [
                        "low",
                        "normal",
                        "high"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "new",
                        "in_progress",
                        "waiting_client",
                        "resolved",
                        "closed"
                      ]
                    },
                    "ownerId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "createdBy": {
                      "type": "string"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "mergedIntoId": {
                      "description": "#1058 : fermée par fusion dans cette requête (irréversible)",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "possibleDuplicateOfId": {
                      "description": "#1058 : doublon possible d'une requête ouverte du même sujet et motif (moins de sept jours), marqué à la création, jamais fusionné d'office",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "firstResponseDueAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : échéance de première réponse, en heures ouvrées depuis la création (null sans règle de délai)"
                    },
                    "resolutionDueAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : échéance de résolution, temps gelé en attente client ajouté"
                    },
                    "firstRespondedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : première réponse publique de l'équipe"
                    },
                    "slaPausedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : début du gel en attente client, null hors gel"
                    },
                    "slaBreached": {
                      "type": "boolean",
                      "description": "#1056 : une échéance est passée sans être tenue (dérivé à la lecture)"
                    }
                  },
                  "required": [
                    "id",
                    "number",
                    "title",
                    "companyId",
                    "contactId",
                    "quoteId",
                    "reason",
                    "priority",
                    "status",
                    "ownerId",
                    "createdBy",
                    "description",
                    "customFields",
                    "createdAt",
                    "updatedAt",
                    "statusChangedAt",
                    "mergedIntoId",
                    "possibleDuplicateOfId",
                    "firstResponseDueAt",
                    "resolutionDueAt",
                    "firstRespondedAt",
                    "slaPausedAt",
                    "slaBreached"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Modifier une requête (champs de fiche - le statut passe par /transition)",
        "tags": [
          "Requêtes"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 200
                  },
                  "reason": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "low",
                      "normal",
                      "high"
                    ]
                  },
                  "ownerId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 5000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "customFields": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "maxLength": 80
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 2000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "requests:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Requête modifiée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "number": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "companyId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contactId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "reason": {
                      "type": "string"
                    },
                    "priority": {
                      "type": "string",
                      "enum": [
                        "low",
                        "normal",
                        "high"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "new",
                        "in_progress",
                        "waiting_client",
                        "resolved",
                        "closed"
                      ]
                    },
                    "ownerId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "createdBy": {
                      "type": "string"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "mergedIntoId": {
                      "description": "#1058 : fermée par fusion dans cette requête (irréversible)",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "possibleDuplicateOfId": {
                      "description": "#1058 : doublon possible d'une requête ouverte du même sujet et motif (moins de sept jours), marqué à la création, jamais fusionné d'office",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "firstResponseDueAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : échéance de première réponse, en heures ouvrées depuis la création (null sans règle de délai)"
                    },
                    "resolutionDueAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : échéance de résolution, temps gelé en attente client ajouté"
                    },
                    "firstRespondedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : première réponse publique de l'équipe"
                    },
                    "slaPausedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : début du gel en attente client, null hors gel"
                    },
                    "slaBreached": {
                      "type": "boolean",
                      "description": "#1056 : une échéance est passée sans être tenue (dérivé à la lecture)"
                    }
                  },
                  "required": [
                    "id",
                    "number",
                    "title",
                    "companyId",
                    "contactId",
                    "quoteId",
                    "reason",
                    "priority",
                    "status",
                    "ownerId",
                    "createdBy",
                    "description",
                    "customFields",
                    "createdAt",
                    "updatedAt",
                    "statusChangedAt",
                    "mergedIntoId",
                    "possibleDuplicateOfId",
                    "firstResponseDueAt",
                    "resolutionDueAt",
                    "firstRespondedAt",
                    "slaPausedAt",
                    "slaBreached"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/requests/{id}/transition": {
      "post": {
        "summary": "Changer le statut - matrice fermée (422 avec transitions permises sinon)",
        "tags": [
          "Requêtes"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "enum": [
                      "in_progress",
                      "waiting_client",
                      "resolved",
                      "closed"
                    ]
                  }
                },
                "required": [
                  "to"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "requests:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Requête transitionnée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "number": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "companyId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contactId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "reason": {
                      "type": "string"
                    },
                    "priority": {
                      "type": "string",
                      "enum": [
                        "low",
                        "normal",
                        "high"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "new",
                        "in_progress",
                        "waiting_client",
                        "resolved",
                        "closed"
                      ]
                    },
                    "ownerId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "createdBy": {
                      "type": "string"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "customFields": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "mergedIntoId": {
                      "description": "#1058 : fermée par fusion dans cette requête (irréversible)",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "possibleDuplicateOfId": {
                      "description": "#1058 : doublon possible d'une requête ouverte du même sujet et motif (moins de sept jours), marqué à la création, jamais fusionné d'office",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "firstResponseDueAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : échéance de première réponse, en heures ouvrées depuis la création (null sans règle de délai)"
                    },
                    "resolutionDueAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : échéance de résolution, temps gelé en attente client ajouté"
                    },
                    "firstRespondedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : première réponse publique de l'équipe"
                    },
                    "slaPausedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#1056 : début du gel en attente client, null hors gel"
                    },
                    "slaBreached": {
                      "type": "boolean",
                      "description": "#1056 : une échéance est passée sans être tenue (dérivé à la lecture)"
                    }
                  },
                  "required": [
                    "id",
                    "number",
                    "title",
                    "companyId",
                    "contactId",
                    "quoteId",
                    "reason",
                    "priority",
                    "status",
                    "ownerId",
                    "createdBy",
                    "description",
                    "customFields",
                    "createdAt",
                    "updatedAt",
                    "statusChangedAt",
                    "mergedIntoId",
                    "possibleDuplicateOfId",
                    "firstResponseDueAt",
                    "resolutionDueAt",
                    "firstRespondedAt",
                    "slaPausedAt",
                    "slaBreached"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/reply-templates": {
      "get": {
        "summary": "Réponses types des requêtes (organisation et personnelles de l'acteur, actives)",
        "tags": [
          "Requêtes"
        ],
        "parameters": [
          {
            "name": "reason",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Ne garder que ce motif et les réponses de tous les motifs",
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "requests:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Les réponses types utilisables par l'acteur de la clé",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "reason": {
                            "description": "Motif visé ; null = tous les motifs",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "body": {
                            "type": "string",
                            "description": "Texte en marqueurs du fil (**gras**, _italique_), variables {{prenom}}, {{nom}}, {{societe}}, {{numero}}, {{titre}}, {{entite}}, {{signature}}"
                          },
                          "setStatus": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "in_progress",
                                  "waiting_client",
                                  "resolved"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Statut posé à l'envoi"
                          },
                          "addTag": {
                            "description": "Étiquette posée à l'envoi",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "scope": {
                            "type": "string",
                            "enum": [
                              "organization",
                              "personal"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "reason",
                          "body",
                          "setStatus",
                          "addTag",
                          "scope"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/sales-activities": {
      "get": {
        "summary": "Lister les activités commerciales (hors corbeille)",
        "tags": [
          "Activités commerciales"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "call",
                "meeting",
                "task"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "open",
                "done",
                "cancelled"
              ]
            }
          },
          {
            "name": "assignedTo",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          },
          {
            "name": "companyId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          },
          {
            "name": "contactId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          },
          {
            "name": "quoteId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          },
          {
            "name": "requestId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "sales_activities:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page d'activités commerciales",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "call",
                              "meeting",
                              "task"
                            ]
                          },
                          "title": {
                            "type": "string"
                          },
                          "description": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "open",
                              "done",
                              "cancelled"
                            ]
                          },
                          "dueAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "startsAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "endsAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "location": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "assignedTo": {
                            "type": "string"
                          },
                          "createdBy": {
                            "type": "string"
                          },
                          "companyId": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "contactId": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "quoteId": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "requestId": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "completedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "completedBy": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "kind",
                          "title",
                          "description",
                          "status",
                          "dueAt",
                          "startsAt",
                          "endsAt",
                          "location",
                          "assignedTo",
                          "createdBy",
                          "companyId",
                          "contactId",
                          "quoteId",
                          "requestId",
                          "completedAt",
                          "completedBy",
                          "createdAt",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Créer une activité - RDV : startsAt requis ; completed = appel loggé",
        "description": "Les liens (société, contact, devis, requête) doivent être vivants ; un lien devis/requête remplit company_id/contact_id (dénormalisation serveur). Sans assignedTo : assignée au user d'intégration créateur.",
        "tags": [
          "Activités commerciales"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "call",
                      "meeting",
                      "task"
                    ]
                  },
                  "title": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 200
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 5000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "dueAt": {
                    "anyOf": [
                      {
                        "anyOf": [
                          {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                              },
                              {
                                "type": "string",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                              }
                            ]
                          },
                          {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          }
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "startsAt": {
                    "anyOf": [
                      {
                        "anyOf": [
                          {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                              },
                              {
                                "type": "string",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                              }
                            ]
                          },
                          {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          }
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "endsAt": {
                    "anyOf": [
                      {
                        "anyOf": [
                          {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                              },
                              {
                                "type": "string",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                              }
                            ]
                          },
                          {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          }
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "location": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "assignedTo": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "companyId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "contactId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "quoteId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "requestId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "completed": {
                    "type": "boolean"
                  },
                  "note": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 5000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "kind",
                  "title"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "sales_activities:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Activité créée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "call",
                        "meeting",
                        "task"
                      ]
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "open",
                        "done",
                        "cancelled"
                      ]
                    },
                    "dueAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "startsAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "endsAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "location": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "assignedTo": {
                      "type": "string"
                    },
                    "createdBy": {
                      "type": "string"
                    },
                    "companyId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contactId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "requestId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "completedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "completedBy": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "kind",
                    "title",
                    "description",
                    "status",
                    "dueAt",
                    "startsAt",
                    "endsAt",
                    "location",
                    "assignedTo",
                    "createdBy",
                    "companyId",
                    "contactId",
                    "quoteId",
                    "requestId",
                    "completedAt",
                    "completedBy",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/sales-activities/{id}": {
      "get": {
        "summary": "Détail d'une activité commerciale",
        "tags": [
          "Activités commerciales"
        ],
        "security": [
          {
            "oauth2": [
              "sales_activities:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Activité",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "call",
                        "meeting",
                        "task"
                      ]
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "open",
                        "done",
                        "cancelled"
                      ]
                    },
                    "dueAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "startsAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "endsAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "location": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "assignedTo": {
                      "type": "string"
                    },
                    "createdBy": {
                      "type": "string"
                    },
                    "companyId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contactId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "requestId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "completedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "completedBy": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "kind",
                    "title",
                    "description",
                    "status",
                    "dueAt",
                    "startsAt",
                    "endsAt",
                    "location",
                    "assignedTo",
                    "createdBy",
                    "companyId",
                    "contactId",
                    "quoteId",
                    "requestId",
                    "completedAt",
                    "completedBy",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Modifier une activité OUVERTE (le statut passe par /transition)",
        "tags": [
          "Activités commerciales"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 200
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 5000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "dueAt": {
                    "anyOf": [
                      {
                        "anyOf": [
                          {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                              },
                              {
                                "type": "string",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                              }
                            ]
                          },
                          {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          }
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "startsAt": {
                    "anyOf": [
                      {
                        "anyOf": [
                          {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                              },
                              {
                                "type": "string",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                              }
                            ]
                          },
                          {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          }
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "endsAt": {
                    "anyOf": [
                      {
                        "anyOf": [
                          {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                              },
                              {
                                "type": "string",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                              }
                            ]
                          },
                          {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          }
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "location": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "assignedTo": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "companyId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "contactId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "quoteId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "requestId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "sales_activities:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Activité modifiée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "call",
                        "meeting",
                        "task"
                      ]
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "open",
                        "done",
                        "cancelled"
                      ]
                    },
                    "dueAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "startsAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "endsAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "location": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "assignedTo": {
                      "type": "string"
                    },
                    "createdBy": {
                      "type": "string"
                    },
                    "companyId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contactId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "requestId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "completedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "completedBy": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "kind",
                    "title",
                    "description",
                    "status",
                    "dueAt",
                    "startsAt",
                    "endsAt",
                    "location",
                    "assignedTo",
                    "createdBy",
                    "companyId",
                    "contactId",
                    "quoteId",
                    "requestId",
                    "completedAt",
                    "completedBy",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/sales-activities/{id}/transition": {
      "post": {
        "summary": "Réaliser ou annuler - écrit l'entrée de fil correspondante",
        "tags": [
          "Activités commerciales"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "enum": [
                      "done",
                      "cancelled"
                    ]
                  }
                },
                "required": [
                  "to"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "sales_activities:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Activité clôturée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "call",
                        "meeting",
                        "task"
                      ]
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "open",
                        "done",
                        "cancelled"
                      ]
                    },
                    "dueAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "startsAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "endsAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "location": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "assignedTo": {
                      "type": "string"
                    },
                    "createdBy": {
                      "type": "string"
                    },
                    "companyId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "contactId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "requestId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "completedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "completedBy": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "createdAt": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "kind",
                    "title",
                    "description",
                    "status",
                    "dueAt",
                    "startsAt",
                    "endsAt",
                    "location",
                    "assignedTo",
                    "createdBy",
                    "companyId",
                    "contactId",
                    "quoteId",
                    "requestId",
                    "completedAt",
                    "completedBy",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/sales-targets": {
      "get": {
        "summary": "Objectifs individuels d'un cycle : objectif d'équipe, somme attribuée, reste, une ligne par commercial (#750)",
        "tags": [
          "Objectifs"
        ],
        "parameters": [
          {
            "name": "cycleId",
            "in": "query",
            "required": true,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "settings:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Répartition du cycle",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "cycle": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "label": {
                          "type": "string"
                        },
                        "startsOn": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        "endsOn": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "upcoming",
                            "active",
                            "closed"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "label",
                        "startsOn",
                        "endsOn",
                        "status"
                      ],
                      "additionalProperties": false
                    },
                    "mode": {
                      "type": "string",
                      "enum": [
                        "equal",
                        "individual"
                      ],
                      "description": "Mode qui s'applique au cycle (figé pour un cycle clos)"
                    },
                    "editable": {
                      "type": "boolean",
                      "description": "Faux pour un cycle clos : l'historique se lit, il ne se modifie plus"
                    },
                    "teamTarget": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "Montant HT, deux décimales"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Somme des objectifs d'entités du cycle ; null si aucune n'en porte"
                    },
                    "assigned": {
                      "type": "string",
                      "description": "Somme des objectifs des commerciaux listés"
                    },
                    "remaining": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "Montant HT, deux décimales"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Objectif d'équipe moins la somme attribuée ; négatif = dépassement"
                    },
                    "overAllocated": {
                      "type": "boolean"
                    },
                    "divisor": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Diviseur de la répartition égale ; null en mode individuel"
                    },
                    "sellers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "userId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "active": {
                            "type": "boolean",
                            "description": "Faux pour un commercial parti, listé en lecture s'il porte un objectif"
                          },
                          "target": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "Montant HT, deux décimales"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Objectif tous périmètres ; null = non défini"
                          },
                          "entries": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "businessUnitId": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "uuid",
                                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ],
                                  "description": "Null = tous périmètres"
                                },
                                "amount": {
                                  "type": "string",
                                  "description": "Montant HT, deux décimales"
                                },
                                "updatedAt": {
                                  "type": "string",
                                  "format": "date-time",
                                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                },
                                "updatedBy": {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                }
                              },
                              "required": [
                                "businessUnitId",
                                "amount",
                                "updatedAt",
                                "updatedBy"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "userId",
                          "name",
                          "active",
                          "target",
                          "entries"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "cycle",
                    "mode",
                    "editable",
                    "teamTarget",
                    "assigned",
                    "remaining",
                    "overAllocated",
                    "divisor",
                    "sellers"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Pose, modifie ou retire (amount null) l'objectif d'un commercial sur un cycle non clos (#750)",
        "description": "Un dépassement de l'objectif d'équipe est signalé dans la réponse (`overAllocated`), jamais refusé. Cycle clos : 422 `not-editable`.",
        "tags": [
          "Objectifs"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "userId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "cycleId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "businessUnitId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "amount": {
                    "anyOf": [
                      {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 999999999999.99
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "userId",
                  "cycleId",
                  "businessUnitId",
                  "amount"
                ]
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "settings:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Répartition du cycle après écriture",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "cycle": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "label": {
                          "type": "string"
                        },
                        "startsOn": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        "endsOn": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "upcoming",
                            "active",
                            "closed"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "label",
                        "startsOn",
                        "endsOn",
                        "status"
                      ],
                      "additionalProperties": false
                    },
                    "mode": {
                      "type": "string",
                      "enum": [
                        "equal",
                        "individual"
                      ],
                      "description": "Mode qui s'applique au cycle (figé pour un cycle clos)"
                    },
                    "editable": {
                      "type": "boolean",
                      "description": "Faux pour un cycle clos : l'historique se lit, il ne se modifie plus"
                    },
                    "teamTarget": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "Montant HT, deux décimales"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Somme des objectifs d'entités du cycle ; null si aucune n'en porte"
                    },
                    "assigned": {
                      "type": "string",
                      "description": "Somme des objectifs des commerciaux listés"
                    },
                    "remaining": {
                      "anyOf": [
                        {
                          "type": "string",
                          "description": "Montant HT, deux décimales"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Objectif d'équipe moins la somme attribuée ; négatif = dépassement"
                    },
                    "overAllocated": {
                      "type": "boolean"
                    },
                    "divisor": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Diviseur de la répartition égale ; null en mode individuel"
                    },
                    "sellers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "userId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "active": {
                            "type": "boolean",
                            "description": "Faux pour un commercial parti, listé en lecture s'il porte un objectif"
                          },
                          "target": {
                            "anyOf": [
                              {
                                "type": "string",
                                "description": "Montant HT, deux décimales"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Objectif tous périmètres ; null = non défini"
                          },
                          "entries": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "businessUnitId": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "uuid",
                                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ],
                                  "description": "Null = tous périmètres"
                                },
                                "amount": {
                                  "type": "string",
                                  "description": "Montant HT, deux décimales"
                                },
                                "updatedAt": {
                                  "type": "string",
                                  "format": "date-time",
                                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                },
                                "updatedBy": {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                }
                              },
                              "required": [
                                "businessUnitId",
                                "amount",
                                "updatedAt",
                                "updatedBy"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "userId",
                          "name",
                          "active",
                          "target",
                          "entries"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "cycle",
                    "mode",
                    "editable",
                    "teamTarget",
                    "assigned",
                    "remaining",
                    "overAllocated",
                    "divisor",
                    "sellers"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/sales-targets/mode": {
      "get": {
        "summary": "Mode de répartition des objectifs de l'organisation (#750)",
        "tags": [
          "Objectifs"
        ],
        "security": [
          {
            "oauth2": [
              "settings:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Mode courant",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "mode": {
                      "type": "string",
                      "enum": [
                        "equal",
                        "individual"
                      ]
                    }
                  },
                  "required": [
                    "mode"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Change le mode de répartition, sans réécrire aucun cycle clos (#750)",
        "tags": [
          "Objectifs"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": [
                      "equal",
                      "individual"
                    ]
                  }
                },
                "required": [
                  "mode"
                ]
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "settings:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Mode enregistré",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "mode": {
                      "type": "string",
                      "enum": [
                        "equal",
                        "individual"
                      ]
                    }
                  },
                  "required": [
                    "mode"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/kpis": {
      "get": {
        "summary": "Pont du chiffre signé entre deux cycles et rétention des sociétés",
        "description": "Même chiffre signé EUR que l'accueil, sous le périmètre du jeton. ownerId filtre le chiffre signé ; la rétention suit le portefeuille N-1, renouvellements visibles des collègues compris. missing signifie absence de signé, pas nécessairement absence de devis. Les ventes aux contacts sont isolées dans contacts et incluses dans les totaux. Sans cycle précédent, previous et delta valent null.",
        "tags": [
          "Ventes"
        ],
        "parameters": [
          {
            "name": "cycleId",
            "in": "query",
            "required": true,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "businessUnitId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "ownerId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "quotes:read",
              "companies:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Pont commercial",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "revenueBridge": {
                      "type": "object",
                      "properties": {
                        "currency": {
                          "type": "string",
                          "const": "EUR"
                        },
                        "asOf": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        "provisional": {
                          "type": "boolean"
                        },
                        "cycle": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "label": {
                              "type": "string"
                            },
                            "endsOn": {
                              "type": "string",
                              "format": "date",
                              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                            }
                          },
                          "required": [
                            "id",
                            "label",
                            "endsOn"
                          ],
                          "additionalProperties": false
                        },
                        "previousCycle": {
                          "anyOf": [
                            {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                },
                                "label": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "id",
                                "label"
                              ],
                              "additionalProperties": false
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "previous": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "Montant HT en euros, deux décimales"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "current": {
                          "type": "string",
                          "description": "Montant HT en euros, deux décimales"
                        },
                        "delta": {
                          "anyOf": [
                            {
                              "type": "string",
                              "description": "Montant HT en euros, deux décimales"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "classes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "new",
                                  "expanded",
                                  "maintained",
                                  "reduced",
                                  "missing"
                                ]
                              },
                              "companies": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "previous": {
                                "type": "string",
                                "description": "Montant HT en euros, deux décimales"
                              },
                              "current": {
                                "type": "string",
                                "description": "Montant HT en euros, deux décimales"
                              },
                              "delta": {
                                "type": "string",
                                "description": "Montant HT en euros, deux décimales"
                              }
                            },
                            "required": [
                              "kind",
                              "companies",
                              "previous",
                              "current",
                              "delta"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "contacts": {
                          "type": "object",
                          "properties": {
                            "previous": {
                              "type": "string",
                              "description": "Montant HT en euros, deux décimales"
                            },
                            "current": {
                              "type": "string",
                              "description": "Montant HT en euros, deux décimales"
                            },
                            "delta": {
                              "type": "string",
                              "description": "Montant HT en euros, deux décimales"
                            }
                          },
                          "required": [
                            "previous",
                            "current",
                            "delta"
                          ],
                          "additionalProperties": false
                        },
                        "retention": {
                          "type": "object",
                          "properties": {
                            "previousCompanies": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "retainedCompanies": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "previous": {
                              "type": "string",
                              "description": "Montant HT en euros, deux décimales"
                            },
                            "retained": {
                              "type": "string",
                              "description": "Montant HT en euros, deux décimales"
                            },
                            "companiesPct": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "revenuePct": {
                              "type": [
                                "number",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "previousCompanies",
                            "retainedCompanies",
                            "previous",
                            "retained",
                            "companiesPct",
                            "revenuePct"
                          ],
                          "additionalProperties": false
                        },
                        "companies": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "companyId": {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              "name": {
                                "type": "string"
                              },
                              "logo": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "visible": {
                                "type": "boolean"
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "new",
                                  "expanded",
                                  "maintained",
                                  "reduced",
                                  "missing"
                                ]
                              },
                              "previous": {
                                "type": "string",
                                "description": "Montant HT en euros, deux décimales"
                              },
                              "current": {
                                "type": "string",
                                "description": "Montant HT en euros, deux décimales"
                              },
                              "delta": {
                                "type": "string",
                                "description": "Montant HT en euros, deux décimales"
                              },
                              "coverage": {
                                "type": "object",
                                "properties": {
                                  "hasQuote": {
                                    "type": "boolean"
                                  },
                                  "hasNonDraft": {
                                    "type": "boolean"
                                  },
                                  "draftQuoteId": {
                                    "anyOf": [
                                      {
                                        "type": "string",
                                        "format": "uuid",
                                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  }
                                },
                                "required": [
                                  "hasQuote",
                                  "hasNonDraft",
                                  "draftQuoteId"
                                ],
                                "additionalProperties": false
                              },
                              "reason": {
                                "anyOf": [
                                  {
                                    "type": "object",
                                    "properties": {
                                      "source": {
                                        "type": "string",
                                        "enum": [
                                          "quote",
                                          "contract"
                                        ]
                                      },
                                      "id": {
                                        "type": "string",
                                        "format": "uuid",
                                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                      },
                                      "date": {
                                        "type": "string"
                                      },
                                      "reason": {
                                        "type": "string"
                                      },
                                      "comment": {
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      }
                                    },
                                    "required": [
                                      "source",
                                      "id",
                                      "date",
                                      "reason",
                                      "comment"
                                    ],
                                    "additionalProperties": false
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              }
                            },
                            "required": [
                              "companyId",
                              "name",
                              "logo",
                              "visible",
                              "kind",
                              "previous",
                              "current",
                              "delta",
                              "coverage",
                              "reason"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "currency",
                        "asOf",
                        "provisional",
                        "cycle",
                        "previousCycle",
                        "previous",
                        "current",
                        "delta",
                        "classes",
                        "contacts",
                        "retention",
                        "companies"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "revenueBridge"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/invoices": {
      "get": {
        "summary": "Lister les factures (hors corbeille)",
        "tags": [
          "Factures"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Jours (1 à 365) - objets dans leur statut courant depuis plus de N jours (status_changed_at), combinable avec status (T-1407)",
              "type": "integer",
              "minimum": 1,
              "maximum": 365
            }
          },
          {
            "name": "ids",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Répétable - restriction à une liste d'ids (max 200)",
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "draft",
                "issued",
                "paid",
                "late",
                "credit"
              ]
            }
          },
          {
            "name": "companyId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          },
          {
            "name": "cycleId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          },
          {
            "name": "businessUnitId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          },
          {
            "name": "externalId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Objets qui portent cet identifiant externe (exact) - avec `externalSource` pour une source précise",
              "type": "string"
            }
          },
          {
            "name": "externalSource",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Source de l'identifiant externe (`tacto`…)",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "invoices:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de factures",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "number": {
                            "description": "Numéro légal, pris à l'émission (#996, ADR-215 D4 b) - null en brouillon ; un brouillon antérieur garde le sien",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "quoteId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "targetType": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact"
                            ]
                          },
                          "targetId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "businessUnitId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "amountInclTax": {
                            "type": "string",
                            "description": "TTC, chaîne décimale - négatif pour un avoir"
                          },
                          "currency": {
                            "type": "string",
                            "minLength": 3,
                            "maxLength": 3,
                            "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                          },
                          "fxRate": {
                            "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "fxRateDate": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Jour de publication du taux figé - null en euros"
                          },
                          "amountEur": {
                            "type": "string",
                            "description": "Contre-valeur en euros au taux figé"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "issued",
                              "paid",
                              "late",
                              "credit"
                            ],
                            "description": "late est dérivé : émise à échéance dépassée (même règle que les listes UI)"
                          },
                          "issuedOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "dueOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Échéance : conditions de paiement appliquées à la date d'émission (#998)"
                          },
                          "paymentCondition": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "days",
                                      "days_end_of_month",
                                      "end_of_month_then_day"
                                    ]
                                  },
                                  "days": {
                                    "type": "integer",
                                    "minimum": 0,
                                    "maximum": 365
                                  },
                                  "dayOfNextMonth": {
                                    "anyOf": [
                                      {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 31
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  }
                                },
                                "required": [
                                  "type",
                                  "days",
                                  "dayOfNextMonth"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#998 : condition de paiement { type, days, dayOfNextMonth } ; null sur un avoir et une facture antérieure"
                          },
                          "paidOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "creditOfInvoiceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "vatRegime": {
                            "type": "string",
                            "enum": [
                              "domestic",
                              "reverse_charge"
                            ],
                            "description": "T-1402 : reverse_charge = autoliquidation (client assujetti d'un autre État membre, TVA à 0, amountInclTax = HT)"
                          },
                          "exportedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "statusChangedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                            "description": "Entrée dans le statut courant (T-1407)"
                          },
                          "externalRefs": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "source": {
                                  "type": "string",
                                  "description": "Système source (minuscules) - `tacto`, `erp`…"
                                },
                                "externalId": {
                                  "type": "string"
                                },
                                "sourceUpdatedAt": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "date-time",
                                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ],
                                  "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                                }
                              },
                              "required": [
                                "source",
                                "externalId",
                                "sourceUpdatedAt"
                              ],
                              "additionalProperties": false
                            },
                            "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                          }
                        },
                        "required": [
                          "id",
                          "number",
                          "quoteId",
                          "targetType",
                          "targetId",
                          "businessUnitId",
                          "cycleId",
                          "amountInclTax",
                          "currency",
                          "fxRate",
                          "fxRateDate",
                          "amountEur",
                          "status",
                          "issuedOn",
                          "dueOn",
                          "paymentCondition",
                          "paidOn",
                          "creditOfInvoiceId",
                          "vatRegime",
                          "exportedAt",
                          "updatedAt",
                          "statusChangedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{id}": {
      "get": {
        "summary": "Détail d'une facture",
        "tags": [
          "Factures"
        ],
        "security": [
          {
            "oauth2": [
              "invoices:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Facture",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "number": {
                      "description": "Numéro légal, pris à l'émission (#996, ADR-215 D4 b) - null en brouillon ; un brouillon antérieur garde le sien",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "targetType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "contact"
                      ]
                    },
                    "targetId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "businessUnitId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "cycleId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "amountInclTax": {
                      "type": "string",
                      "description": "TTC, chaîne décimale - négatif pour un avoir"
                    },
                    "currency": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 3,
                      "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                    },
                    "fxRate": {
                      "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "fxRateDate": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Jour de publication du taux figé - null en euros"
                    },
                    "amountEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros au taux figé"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "issued",
                        "paid",
                        "late",
                        "credit"
                      ],
                      "description": "late est dérivé : émise à échéance dépassée (même règle que les listes UI)"
                    },
                    "issuedOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "dueOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Échéance : conditions de paiement appliquées à la date d'émission (#998)"
                    },
                    "paymentCondition": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "days",
                                "days_end_of_month",
                                "end_of_month_then_day"
                              ]
                            },
                            "days": {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 365
                            },
                            "dayOfNextMonth": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": 1,
                                  "maximum": 31
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "type",
                            "days",
                            "dayOfNextMonth"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#998 : condition de paiement { type, days, dayOfNextMonth } ; null sur un avoir et une facture antérieure"
                    },
                    "paidOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "creditOfInvoiceId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "vatRegime": {
                      "type": "string",
                      "enum": [
                        "domestic",
                        "reverse_charge"
                      ],
                      "description": "T-1402 : reverse_charge = autoliquidation (client assujetti d'un autre État membre, TVA à 0, amountInclTax = HT)"
                    },
                    "exportedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    }
                  },
                  "required": [
                    "id",
                    "number",
                    "quoteId",
                    "targetType",
                    "targetId",
                    "businessUnitId",
                    "cycleId",
                    "amountInclTax",
                    "currency",
                    "fxRate",
                    "fxRateDate",
                    "amountEur",
                    "status",
                    "issuedOn",
                    "dueOn",
                    "paymentCondition",
                    "paidOn",
                    "creditOfInvoiceId",
                    "vatRegime",
                    "exportedAt",
                    "updatedAt",
                    "statusChangedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{id}/payments": {
      "post": {
        "summary": "Marquer payée (échéances soldées, notification - règles UI)",
        "description": "Permis depuis issued ou late uniquement (422 sinon). Solde les échéances liées, trace l'activité et notifie le commercial comme le geste UI.",
        "tags": [
          "Factures"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "paidOn": {
                    "type": "string",
                    "format": "date",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
                    "description": "Date de paiement (YYYY-MM-DD)"
                  },
                  "method": {
                    "description": "Moyen de règlement (défaut : transfer)",
                    "type": "string",
                    "enum": [
                      "transfer",
                      "card",
                      "other"
                    ]
                  },
                  "reference": {
                    "description": "Référence du règlement (libellé de virement, identifiant de transaction)",
                    "type": "string",
                    "maxLength": 140
                  }
                },
                "required": [
                  "paidOn"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "invoices:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Facture payée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "number": {
                      "description": "Numéro légal, pris à l'émission (#996, ADR-215 D4 b) - null en brouillon ; un brouillon antérieur garde le sien",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "targetType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "contact"
                      ]
                    },
                    "targetId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "businessUnitId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "cycleId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "amountInclTax": {
                      "type": "string",
                      "description": "TTC, chaîne décimale - négatif pour un avoir"
                    },
                    "currency": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 3,
                      "description": "Devise du document, ISO 4217 (T-1404, ADR-184) - EUR par défaut"
                    },
                    "fxRate": {
                      "description": "Taux BCE figé, « 1 EUR = fxRate devise » - null en euros",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "fxRateDate": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Jour de publication du taux figé - null en euros"
                    },
                    "amountEur": {
                      "type": "string",
                      "description": "Contre-valeur en euros au taux figé"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "issued",
                        "paid",
                        "late",
                        "credit"
                      ],
                      "description": "late est dérivé : émise à échéance dépassée (même règle que les listes UI)"
                    },
                    "issuedOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "dueOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Échéance : conditions de paiement appliquées à la date d'émission (#998)"
                    },
                    "paymentCondition": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "days",
                                "days_end_of_month",
                                "end_of_month_then_day"
                              ]
                            },
                            "days": {
                              "type": "integer",
                              "minimum": 0,
                              "maximum": 365
                            },
                            "dayOfNextMonth": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": 1,
                                  "maximum": 31
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "type",
                            "days",
                            "dayOfNextMonth"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#998 : condition de paiement { type, days, dayOfNextMonth } ; null sur un avoir et une facture antérieure"
                    },
                    "paidOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "creditOfInvoiceId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "vatRegime": {
                      "type": "string",
                      "enum": [
                        "domestic",
                        "reverse_charge"
                      ],
                      "description": "T-1402 : reverse_charge = autoliquidation (client assujetti d'un autre État membre, TVA à 0, amountInclTax = HT)"
                    },
                    "exportedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    }
                  },
                  "required": [
                    "id",
                    "number",
                    "quoteId",
                    "targetType",
                    "targetId",
                    "businessUnitId",
                    "cycleId",
                    "amountInclTax",
                    "currency",
                    "fxRate",
                    "fxRateDate",
                    "amountEur",
                    "status",
                    "issuedOn",
                    "dueOn",
                    "paymentCondition",
                    "paidOn",
                    "creditOfInvoiceId",
                    "vatRegime",
                    "exportedAt",
                    "updatedAt",
                    "statusChangedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{id}/pdf": {
      "get": {
        "summary": "PDF de la facture (si PDF_RENDERER=chromium est actif - 404 sinon)",
        "tags": [
          "Factures"
        ],
        "security": [
          {
            "oauth2": [
              "invoices:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Document PDF (application/pdf, attachment)"
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{id}/facturx": {
      "get": {
        "summary": "Factur-X de la facture (PDF/A-3 avec factur-x.xml EN 16931), archivé - généré à la demande s'il n'existe pas",
        "tags": [
          "Factures"
        ],
        "security": [
          {
            "oauth2": [
              "invoices:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Factur-X (application/pdf, attachment, en-tête X-Cercla-Sha256)"
          },
          "404": {
            "description": "Facture introuvable, ou module facturation électronique inactif (einvoice-unavailable)"
          },
          "409": {
            "description": "Facture inéligible (einvoice-ineligible : brouillon, client sans SIRET, totaux)"
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{id}/einvoicing": {
      "get": {
        "summary": "Transmissions de la facture électronique et statuts de cycle de vie DGFiP",
        "tags": [
          "Factures"
        ],
        "security": [
          {
            "oauth2": [
              "invoices:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Transmissions (plus récente d'abord) avec événements",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "transmissions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "invoiceId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "invoiceNumber": {
                            "type": "string"
                          },
                          "provider": {
                            "type": "string",
                            "description": "mock, qonto, sage, afnor, file, external ou nom donné par le tiers"
                          },
                          "providerRef": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "state": {
                            "type": "string",
                            "enum": [
                              "queued",
                              "submitted",
                              "failed",
                              "done"
                            ]
                          },
                          "lastCode": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "lastCodeLabel": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "lastError": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "documentFileId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "events": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                },
                                "transmissionId": {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                },
                                "invoiceId": {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                },
                                "invoiceNumber": {
                                  "type": "string"
                                },
                                "provider": {
                                  "type": "string"
                                },
                                "providerRef": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "code": {
                                  "anyOf": [
                                    {
                                      "type": "integer",
                                      "minimum": -9007199254740991,
                                      "maximum": 9007199254740991
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "label": {
                                  "type": "string"
                                },
                                "source": {
                                  "type": "string",
                                  "enum": [
                                    "provider",
                                    "api",
                                    "manual",
                                    "system"
                                  ]
                                },
                                "reason": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "occurredAt": {
                                  "type": "string",
                                  "format": "date-time",
                                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                }
                              },
                              "required": [
                                "id",
                                "transmissionId",
                                "invoiceId",
                                "invoiceNumber",
                                "provider",
                                "providerRef",
                                "code",
                                "label",
                                "source",
                                "reason",
                                "occurredAt"
                              ],
                              "additionalProperties": false
                            }
                          }
                        },
                        "required": [
                          "id",
                          "invoiceId",
                          "invoiceNumber",
                          "provider",
                          "providerRef",
                          "state",
                          "lastCode",
                          "lastCodeLabel",
                          "lastError",
                          "documentFileId",
                          "createdAt",
                          "updatedAt",
                          "events"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "transmissions"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{id}/einvoicing/transmissions": {
      "post": {
        "summary": "Déclarer un dépôt du Factur-X fait par un tiers (plateforme sans adaptateur)",
        "description": "Crée une transmission déposée (événement 200 daté du dépôt), ou rend le dépôt existant pour la même facture, le même fournisseur et la même référence. Après désactivation, conserve seulement la preuve, sans effets secondaires. L'empreinte `documentSha256`, si fournie, doit être celle de l'archive Cercla (409 sinon).",
        "tags": [
          "Factures"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "providerRef": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500,
                    "description": "Identifiant du dépôt chez la plateforme"
                  },
                  "provider": {
                    "description": "Nom de la plateforme (défaut : external)",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "depositedAt": {
                    "description": "Date du dépôt (défaut : maintenant)",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                      },
                      {
                        "type": "string",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z))$"
                      }
                    ]
                  },
                  "documentSha256": {
                    "description": "Empreinte du fichier déposé - vérifiée contre l'archive Cercla (409 sinon)",
                    "type": "string",
                    "pattern": "^[0-9a-f]{64}$"
                  },
                  "payload": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "required": [
                  "providerRef"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "invoices:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Dépôt déjà enregistré",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "invoiceId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "invoiceNumber": {
                      "type": "string"
                    },
                    "provider": {
                      "type": "string",
                      "description": "mock, qonto, sage, afnor, file, external ou nom donné par le tiers"
                    },
                    "providerRef": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "state": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "submitted",
                        "failed",
                        "done"
                      ]
                    },
                    "lastCode": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "lastCodeLabel": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "lastError": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "documentFileId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "invoiceId",
                    "invoiceNumber",
                    "provider",
                    "providerRef",
                    "state",
                    "lastCode",
                    "lastCodeLabel",
                    "lastError",
                    "documentFileId",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "201": {
            "description": "Transmission déposée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "invoiceId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "invoiceNumber": {
                      "type": "string"
                    },
                    "provider": {
                      "type": "string",
                      "description": "mock, qonto, sage, afnor, file, external ou nom donné par le tiers"
                    },
                    "providerRef": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "state": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "submitted",
                        "failed",
                        "done"
                      ]
                    },
                    "lastCode": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "lastCodeLabel": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "lastError": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "documentFileId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "invoiceId",
                    "invoiceNumber",
                    "provider",
                    "providerRef",
                    "state",
                    "lastCode",
                    "lastCodeLabel",
                    "lastError",
                    "documentFileId",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{id}/einvoicing/events": {
      "post": {
        "summary": "Pousser un statut de cycle de vie DGFiP (200 à 213) sur la dernière transmission déposée",
        "description": "Idempotent par (transmission, code, date) : 200 sans corps si l'événement existait. 210 et 213 notifient les administrateurs si les applications et générations restent actives ; après arrêt, seule la preuve est conservée sans reprise automatique. Aucun statut ne change l'état métier de la facture.",
        "tags": [
          "Factures"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "code": {
                    "type": "integer",
                    "minimum": 200,
                    "maximum": 213,
                    "description": "Code de cycle de vie DGFiP (spécifications externes 3.1) : 200 déposée … 213 rejetée"
                  },
                  "occurredAt": {
                    "description": "Date du statut chez la plateforme (défaut : maintenant)",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                      },
                      {
                        "type": "string",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z))$"
                      }
                    ]
                  },
                  "reason": {
                    "description": "Motif de refus ou de rejet (REJ_*)",
                    "type": "string",
                    "maxLength": 2000
                  },
                  "transmissionId": {
                    "description": "Cible explicite - défaut : dernière transmission déposée",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "payload": {
                    "description": "Charge utile brute, diagnostic seulement",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "required": [
                  "code"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "invoices:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Événement enregistré",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "transmissionId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "invoiceId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "invoiceNumber": {
                      "type": "string"
                    },
                    "provider": {
                      "type": "string"
                    },
                    "providerRef": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "code": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "label": {
                      "type": "string"
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "provider",
                        "api",
                        "manual",
                        "system"
                      ]
                    },
                    "reason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "occurredAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "transmissionId",
                    "invoiceId",
                    "invoiceNumber",
                    "provider",
                    "providerRef",
                    "code",
                    "label",
                    "source",
                    "reason",
                    "occurredAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/companies/{id}/external-refs/{source}": {
      "put": {
        "summary": "Poser l'identifiant d'une source sur une société (idempotent)",
        "description": "Une source, un identifiant par objet : la même écriture deux fois ne crée qu'une ligne ; un identifiant déjà porté par un AUTRE objet de la même source répond 409 avec l'objet porteur (jamais déplacé en silence). La source `salesforce` est réservée aux scripts de reprise (403). Même garde que le PATCH de l'objet : hors visibilité 404, hors périmètre d'écriture 403.",
        "tags": [
          "Sociétés"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "externalId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "sourceUpdatedAt": {
                    "description": "Dernière modification dans la source - curseur du delta",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      },
                      {
                        "type": "string",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      }
                    ]
                  }
                },
                "required": [
                  "externalId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "companies:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Identifiants de l'objet après écriture",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "Objet porteur"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    }
                  },
                  "required": [
                    "id",
                    "externalRefs"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Retirer l'identifiant d'une source sur une société",
        "tags": [
          "Sociétés"
        ],
        "security": [
          {
            "oauth2": [
              "companies:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Identifiants restants",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "Objet porteur"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "removed": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Références retirées (0 si la source n'en portait pas)"
                    }
                  },
                  "required": [
                    "id",
                    "externalRefs",
                    "removed"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/contacts/{id}/external-refs/{source}": {
      "put": {
        "summary": "Poser l'identifiant d'une source sur un contact (idempotent)",
        "description": "Une source, un identifiant par objet : la même écriture deux fois ne crée qu'une ligne ; un identifiant déjà porté par un AUTRE objet de la même source répond 409 avec l'objet porteur (jamais déplacé en silence). La source `salesforce` est réservée aux scripts de reprise (403). Même garde que le PATCH de l'objet : hors visibilité 404, hors périmètre d'écriture 403.",
        "tags": [
          "Contacts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "externalId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "sourceUpdatedAt": {
                    "description": "Dernière modification dans la source - curseur du delta",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      },
                      {
                        "type": "string",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      }
                    ]
                  }
                },
                "required": [
                  "externalId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "contacts:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Identifiants de l'objet après écriture",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "Objet porteur"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    }
                  },
                  "required": [
                    "id",
                    "externalRefs"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Retirer l'identifiant d'une source sur un contact",
        "tags": [
          "Contacts"
        ],
        "security": [
          {
            "oauth2": [
              "contacts:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Identifiants restants",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "Objet porteur"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "removed": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Références retirées (0 si la source n'en portait pas)"
                    }
                  },
                  "required": [
                    "id",
                    "externalRefs",
                    "removed"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/quotes/{id}/external-refs/{source}": {
      "put": {
        "summary": "Poser l'identifiant d'une source sur un devis (idempotent)",
        "description": "Une source, un identifiant par objet : la même écriture deux fois ne crée qu'une ligne ; un identifiant déjà porté par un AUTRE objet de la même source répond 409 avec l'objet porteur (jamais déplacé en silence). La source `salesforce` est réservée aux scripts de reprise (403). Même garde que le PATCH de l'objet : hors visibilité 404, hors périmètre d'écriture 403.",
        "tags": [
          "Devis"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "externalId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "sourceUpdatedAt": {
                    "description": "Dernière modification dans la source - curseur du delta",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      },
                      {
                        "type": "string",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      }
                    ]
                  }
                },
                "required": [
                  "externalId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Identifiants de l'objet après écriture",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "Objet porteur"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    }
                  },
                  "required": [
                    "id",
                    "externalRefs"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Retirer l'identifiant d'une source sur un devis",
        "tags": [
          "Devis"
        ],
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Identifiants restants",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "Objet porteur"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "removed": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Références retirées (0 si la source n'en portait pas)"
                    }
                  },
                  "required": [
                    "id",
                    "externalRefs",
                    "removed"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/invoices/{id}/external-refs/{source}": {
      "put": {
        "summary": "Poser l'identifiant d'une source sur un facture (idempotent)",
        "description": "Une source, un identifiant par objet : la même écriture deux fois ne crée qu'une ligne ; un identifiant déjà porté par un AUTRE objet de la même source répond 409 avec l'objet porteur (jamais déplacé en silence). La source `salesforce` est réservée aux scripts de reprise (403). Même garde que le PATCH de l'objet : hors visibilité 404, hors périmètre d'écriture 403.",
        "tags": [
          "Factures"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "externalId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "sourceUpdatedAt": {
                    "description": "Dernière modification dans la source - curseur du delta",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      },
                      {
                        "type": "string",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      }
                    ]
                  }
                },
                "required": [
                  "externalId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "invoices:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Identifiants de l'objet après écriture",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "Objet porteur"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    }
                  },
                  "required": [
                    "id",
                    "externalRefs"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Retirer l'identifiant d'une source sur un facture",
        "tags": [
          "Factures"
        ],
        "security": [
          {
            "oauth2": [
              "invoices:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Identifiants restants",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "Objet porteur"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "removed": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Références retirées (0 si la source n'en portait pas)"
                    }
                  },
                  "required": [
                    "id",
                    "externalRefs",
                    "removed"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/contracts/{id}/external-refs/{source}": {
      "put": {
        "summary": "Poser l'identifiant d'une source sur un contrat (idempotent)",
        "description": "Une source, un identifiant par objet : la même écriture deux fois ne crée qu'une ligne ; un identifiant déjà porté par un AUTRE objet de la même source répond 409 avec l'objet porteur (jamais déplacé en silence). La source `salesforce` est réservée aux scripts de reprise (403). Même garde que le PATCH de l'objet : hors visibilité 404, hors périmètre d'écriture 403.",
        "tags": [
          "Contrats"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "externalId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "sourceUpdatedAt": {
                    "description": "Dernière modification dans la source - curseur du delta",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      },
                      {
                        "type": "string",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      }
                    ]
                  }
                },
                "required": [
                  "externalId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Identifiants de l'objet après écriture",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "Objet porteur"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    }
                  },
                  "required": [
                    "id",
                    "externalRefs"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Retirer l'identifiant d'une source sur un contrat",
        "tags": [
          "Contrats"
        ],
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Identifiants restants",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "Objet porteur"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    },
                    "removed": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Références retirées (0 si la source n'en portait pas)"
                    }
                  },
                  "required": [
                    "id",
                    "externalRefs",
                    "removed"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/contracts": {
      "get": {
        "summary": "Lister les contrats (hors corbeille) - qui est en contrat où",
        "description": "Un contrat naît d'un devis signé (ADR-156) ; il n'y a pas de POST. Périmètre : celui des devis porteurs. `endsBefore` sert aux échéances à venir (renouvellements).",
        "tags": [
          "Contrats"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Jours (1 à 365) - objets dans leur statut courant depuis plus de N jours (status_changed_at), combinable avec status (T-1407)",
              "type": "integer",
              "minimum": 1,
              "maximum": 365
            }
          },
          {
            "name": "ids",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Répétable - restriction à une liste d'ids (max 200)",
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "active",
                "amended",
                "terminated",
                "expired"
              ]
            }
          },
          {
            "name": "companyId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Contrats dont la cible est cette société",
              "type": "string"
            }
          },
          {
            "name": "contactId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Contrats dont la cible est ce contact (B2C)",
              "type": "string"
            }
          },
          {
            "name": "endsBefore",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO date - contrats dont la fin est avant (inclus)",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "quotes:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de contrats",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "number": {
                            "type": "string",
                            "description": "Série CT-{YYYY}-{seq}, suffixe -v{n} sur un avenant"
                          },
                          "quoteId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                            "description": "Le devis signé qui a fait naître cette version"
                          },
                          "targetType": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact"
                            ]
                          },
                          "targetId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "signatoryContactId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "ownerId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "subject": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "startsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
                            "description": "Dérivée du premier cycle vendu"
                          },
                          "endsOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
                            "description": "Dérivée du dernier cycle vendu"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "amended",
                              "terminated",
                              "expired"
                            ]
                          },
                          "currency": {
                            "type": "string",
                            "enum": [
                              "EUR",
                              "USD",
                              "GBP",
                              "CHF"
                            ]
                          },
                          "fxRate": {
                            "description": "Taux figé du devis porteur : 1 EUR = taux devise",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "fxRateDate": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "totalExclTaxEur": {
                            "type": "number"
                          },
                          "totalInclTaxEur": {
                            "type": "number"
                          },
                          "totalExclTax": {
                            "type": "number"
                          },
                          "totalInclTax": {
                            "type": "number"
                          },
                          "version": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "parentContractId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "La version précédente quand c'est un avenant"
                          },
                          "renewal": {
                            "type": "string",
                            "enum": [
                              "none",
                              "tacit",
                              "proposed"
                            ]
                          },
                          "renewalNoticeDays": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "terminatedOn": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "terminationReason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "statusChangedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                            "description": "Entrée dans le statut courant (T-1407)"
                          }
                        },
                        "required": [
                          "id",
                          "number",
                          "quoteId",
                          "targetType",
                          "targetId",
                          "signatoryContactId",
                          "ownerId",
                          "subject",
                          "startsOn",
                          "endsOn",
                          "status",
                          "currency",
                          "fxRate",
                          "fxRateDate",
                          "totalExclTaxEur",
                          "totalInclTaxEur",
                          "totalExclTax",
                          "totalInclTax",
                          "version",
                          "parentContractId",
                          "renewal",
                          "renewalNoticeDays",
                          "terminatedOn",
                          "terminationReason",
                          "createdAt",
                          "updatedAt",
                          "statusChangedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/contracts/{id}": {
      "get": {
        "summary": "Détail d'un contrat - échéancier, facturé, payé, identifiants externes",
        "tags": [
          "Contrats"
        ],
        "security": [
          {
            "oauth2": [
              "quotes:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Contrat",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "number": {
                      "type": "string",
                      "description": "Série CT-{YYYY}-{seq}, suffixe -v{n} sur un avenant"
                    },
                    "quoteId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "Le devis signé qui a fait naître cette version"
                    },
                    "targetType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "contact"
                      ]
                    },
                    "targetId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "signatoryContactId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "ownerId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "subject": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "startsOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
                      "description": "Dérivée du premier cycle vendu"
                    },
                    "endsOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
                      "description": "Dérivée du dernier cycle vendu"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "amended",
                        "terminated",
                        "expired"
                      ]
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "EUR",
                        "USD",
                        "GBP",
                        "CHF"
                      ]
                    },
                    "fxRate": {
                      "description": "Taux figé du devis porteur : 1 EUR = taux devise",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "fxRateDate": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "totalExclTaxEur": {
                      "type": "number"
                    },
                    "totalInclTaxEur": {
                      "type": "number"
                    },
                    "totalExclTax": {
                      "type": "number"
                    },
                    "totalInclTax": {
                      "type": "number"
                    },
                    "version": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "parentContractId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "La version précédente quand c'est un avenant"
                    },
                    "renewal": {
                      "type": "string",
                      "enum": [
                        "none",
                        "tacit",
                        "proposed"
                      ]
                    },
                    "renewalNoticeDays": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "terminatedOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "terminationReason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "installments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "installmentId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleLabel": {
                            "type": "string"
                          },
                          "dueOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "amountInclTax": {
                            "type": "number"
                          },
                          "amountInclTaxEur": {
                            "type": "number"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "to_invoice",
                              "invoiced",
                              "paid",
                              "late",
                              "cancelled"
                            ]
                          },
                          "invoiceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "installmentId",
                          "cycleId",
                          "cycleLabel",
                          "dueOn",
                          "amountInclTax",
                          "amountInclTaxEur",
                          "status",
                          "invoiceId"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Échéancier du devis porteur (une échéance par cycle)"
                    },
                    "invoicedEur": {
                      "type": "number",
                      "description": "Facturé TTC converti au taux figé de chaque facture"
                    },
                    "paidEur": {
                      "type": "number"
                    },
                    "creditedEur": {
                      "type": "number"
                    },
                    "invoiced": {
                      "type": "number",
                      "description": "Somme TTC des factures émises (émises, payées, en retard) - calculée"
                    },
                    "paid": {
                      "type": "number",
                      "description": "Somme TTC des factures réglées - calculée"
                    },
                    "credited": {
                      "type": "number",
                      "description": "Somme TTC des avoirs rattachés au devis - calculée"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    }
                  },
                  "required": [
                    "id",
                    "number",
                    "quoteId",
                    "targetType",
                    "targetId",
                    "signatoryContactId",
                    "ownerId",
                    "subject",
                    "startsOn",
                    "endsOn",
                    "status",
                    "currency",
                    "fxRate",
                    "fxRateDate",
                    "totalExclTaxEur",
                    "totalInclTaxEur",
                    "totalExclTax",
                    "totalInclTax",
                    "version",
                    "parentContractId",
                    "renewal",
                    "renewalNoticeDays",
                    "terminatedOn",
                    "terminationReason",
                    "createdAt",
                    "updatedAt",
                    "statusChangedAt",
                    "installments",
                    "invoicedEur",
                    "paidEur",
                    "creditedEur",
                    "invoiced",
                    "paid",
                    "credited",
                    "externalRefs"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/contracts/{id}/terminate": {
      "post": {
        "summary": "Résilier un contrat actif - geste irréversible, motif obligatoire",
        "description": "Statut `terminated`, date et motif posés, échéances futures non facturées annulées, webhook `contract.terminated` émis une fois. Un contrat qui n'est plus actif répond 409 ; un motif hors liste ou une date avant le début du contrat répondent 422.",
        "tags": [
          "Contrats"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "on": {
                    "description": "Date de résiliation - défaut : aujourd'hui (jour local)",
                    "type": "string",
                    "format": "date",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                  },
                  "reason": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  }
                },
                "required": [
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Contrat résilié",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "number": {
                      "type": "string",
                      "description": "Série CT-{YYYY}-{seq}, suffixe -v{n} sur un avenant"
                    },
                    "quoteId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                      "description": "Le devis signé qui a fait naître cette version"
                    },
                    "targetType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "contact"
                      ]
                    },
                    "targetId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "signatoryContactId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "ownerId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "subject": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "startsOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
                      "description": "Dérivée du premier cycle vendu"
                    },
                    "endsOn": {
                      "type": "string",
                      "format": "date",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
                      "description": "Dérivée du dernier cycle vendu"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "amended",
                        "terminated",
                        "expired"
                      ]
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "EUR",
                        "USD",
                        "GBP",
                        "CHF"
                      ]
                    },
                    "fxRate": {
                      "description": "Taux figé du devis porteur : 1 EUR = taux devise",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "fxRateDate": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "totalExclTaxEur": {
                      "type": "number"
                    },
                    "totalInclTaxEur": {
                      "type": "number"
                    },
                    "totalExclTax": {
                      "type": "number"
                    },
                    "totalInclTax": {
                      "type": "number"
                    },
                    "version": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "parentContractId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "La version précédente quand c'est un avenant"
                    },
                    "renewal": {
                      "type": "string",
                      "enum": [
                        "none",
                        "tacit",
                        "proposed"
                      ]
                    },
                    "renewalNoticeDays": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "terminatedOn": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "terminationReason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "statusChangedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$",
                      "description": "Entrée dans le statut courant (T-1407)"
                    },
                    "installments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "installmentId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "cycleLabel": {
                            "type": "string"
                          },
                          "dueOn": {
                            "type": "string",
                            "format": "date",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                          },
                          "amountInclTax": {
                            "type": "number"
                          },
                          "amountInclTaxEur": {
                            "type": "number"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "to_invoice",
                              "invoiced",
                              "paid",
                              "late",
                              "cancelled"
                            ]
                          },
                          "invoiceId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "installmentId",
                          "cycleId",
                          "cycleLabel",
                          "dueOn",
                          "amountInclTax",
                          "amountInclTaxEur",
                          "status",
                          "invoiceId"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Échéancier du devis porteur (une échéance par cycle)"
                    },
                    "invoicedEur": {
                      "type": "number",
                      "description": "Facturé TTC converti au taux figé de chaque facture"
                    },
                    "paidEur": {
                      "type": "number"
                    },
                    "creditedEur": {
                      "type": "number"
                    },
                    "invoiced": {
                      "type": "number",
                      "description": "Somme TTC des factures émises (émises, payées, en retard) - calculée"
                    },
                    "paid": {
                      "type": "number",
                      "description": "Somme TTC des factures réglées - calculée"
                    },
                    "credited": {
                      "type": "number",
                      "description": "Somme TTC des avoirs rattachés au devis - calculée"
                    },
                    "externalRefs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "source": {
                            "type": "string",
                            "description": "Système source (minuscules) - `tacto`, `erp`…"
                          },
                          "externalId": {
                            "type": "string"
                          },
                          "sourceUpdatedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                          }
                        },
                        "required": [
                          "source",
                          "externalId",
                          "sourceUpdatedAt"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                    }
                  },
                  "required": [
                    "id",
                    "number",
                    "quoteId",
                    "targetType",
                    "targetId",
                    "signatoryContactId",
                    "ownerId",
                    "subject",
                    "startsOn",
                    "endsOn",
                    "status",
                    "currency",
                    "fxRate",
                    "fxRateDate",
                    "totalExclTaxEur",
                    "totalInclTaxEur",
                    "totalExclTax",
                    "totalInclTax",
                    "version",
                    "parentContractId",
                    "renewal",
                    "renewalNoticeDays",
                    "terminatedOn",
                    "terminationReason",
                    "createdAt",
                    "updatedAt",
                    "statusChangedAt",
                    "installments",
                    "invoicedEur",
                    "paidEur",
                    "creditedEur",
                    "invoiced",
                    "paid",
                    "credited",
                    "externalRefs"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/contracts/{id}/renewal": {
      "post": {
        "summary": "Proposer le renouvellement d'un contrat (brouillon de devis sur les cycles suivants)",
        "description": "Même geste que la fiche (T-1413) : un seul brouillon par contrat, la seconde demande rend le même (`created: false`). `upliftPercent` revalorise le prix de chaque ligne (un prix négocié valide prime), entrée datée dans le fil du brouillon (#972). Hors fenêtre de préavis, sans cycle suivant ou contrat clos : 409.",
        "tags": [
          "Contrats"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "upliftPercent": {
                    "description": "Revalorisation appliquée au prix de chaque ligne (un prix négocié valide prime) ; absente : réglage de l'organisation ; 0 : aucune hausse",
                    "type": "number",
                    "minimum": 0,
                    "maximum": 50
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "quotes:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Brouillon créé ou déjà ouvert (`created`)",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "created": {
                      "type": "boolean",
                      "description": "false : le brouillon de renouvellement existait déjà, rendu tel quel"
                    },
                    "quote": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "number": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "number"
                      ],
                      "additionalProperties": false
                    },
                    "upliftPercent": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "created",
                    "quote",
                    "upliftPercent"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/webhook-subscriptions": {
      "get": {
        "summary": "Lister les abonnements webhooks (jamais le secret)",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "oauth2": [
              "webhooks:manage"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Tous les abonnements (liste complète, hors curseur)",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "url": {
                            "type": "string"
                          },
                          "events": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "company.created",
                                "company.updated",
                                "company.trashed",
                                "contact.created",
                                "contact.updated",
                                "contact.trashed",
                                "contact.anonymized",
                                "quote.created",
                                "quote.updated",
                                "quote.status_changed",
                                "quote.viewed",
                                "invoice.created",
                                "invoice.paid",
                                "invoice.late",
                                "invoice.issued",
                                "contract.created",
                                "contract.amended",
                                "contract.terminated",
                                "contract.expired",
                                "request.created",
                                "request.updated",
                                "request.status_changed",
                                "request.merged",
                                "request.due_soon",
                                "request.overdue",
                                "request.unassigned",
                                "sales_activity.created",
                                "sales_activity.completed",
                                "sales_activity.cancelled",
                                "invoice.einvoice.submitted",
                                "invoice.einvoice.status_changed",
                                "signature.viewed",
                                "signature.signed",
                                "signature.declined",
                                "signature.expired",
                                "signature.cancelled",
                                "signature.recipient.viewed",
                                "signature.recipient.signed",
                                "export.ready",
                                "campaign.sent",
                                "campaign.paused",
                                "contact.unsubscribed",
                                "contact.marketing_consent_changed",
                                "form.submitted",
                                "event.registered",
                                "event.attended",
                                "order.received",
                                "order.confirmed",
                                "order.delivered",
                                "order.cancelled",
                                "order.updated"
                              ]
                            }
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "disabled"
                            ]
                          },
                          "consecutiveFailures": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          }
                        },
                        "required": [
                          "id",
                          "url",
                          "events",
                          "status",
                          "consecutiveFailures",
                          "createdAt",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Créer un abonnement - le secret whsec_ n'est montré qu'ici",
        "description": "URL https obligatoire hors dev (garde SSRF, résolution DNS publique). Conservez `secret` immédiatement : il n'est jamais relisible ensuite.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "maxLength": 2000,
                    "format": "uri"
                  },
                  "events": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "company.created",
                        "company.updated",
                        "company.trashed",
                        "contact.created",
                        "contact.updated",
                        "contact.trashed",
                        "contact.anonymized",
                        "quote.created",
                        "quote.updated",
                        "quote.status_changed",
                        "quote.viewed",
                        "invoice.created",
                        "invoice.paid",
                        "invoice.late",
                        "invoice.issued",
                        "contract.created",
                        "contract.amended",
                        "contract.terminated",
                        "contract.expired",
                        "request.created",
                        "request.updated",
                        "request.status_changed",
                        "request.merged",
                        "request.due_soon",
                        "request.overdue",
                        "request.unassigned",
                        "sales_activity.created",
                        "sales_activity.completed",
                        "sales_activity.cancelled",
                        "invoice.einvoice.submitted",
                        "invoice.einvoice.status_changed",
                        "signature.viewed",
                        "signature.signed",
                        "signature.declined",
                        "signature.expired",
                        "signature.cancelled",
                        "signature.recipient.viewed",
                        "signature.recipient.signed",
                        "export.ready",
                        "campaign.sent",
                        "campaign.paused",
                        "contact.unsubscribed",
                        "contact.marketing_consent_changed",
                        "form.submitted",
                        "event.registered",
                        "event.attended",
                        "order.received",
                        "order.confirmed",
                        "order.delivered",
                        "order.cancelled",
                        "order.updated"
                      ]
                    }
                  }
                },
                "required": [
                  "url",
                  "events"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "webhooks:manage"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Abonnement créé, secret inclus",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "company.created",
                          "company.updated",
                          "company.trashed",
                          "contact.created",
                          "contact.updated",
                          "contact.trashed",
                          "contact.anonymized",
                          "quote.created",
                          "quote.updated",
                          "quote.status_changed",
                          "quote.viewed",
                          "invoice.created",
                          "invoice.paid",
                          "invoice.late",
                          "invoice.issued",
                          "contract.created",
                          "contract.amended",
                          "contract.terminated",
                          "contract.expired",
                          "request.created",
                          "request.updated",
                          "request.status_changed",
                          "request.merged",
                          "request.due_soon",
                          "request.overdue",
                          "request.unassigned",
                          "sales_activity.created",
                          "sales_activity.completed",
                          "sales_activity.cancelled",
                          "invoice.einvoice.submitted",
                          "invoice.einvoice.status_changed",
                          "signature.viewed",
                          "signature.signed",
                          "signature.declined",
                          "signature.expired",
                          "signature.cancelled",
                          "signature.recipient.viewed",
                          "signature.recipient.signed",
                          "export.ready",
                          "campaign.sent",
                          "campaign.paused",
                          "contact.unsubscribed",
                          "contact.marketing_consent_changed",
                          "form.submitted",
                          "event.registered",
                          "event.attended",
                          "order.received",
                          "order.confirmed",
                          "order.delivered",
                          "order.cancelled",
                          "order.updated"
                        ]
                      }
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "disabled"
                      ]
                    },
                    "consecutiveFailures": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "secret": {
                      "type": "string",
                      "description": "Secret de signature whsec_ - montré UNIQUEMENT dans cette réponse, jamais relisible"
                    }
                  },
                  "required": [
                    "id",
                    "url",
                    "events",
                    "status",
                    "consecutiveFailures",
                    "createdAt",
                    "updatedAt",
                    "secret"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/webhook-subscriptions/{id}": {
      "patch": {
        "summary": "Modifier un abonnement (url, événements, statut)",
        "description": "Repasser `status` à `active` réarme le compteur d'échecs consécutifs (même sémantique que la réactivation UI).",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "maxLength": 2000,
                    "format": "uri"
                  },
                  "events": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "company.created",
                        "company.updated",
                        "company.trashed",
                        "contact.created",
                        "contact.updated",
                        "contact.trashed",
                        "contact.anonymized",
                        "quote.created",
                        "quote.updated",
                        "quote.status_changed",
                        "quote.viewed",
                        "invoice.created",
                        "invoice.paid",
                        "invoice.late",
                        "invoice.issued",
                        "contract.created",
                        "contract.amended",
                        "contract.terminated",
                        "contract.expired",
                        "request.created",
                        "request.updated",
                        "request.status_changed",
                        "request.merged",
                        "request.due_soon",
                        "request.overdue",
                        "request.unassigned",
                        "sales_activity.created",
                        "sales_activity.completed",
                        "sales_activity.cancelled",
                        "invoice.einvoice.submitted",
                        "invoice.einvoice.status_changed",
                        "signature.viewed",
                        "signature.signed",
                        "signature.declined",
                        "signature.expired",
                        "signature.cancelled",
                        "signature.recipient.viewed",
                        "signature.recipient.signed",
                        "export.ready",
                        "campaign.sent",
                        "campaign.paused",
                        "contact.unsubscribed",
                        "contact.marketing_consent_changed",
                        "form.submitted",
                        "event.registered",
                        "event.attended",
                        "order.received",
                        "order.confirmed",
                        "order.delivered",
                        "order.cancelled",
                        "order.updated"
                      ]
                    }
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "disabled"
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "webhooks:manage"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Abonnement modifié",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "company.created",
                          "company.updated",
                          "company.trashed",
                          "contact.created",
                          "contact.updated",
                          "contact.trashed",
                          "contact.anonymized",
                          "quote.created",
                          "quote.updated",
                          "quote.status_changed",
                          "quote.viewed",
                          "invoice.created",
                          "invoice.paid",
                          "invoice.late",
                          "invoice.issued",
                          "contract.created",
                          "contract.amended",
                          "contract.terminated",
                          "contract.expired",
                          "request.created",
                          "request.updated",
                          "request.status_changed",
                          "request.merged",
                          "request.due_soon",
                          "request.overdue",
                          "request.unassigned",
                          "sales_activity.created",
                          "sales_activity.completed",
                          "sales_activity.cancelled",
                          "invoice.einvoice.submitted",
                          "invoice.einvoice.status_changed",
                          "signature.viewed",
                          "signature.signed",
                          "signature.declined",
                          "signature.expired",
                          "signature.cancelled",
                          "signature.recipient.viewed",
                          "signature.recipient.signed",
                          "export.ready",
                          "campaign.sent",
                          "campaign.paused",
                          "contact.unsubscribed",
                          "contact.marketing_consent_changed",
                          "form.submitted",
                          "event.registered",
                          "event.attended",
                          "order.received",
                          "order.confirmed",
                          "order.delivered",
                          "order.cancelled",
                          "order.updated"
                        ]
                      }
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "disabled"
                      ]
                    },
                    "consecutiveFailures": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "url",
                    "events",
                    "status",
                    "consecutiveFailures",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Supprimer un abonnement (ses livraisons partent avec lui)",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "oauth2": [
              "webhooks:manage"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Abonnement supprimé",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/webhook-deliveries": {
      "get": {
        "summary": "Journal des livraisons récentes (rétention 30 jours)",
        "description": "Les livraisons ne sont pas ordonnées entre elles (retries) : utiliser `data.updatedAt` du payload livré pour un upsert last-write-wins.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Nombre de livraisons retournées - défaut 100, max 200",
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "webhooks:manage"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Livraisons, plus récentes d'abord",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "subscriptionId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "subscriptionUrl": {
                            "type": "string"
                          },
                          "event": {
                            "type": "string"
                          },
                          "occurredAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "delivering",
                              "success",
                              "failed"
                            ]
                          },
                          "attempts": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "nextAttemptAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "lastAttemptAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "httpStatus": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "durationMs": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "error": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          }
                        },
                        "required": [
                          "id",
                          "subscriptionId",
                          "subscriptionUrl",
                          "event",
                          "occurredAt",
                          "status",
                          "attempts",
                          "nextAttemptAt",
                          "lastAttemptAt",
                          "httpStatus",
                          "durationMs",
                          "error",
                          "createdAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/webhook-deliveries/{id}/replay": {
      "post": {
        "summary": "Rejouer une livraison finale (failed ou success) - budget de tentatives neuf",
        "description": "La livraison repasse `pending` avec 5 tentatives ; elle part au prochain drainage (best-effort immédiat, sinon cron `webhooks:run`).",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "oauth2": [
              "webhooks:manage"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Livraison réarmée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "replayed": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "replayed"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/abysign/envelopes": {
      "get": {
        "summary": "Lister les enveloppes (curseur), filtres statut, externalId, sentSince",
        "tags": [
          "Signature électronique (AbySign)"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Filtre par statut",
              "type": "string",
              "enum": [
                "draft",
                "pending",
                "signed",
                "refused",
                "cancelled",
                "expired",
                "superseded"
              ]
            }
          },
          {
            "name": "externalId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Votre identifiant (ex. Quote.Id Salesforce)",
              "type": "string",
              "minLength": 1,
              "maxLength": 120
            }
          },
          {
            "name": "sentSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Envoyées depuis cette date (ISO 8601)",
              "anyOf": [
                {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                {
                  "type": "string",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z))$"
                }
              ]
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "signatures:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page d'enveloppes (sans lien de signature : il se lit enveloppe par enveloppe)",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "pending",
                              "signed",
                              "refused",
                              "cancelled",
                              "expired",
                              "superseded"
                            ]
                          },
                          "sequential": {
                            "type": "boolean"
                          },
                          "recipients": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                },
                                "rank": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                "role": {
                                  "type": "string",
                                  "enum": [
                                    "signer",
                                    "viewer",
                                    "cc",
                                    "in_person"
                                  ]
                                },
                                "name": {
                                  "type": "string"
                                },
                                "email": {
                                  "type": "string"
                                },
                                "status": {
                                  "type": "string",
                                  "enum": [
                                    "pending",
                                    "viewed",
                                    "signed",
                                    "declined"
                                  ]
                                },
                                "accessCodeRequired": {
                                  "type": "boolean"
                                },
                                "sentAt": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "date-time",
                                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "openedAt": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "date-time",
                                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "decidedAt": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "date-time",
                                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "signUrl": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                }
                              },
                              "required": [
                                "id",
                                "rank",
                                "role",
                                "name",
                                "email",
                                "status",
                                "accessCodeRequired",
                                "sentAt",
                                "openedAt",
                                "decidedAt",
                                "signUrl"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "quote",
                              "api"
                            ]
                          },
                          "externalId": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "title": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "quoteId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Devis Cercla rattaché - null pour une enveloppe API"
                          },
                          "accessCodeRequired": {
                            "type": "boolean",
                            "description": "Un code d'accès de l'émetteur protège le document"
                          },
                          "signer": {
                            "type": "object",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "email": {
                                "type": "string"
                              },
                              "signUrl": {
                                "description": "Lien de signature - publié tant que l'enveloppe est en attente, au principal porteur du scope signatures:write, hors réponses de liste ; jamais dans un webhook",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "name",
                              "email",
                              "signUrl"
                            ],
                            "additionalProperties": false
                          },
                          "message": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "sentAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "expiresAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "openedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "decidedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "refusalReason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "sha256": {
                            "type": "object",
                            "properties": {
                              "source": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "signed": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "source",
                              "signed"
                            ],
                            "additionalProperties": false
                          },
                          "timestamp": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "mode": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "authority": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "mode",
                                  "authority"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "fields": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "key": {
                                  "type": "string"
                                },
                                "recipientId": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "uuid",
                                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "type": {
                                  "type": "string",
                                  "enum": [
                                    "signature",
                                    "initials",
                                    "date",
                                    "text",
                                    "checkbox",
                                    "name",
                                    "email",
                                    "company",
                                    "title",
                                    "number",
                                    "dropdown",
                                    "radio"
                                  ]
                                },
                                "page": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                "x": {
                                  "type": "number"
                                },
                                "y": {
                                  "type": "number"
                                },
                                "width": {
                                  "type": "number"
                                },
                                "height": {
                                  "type": "number"
                                },
                                "required": {
                                  "type": "boolean"
                                },
                                "label": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "filled": {
                                  "type": "boolean"
                                },
                                "value": {
                                  "description": "Valeur texte (date, texte, case) - jamais l'image",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                }
                              },
                              "required": [
                                "key",
                                "recipientId",
                                "type",
                                "page",
                                "x",
                                "y",
                                "width",
                                "height",
                                "required",
                                "label",
                                "filled",
                                "value"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "events": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "at": {
                                  "type": "string",
                                  "format": "date-time",
                                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                },
                                "type": {
                                  "type": "string"
                                },
                                "detail": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "at",
                                "type"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "links": {
                            "type": "object",
                            "properties": {
                              "signed": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "certificate": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "proof": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "timestamp": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "signed",
                              "certificate",
                              "proof",
                              "timestamp"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "id",
                          "status",
                          "sequential",
                          "recipients",
                          "source",
                          "externalId",
                          "title",
                          "quoteId",
                          "accessCodeRequired",
                          "signer",
                          "message",
                          "sentAt",
                          "expiresAt",
                          "openedAt",
                          "decidedAt",
                          "refusalReason",
                          "sha256",
                          "timestamp",
                          "fields",
                          "events",
                          "links"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Créer une enveloppe : un PDF, un ou plusieurs destinataires, en brouillon ou envoyée",
        "description": "Deux formes : `application/json` (document en base64, décrit ici) ou `multipart/form-data` (partie `document` = fichier PDF, champs `signer[name]`, `signer[email]`, `message`, `validityDays`, `initialsEveryPage`, `externalId`, `title`, `fields` en JSON). Le document est figé tel quel, jamais re-rendu. Un signataire via `signer`, ou plusieurs destinataires via `recipients` ; `sequential` ordonne les signatures, `draft` prépare sans envoyer. Idempotence par `Idempotency-Key`.",
        "tags": [
          "Signature électronique (AbySign)"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "signer": {
                    "description": "Signataire unique (forme courte) - ou `recipients`",
                    "type": "object",
                    "properties": {
                      "name": {
                        "description": "Nom du signataire (défaut : l'email)",
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                      },
                      "email": {
                        "type": "string",
                        "maxLength": 254,
                        "format": "email",
                        "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                      }
                    },
                    "required": [
                      "email"
                    ],
                    "additionalProperties": false
                  },
                  "recipients": {
                    "description": "Destinataires (T-939) : au moins un rôle signer ou in_person",
                    "minItems": 1,
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "description": "Nom (défaut : l'email)",
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 120
                        },
                        "email": {
                          "type": "string",
                          "maxLength": 254,
                          "format": "email",
                          "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                        },
                        "role": {
                          "default": "signer",
                          "description": "signer : doit signer ; viewer : doit consulter ; cc : reçoit le document final ; in_person : signe sur l'appareil de l'émetteur (aucun email)",
                          "type": "string",
                          "enum": [
                            "signer",
                            "viewer",
                            "cc",
                            "in_person"
                          ]
                        },
                        "rank": {
                          "description": "Rang de signature (ordre séquentiel) - défaut : ordre de la liste",
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 50
                        },
                        "accessCode": {
                          "type": "string",
                          "minLength": 4,
                          "maxLength": 12,
                          "pattern": "^[A-Za-z0-9-]+$"
                        },
                        "privateMessage": {
                          "description": "Note personnelle à ce destinataire",
                          "type": "string",
                          "maxLength": 1000
                        },
                        "verification": {
                          "default": "none",
                          "description": "#1054 : `sms` = code à six chiffres envoyé au mobile `phone` avant d'ouvrir le document (second canal) ; exige un adaptateur SMS configuré, sinon 422",
                          "type": "string",
                          "enum": [
                            "none",
                            "sms"
                          ]
                        },
                        "phone": {
                          "description": "Mobile du destinataire (E.164 ou format français) ; requis avec `verification: sms`",
                          "type": "string",
                          "maxLength": 32
                        }
                      },
                      "required": [
                        "email"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "sequential": {
                    "description": "Ordre séquentiel : chaque rang reçoit son invitation quand le précédent a signé",
                    "type": "boolean"
                  },
                  "draft": {
                    "description": "Brouillon (T-941) : rien n'est envoyé ; placez les champs (PUT …/fields) puis envoyez (POST …/send)",
                    "type": "boolean"
                  },
                  "message": {
                    "description": "Mot de l'émetteur repris dans l'email",
                    "type": "string",
                    "maxLength": 500
                  },
                  "validityDays": {
                    "description": "Défaut : réglage de l'organisation",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 90
                  },
                  "initialsEveryPage": {
                    "description": "Paraphe de chaque page (défaut : réglage de l'organisation)",
                    "type": "boolean"
                  },
                  "accessCode": {
                    "description": "Code d'accès à transmettre au signataire par un autre canal (téléphone) ; le document reste invisible sans lui",
                    "type": "string",
                    "minLength": 4,
                    "maxLength": 12,
                    "pattern": "^[A-Za-z0-9-]+$"
                  },
                  "externalId": {
                    "description": "Votre identifiant (ex. Quote.Id Salesforce), repris dans les webhooks",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "title": {
                    "description": "Libellé montré au signataire (défaut : nom du fichier)",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "fields": {
                    "description": "Champs positionnés ; absent : tags textuels du document, sinon champ signature en bas de la dernière page",
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": [
                            "signature",
                            "initials",
                            "date",
                            "text",
                            "checkbox",
                            "name",
                            "email",
                            "company",
                            "title",
                            "number",
                            "dropdown",
                            "radio"
                          ]
                        },
                        "page": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 9007199254740991,
                          "description": "Page (1 = première)"
                        },
                        "x": {
                          "type": "number",
                          "minimum": 0,
                          "description": "Abscisse en points PDF, origine bas-gauche"
                        },
                        "y": {
                          "type": "number",
                          "minimum": 0,
                          "description": "Ordonnée en points PDF, origine bas-gauche"
                        },
                        "width": {
                          "type": "number",
                          "exclusiveMinimum": 0,
                          "maximum": 2000
                        },
                        "height": {
                          "type": "number",
                          "exclusiveMinimum": 0,
                          "maximum": 2000
                        },
                        "required": {
                          "default": true,
                          "type": "boolean"
                        },
                        "label": {
                          "anyOf": [
                            {
                              "type": "string",
                              "maxLength": 80
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "recipientIndex": {
                          "description": "Index du destinataire signataire dans `recipients` (défaut 0 : le premier signataire)",
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 49
                        },
                        "options": {
                          "description": "Options d'une liste (dropdown) ou d'un choix (radio)",
                          "maxItems": 20,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 80
                          }
                        }
                      },
                      "required": [
                        "type",
                        "page",
                        "x",
                        "y",
                        "width",
                        "height"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "document": {
                    "type": "object",
                    "properties": {
                      "filename": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200
                      },
                      "contentBase64": {
                        "type": "string",
                        "minLength": 1,
                        "description": "Le PDF en base64 (≤ 20 Mo décodés)"
                      }
                    },
                    "required": [
                      "filename",
                      "contentBase64"
                    ],
                    "additionalProperties": false
                  }
                },
                "required": [
                  "document"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "signatures:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Enveloppe en attente, avec `signer.signUrl`",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "pending",
                        "signed",
                        "refused",
                        "cancelled",
                        "expired",
                        "superseded"
                      ]
                    },
                    "sequential": {
                      "type": "boolean"
                    },
                    "recipients": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "rank": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "signer",
                              "viewer",
                              "cc",
                              "in_person"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "viewed",
                              "signed",
                              "declined"
                            ]
                          },
                          "accessCodeRequired": {
                            "type": "boolean"
                          },
                          "sentAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "openedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "decidedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "signUrl": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "rank",
                          "role",
                          "name",
                          "email",
                          "status",
                          "accessCodeRequired",
                          "sentAt",
                          "openedAt",
                          "decidedAt",
                          "signUrl"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "quote",
                        "api"
                      ]
                    },
                    "externalId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "title": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Devis Cercla rattaché - null pour une enveloppe API"
                    },
                    "accessCodeRequired": {
                      "type": "boolean",
                      "description": "Un code d'accès de l'émetteur protège le document"
                    },
                    "signer": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        },
                        "signUrl": {
                          "description": "Lien de signature - publié tant que l'enveloppe est en attente, au principal porteur du scope signatures:write, hors réponses de liste ; jamais dans un webhook",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "name",
                        "email",
                        "signUrl"
                      ],
                      "additionalProperties": false
                    },
                    "message": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sentAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "openedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "decidedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "refusalReason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sha256": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "signed": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "source",
                        "signed"
                      ],
                      "additionalProperties": false
                    },
                    "timestamp": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "mode": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "authority": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "mode",
                            "authority"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "recipientId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "signature",
                              "initials",
                              "date",
                              "text",
                              "checkbox",
                              "name",
                              "email",
                              "company",
                              "title",
                              "number",
                              "dropdown",
                              "radio"
                            ]
                          },
                          "page": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "x": {
                            "type": "number"
                          },
                          "y": {
                            "type": "number"
                          },
                          "width": {
                            "type": "number"
                          },
                          "height": {
                            "type": "number"
                          },
                          "required": {
                            "type": "boolean"
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "filled": {
                            "type": "boolean"
                          },
                          "value": {
                            "description": "Valeur texte (date, texte, case) - jamais l'image",
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "key",
                          "recipientId",
                          "type",
                          "page",
                          "x",
                          "y",
                          "width",
                          "height",
                          "required",
                          "label",
                          "filled",
                          "value"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "at": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "type": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "at",
                          "type"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "links": {
                      "type": "object",
                      "properties": {
                        "signed": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "certificate": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "proof": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "timestamp": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "signed",
                        "certificate",
                        "proof",
                        "timestamp"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "status",
                    "sequential",
                    "recipients",
                    "source",
                    "externalId",
                    "title",
                    "quoteId",
                    "accessCodeRequired",
                    "signer",
                    "message",
                    "sentAt",
                    "expiresAt",
                    "openedAt",
                    "decidedAt",
                    "refusalReason",
                    "sha256",
                    "timestamp",
                    "fields",
                    "events",
                    "links"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/abysign/envelopes/{id}": {
      "get": {
        "summary": "Statut, champs, événements et liens d'une enveloppe",
        "tags": [
          "Signature électronique (AbySign)"
        ],
        "security": [
          {
            "oauth2": [
              "signatures:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Enveloppe",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "pending",
                        "signed",
                        "refused",
                        "cancelled",
                        "expired",
                        "superseded"
                      ]
                    },
                    "sequential": {
                      "type": "boolean"
                    },
                    "recipients": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "rank": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "signer",
                              "viewer",
                              "cc",
                              "in_person"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "viewed",
                              "signed",
                              "declined"
                            ]
                          },
                          "accessCodeRequired": {
                            "type": "boolean"
                          },
                          "sentAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "openedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "decidedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "signUrl": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "rank",
                          "role",
                          "name",
                          "email",
                          "status",
                          "accessCodeRequired",
                          "sentAt",
                          "openedAt",
                          "decidedAt",
                          "signUrl"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "quote",
                        "api"
                      ]
                    },
                    "externalId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "title": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Devis Cercla rattaché - null pour une enveloppe API"
                    },
                    "accessCodeRequired": {
                      "type": "boolean",
                      "description": "Un code d'accès de l'émetteur protège le document"
                    },
                    "signer": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        },
                        "signUrl": {
                          "description": "Lien de signature - publié tant que l'enveloppe est en attente, au principal porteur du scope signatures:write, hors réponses de liste ; jamais dans un webhook",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "name",
                        "email",
                        "signUrl"
                      ],
                      "additionalProperties": false
                    },
                    "message": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sentAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "openedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "decidedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "refusalReason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sha256": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "signed": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "source",
                        "signed"
                      ],
                      "additionalProperties": false
                    },
                    "timestamp": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "mode": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "authority": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "mode",
                            "authority"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "recipientId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "signature",
                              "initials",
                              "date",
                              "text",
                              "checkbox",
                              "name",
                              "email",
                              "company",
                              "title",
                              "number",
                              "dropdown",
                              "radio"
                            ]
                          },
                          "page": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "x": {
                            "type": "number"
                          },
                          "y": {
                            "type": "number"
                          },
                          "width": {
                            "type": "number"
                          },
                          "height": {
                            "type": "number"
                          },
                          "required": {
                            "type": "boolean"
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "filled": {
                            "type": "boolean"
                          },
                          "value": {
                            "description": "Valeur texte (date, texte, case) - jamais l'image",
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "key",
                          "recipientId",
                          "type",
                          "page",
                          "x",
                          "y",
                          "width",
                          "height",
                          "required",
                          "label",
                          "filled",
                          "value"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "at": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "type": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "at",
                          "type"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "links": {
                      "type": "object",
                      "properties": {
                        "signed": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "certificate": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "proof": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "timestamp": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "signed",
                        "certificate",
                        "proof",
                        "timestamp"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "status",
                    "sequential",
                    "recipients",
                    "source",
                    "externalId",
                    "title",
                    "quoteId",
                    "accessCodeRequired",
                    "signer",
                    "message",
                    "sentAt",
                    "expiresAt",
                    "openedAt",
                    "decidedAt",
                    "refusalReason",
                    "sha256",
                    "timestamp",
                    "fields",
                    "events",
                    "links"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/abysign/envelopes/{id}/remind": {
      "post": {
        "summary": "Relancer le signataire (une relance par heure et par enveloppe)",
        "description": "409 si l'enveloppe n'est plus en attente, 429 avec `Retry-After` si une relance date de moins d'une heure.",
        "tags": [
          "Signature électronique (AbySign)"
        ],
        "security": [
          {
            "oauth2": [
              "signatures:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Enveloppe après relance",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "pending",
                        "signed",
                        "refused",
                        "cancelled",
                        "expired",
                        "superseded"
                      ]
                    },
                    "sequential": {
                      "type": "boolean"
                    },
                    "recipients": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "rank": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "signer",
                              "viewer",
                              "cc",
                              "in_person"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "viewed",
                              "signed",
                              "declined"
                            ]
                          },
                          "accessCodeRequired": {
                            "type": "boolean"
                          },
                          "sentAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "openedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "decidedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "signUrl": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "rank",
                          "role",
                          "name",
                          "email",
                          "status",
                          "accessCodeRequired",
                          "sentAt",
                          "openedAt",
                          "decidedAt",
                          "signUrl"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "quote",
                        "api"
                      ]
                    },
                    "externalId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "title": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Devis Cercla rattaché - null pour une enveloppe API"
                    },
                    "accessCodeRequired": {
                      "type": "boolean",
                      "description": "Un code d'accès de l'émetteur protège le document"
                    },
                    "signer": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        },
                        "signUrl": {
                          "description": "Lien de signature - publié tant que l'enveloppe est en attente, au principal porteur du scope signatures:write, hors réponses de liste ; jamais dans un webhook",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "name",
                        "email",
                        "signUrl"
                      ],
                      "additionalProperties": false
                    },
                    "message": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sentAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "openedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "decidedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "refusalReason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sha256": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "signed": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "source",
                        "signed"
                      ],
                      "additionalProperties": false
                    },
                    "timestamp": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "mode": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "authority": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "mode",
                            "authority"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "recipientId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "signature",
                              "initials",
                              "date",
                              "text",
                              "checkbox",
                              "name",
                              "email",
                              "company",
                              "title",
                              "number",
                              "dropdown",
                              "radio"
                            ]
                          },
                          "page": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "x": {
                            "type": "number"
                          },
                          "y": {
                            "type": "number"
                          },
                          "width": {
                            "type": "number"
                          },
                          "height": {
                            "type": "number"
                          },
                          "required": {
                            "type": "boolean"
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "filled": {
                            "type": "boolean"
                          },
                          "value": {
                            "description": "Valeur texte (date, texte, case) - jamais l'image",
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "key",
                          "recipientId",
                          "type",
                          "page",
                          "x",
                          "y",
                          "width",
                          "height",
                          "required",
                          "label",
                          "filled",
                          "value"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "at": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "type": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "at",
                          "type"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "links": {
                      "type": "object",
                      "properties": {
                        "signed": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "certificate": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "proof": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "timestamp": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "signed",
                        "certificate",
                        "proof",
                        "timestamp"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "status",
                    "sequential",
                    "recipients",
                    "source",
                    "externalId",
                    "title",
                    "quoteId",
                    "accessCodeRequired",
                    "signer",
                    "message",
                    "sentAt",
                    "expiresAt",
                    "openedAt",
                    "decidedAt",
                    "refusalReason",
                    "sha256",
                    "timestamp",
                    "fields",
                    "events",
                    "links"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/abysign/envelopes/{id}/cancel": {
      "post": {
        "summary": "Annuler une enveloppe en attente (le lien affiche « annulée »)",
        "description": "Idempotent sur une enveloppe déjà annulée ; 409 si elle est signée, refusée ou expirée.",
        "tags": [
          "Signature électronique (AbySign)"
        ],
        "security": [
          {
            "oauth2": [
              "signatures:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Enveloppe annulée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "pending",
                        "signed",
                        "refused",
                        "cancelled",
                        "expired",
                        "superseded"
                      ]
                    },
                    "sequential": {
                      "type": "boolean"
                    },
                    "recipients": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "rank": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "signer",
                              "viewer",
                              "cc",
                              "in_person"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "viewed",
                              "signed",
                              "declined"
                            ]
                          },
                          "accessCodeRequired": {
                            "type": "boolean"
                          },
                          "sentAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "openedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "decidedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "signUrl": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "rank",
                          "role",
                          "name",
                          "email",
                          "status",
                          "accessCodeRequired",
                          "sentAt",
                          "openedAt",
                          "decidedAt",
                          "signUrl"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "quote",
                        "api"
                      ]
                    },
                    "externalId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "title": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Devis Cercla rattaché - null pour une enveloppe API"
                    },
                    "accessCodeRequired": {
                      "type": "boolean",
                      "description": "Un code d'accès de l'émetteur protège le document"
                    },
                    "signer": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        },
                        "signUrl": {
                          "description": "Lien de signature - publié tant que l'enveloppe est en attente, au principal porteur du scope signatures:write, hors réponses de liste ; jamais dans un webhook",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "name",
                        "email",
                        "signUrl"
                      ],
                      "additionalProperties": false
                    },
                    "message": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sentAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "openedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "decidedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "refusalReason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sha256": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "signed": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "source",
                        "signed"
                      ],
                      "additionalProperties": false
                    },
                    "timestamp": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "mode": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "authority": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "mode",
                            "authority"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "recipientId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "signature",
                              "initials",
                              "date",
                              "text",
                              "checkbox",
                              "name",
                              "email",
                              "company",
                              "title",
                              "number",
                              "dropdown",
                              "radio"
                            ]
                          },
                          "page": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "x": {
                            "type": "number"
                          },
                          "y": {
                            "type": "number"
                          },
                          "width": {
                            "type": "number"
                          },
                          "height": {
                            "type": "number"
                          },
                          "required": {
                            "type": "boolean"
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "filled": {
                            "type": "boolean"
                          },
                          "value": {
                            "description": "Valeur texte (date, texte, case) - jamais l'image",
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "key",
                          "recipientId",
                          "type",
                          "page",
                          "x",
                          "y",
                          "width",
                          "height",
                          "required",
                          "label",
                          "filled",
                          "value"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "at": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "type": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "at",
                          "type"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "links": {
                      "type": "object",
                      "properties": {
                        "signed": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "certificate": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "proof": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "timestamp": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "signed",
                        "certificate",
                        "proof",
                        "timestamp"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "status",
                    "sequential",
                    "recipients",
                    "source",
                    "externalId",
                    "title",
                    "quoteId",
                    "accessCodeRequired",
                    "signer",
                    "message",
                    "sentAt",
                    "expiresAt",
                    "openedAt",
                    "decidedAt",
                    "refusalReason",
                    "sha256",
                    "timestamp",
                    "fields",
                    "events",
                    "links"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/abysign/envelopes/{id}/fields": {
      "put": {
        "summary": "Remplacer les champs d'un brouillon (positions en points PDF, origine bas-gauche)",
        "description": "Brouillon seulement (409 sinon). Au moins un champ `signature`. `recipientId` désigne le signataire ; absent : le premier.",
        "tags": [
          "Signature électronique (AbySign)"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "fields": {
                    "minItems": 1,
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": [
                            "signature",
                            "initials",
                            "date",
                            "text",
                            "checkbox",
                            "name",
                            "email",
                            "company",
                            "title",
                            "number",
                            "dropdown",
                            "radio"
                          ]
                        },
                        "page": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 9007199254740991,
                          "description": "Page (1 = première)"
                        },
                        "x": {
                          "type": "number",
                          "minimum": 0,
                          "description": "Abscisse en points PDF, origine bas-gauche"
                        },
                        "y": {
                          "type": "number",
                          "minimum": 0,
                          "description": "Ordonnée en points PDF, origine bas-gauche"
                        },
                        "width": {
                          "type": "number",
                          "exclusiveMinimum": 0,
                          "maximum": 2000
                        },
                        "height": {
                          "type": "number",
                          "exclusiveMinimum": 0,
                          "maximum": 2000
                        },
                        "required": {
                          "default": true,
                          "type": "boolean"
                        },
                        "label": {
                          "anyOf": [
                            {
                              "type": "string",
                              "maxLength": 80
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "recipientIndex": {
                          "description": "Index du destinataire signataire dans `recipients` (défaut 0 : le premier signataire)",
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 49
                        },
                        "options": {
                          "description": "Options d'une liste (dropdown) ou d'un choix (radio)",
                          "maxItems": 20,
                          "type": "array",
                          "items": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 80
                          }
                        },
                        "key": {
                          "type": "string",
                          "maxLength": 60
                        },
                        "recipientId": {
                          "description": "Signataire du champ (id de destinataire) - défaut : le premier",
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "type",
                        "page",
                        "x",
                        "y",
                        "width",
                        "height"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "fields"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "signatures:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Enveloppe avec ses champs",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "pending",
                        "signed",
                        "refused",
                        "cancelled",
                        "expired",
                        "superseded"
                      ]
                    },
                    "sequential": {
                      "type": "boolean"
                    },
                    "recipients": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "rank": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "signer",
                              "viewer",
                              "cc",
                              "in_person"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "viewed",
                              "signed",
                              "declined"
                            ]
                          },
                          "accessCodeRequired": {
                            "type": "boolean"
                          },
                          "sentAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "openedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "decidedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "signUrl": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "rank",
                          "role",
                          "name",
                          "email",
                          "status",
                          "accessCodeRequired",
                          "sentAt",
                          "openedAt",
                          "decidedAt",
                          "signUrl"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "quote",
                        "api"
                      ]
                    },
                    "externalId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "title": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Devis Cercla rattaché - null pour une enveloppe API"
                    },
                    "accessCodeRequired": {
                      "type": "boolean",
                      "description": "Un code d'accès de l'émetteur protège le document"
                    },
                    "signer": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        },
                        "signUrl": {
                          "description": "Lien de signature - publié tant que l'enveloppe est en attente, au principal porteur du scope signatures:write, hors réponses de liste ; jamais dans un webhook",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "name",
                        "email",
                        "signUrl"
                      ],
                      "additionalProperties": false
                    },
                    "message": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sentAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "openedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "decidedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "refusalReason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sha256": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "signed": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "source",
                        "signed"
                      ],
                      "additionalProperties": false
                    },
                    "timestamp": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "mode": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "authority": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "mode",
                            "authority"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "recipientId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "signature",
                              "initials",
                              "date",
                              "text",
                              "checkbox",
                              "name",
                              "email",
                              "company",
                              "title",
                              "number",
                              "dropdown",
                              "radio"
                            ]
                          },
                          "page": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "x": {
                            "type": "number"
                          },
                          "y": {
                            "type": "number"
                          },
                          "width": {
                            "type": "number"
                          },
                          "height": {
                            "type": "number"
                          },
                          "required": {
                            "type": "boolean"
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "filled": {
                            "type": "boolean"
                          },
                          "value": {
                            "description": "Valeur texte (date, texte, case) - jamais l'image",
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "key",
                          "recipientId",
                          "type",
                          "page",
                          "x",
                          "y",
                          "width",
                          "height",
                          "required",
                          "label",
                          "filled",
                          "value"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "at": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "type": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "at",
                          "type"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "links": {
                      "type": "object",
                      "properties": {
                        "signed": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "certificate": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "proof": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "timestamp": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "signed",
                        "certificate",
                        "proof",
                        "timestamp"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "status",
                    "sequential",
                    "recipients",
                    "source",
                    "externalId",
                    "title",
                    "quoteId",
                    "accessCodeRequired",
                    "signer",
                    "message",
                    "sentAt",
                    "expiresAt",
                    "openedAt",
                    "decidedAt",
                    "refusalReason",
                    "sha256",
                    "timestamp",
                    "fields",
                    "events",
                    "links"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/abysign/envelopes/{id}/send": {
      "post": {
        "summary": "Envoyer un brouillon : invitations, rappels, statut en attente",
        "description": "409 si l'enveloppe n'est plus un brouillon ; 422 sans champ signature.",
        "tags": [
          "Signature électronique (AbySign)"
        ],
        "security": [
          {
            "oauth2": [
              "signatures:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Enveloppe en attente",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "pending",
                        "signed",
                        "refused",
                        "cancelled",
                        "expired",
                        "superseded"
                      ]
                    },
                    "sequential": {
                      "type": "boolean"
                    },
                    "recipients": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "rank": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "role": {
                            "type": "string",
                            "enum": [
                              "signer",
                              "viewer",
                              "cc",
                              "in_person"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "viewed",
                              "signed",
                              "declined"
                            ]
                          },
                          "accessCodeRequired": {
                            "type": "boolean"
                          },
                          "sentAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "openedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "decidedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "signUrl": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "rank",
                          "role",
                          "name",
                          "email",
                          "status",
                          "accessCodeRequired",
                          "sentAt",
                          "openedAt",
                          "decidedAt",
                          "signUrl"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "quote",
                        "api"
                      ]
                    },
                    "externalId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "title": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "quoteId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Devis Cercla rattaché - null pour une enveloppe API"
                    },
                    "accessCodeRequired": {
                      "type": "boolean",
                      "description": "Un code d'accès de l'émetteur protège le document"
                    },
                    "signer": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        },
                        "signUrl": {
                          "description": "Lien de signature - publié tant que l'enveloppe est en attente, au principal porteur du scope signatures:write, hors réponses de liste ; jamais dans un webhook",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "name",
                        "email",
                        "signUrl"
                      ],
                      "additionalProperties": false
                    },
                    "message": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sentAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "openedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "decidedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "refusalReason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "sha256": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "signed": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "source",
                        "signed"
                      ],
                      "additionalProperties": false
                    },
                    "timestamp": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "mode": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "authority": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "mode",
                            "authority"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "recipientId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "signature",
                              "initials",
                              "date",
                              "text",
                              "checkbox",
                              "name",
                              "email",
                              "company",
                              "title",
                              "number",
                              "dropdown",
                              "radio"
                            ]
                          },
                          "page": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "x": {
                            "type": "number"
                          },
                          "y": {
                            "type": "number"
                          },
                          "width": {
                            "type": "number"
                          },
                          "height": {
                            "type": "number"
                          },
                          "required": {
                            "type": "boolean"
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "filled": {
                            "type": "boolean"
                          },
                          "value": {
                            "description": "Valeur texte (date, texte, case) - jamais l'image",
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "key",
                          "recipientId",
                          "type",
                          "page",
                          "x",
                          "y",
                          "width",
                          "height",
                          "required",
                          "label",
                          "filled",
                          "value"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "at": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "type": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "at",
                          "type"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "links": {
                      "type": "object",
                      "properties": {
                        "signed": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "certificate": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "proof": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "timestamp": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "signed",
                        "certificate",
                        "proof",
                        "timestamp"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "id",
                    "status",
                    "sequential",
                    "recipients",
                    "source",
                    "externalId",
                    "title",
                    "quoteId",
                    "accessCodeRequired",
                    "signer",
                    "message",
                    "sentAt",
                    "expiresAt",
                    "openedAt",
                    "decidedAt",
                    "refusalReason",
                    "sha256",
                    "timestamp",
                    "fields",
                    "events",
                    "links"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/abysign/envelopes/{id}/signed.pdf": {
      "get": {
        "summary": "PDF signé (certificat de signature en dernières pages)",
        "description": "Réponse `application/pdf` en pièce jointe. 404 tant que l'enveloppe n'est pas signée ou si l'artefact n'existe pas.",
        "tags": [
          "Signature électronique (AbySign)"
        ],
        "security": [
          {
            "oauth2": [
              "signatures:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "PDF signé (certificat de signature en dernières pages)"
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/abysign/envelopes/{id}/certificate.pdf": {
      "get": {
        "summary": "Certificat de signature seul",
        "description": "Réponse `application/pdf` en pièce jointe. 404 tant que l'enveloppe n'est pas signée ou si l'artefact n'existe pas.",
        "tags": [
          "Signature électronique (AbySign)"
        ],
        "security": [
          {
            "oauth2": [
              "signatures:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Certificat de signature seul"
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/abysign/envelopes/{id}/proof.json": {
      "get": {
        "summary": "Journal de preuve scellé (Ed25519, clé publique incluse)",
        "description": "Réponse `application/json` en pièce jointe. 404 tant que l'enveloppe n'est pas signée ou si l'artefact n'existe pas.",
        "tags": [
          "Signature électronique (AbySign)"
        ],
        "security": [
          {
            "oauth2": [
              "signatures:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Journal de preuve scellé (Ed25519, clé publique incluse)",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {},
                  "description": "Voir docs/08-API §16 et la page /verifier"
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/abysign/envelopes/{id}/timestamp.tsr": {
      "get": {
        "summary": "Jeton d'horodatage RFC 3161 (404 sans autorité configurée)",
        "description": "Réponse `application/timestamp-reply` en pièce jointe. 404 tant que l'enveloppe n'est pas signée ou si l'artefact n'existe pas.",
        "tags": [
          "Signature électronique (AbySign)"
        ],
        "security": [
          {
            "oauth2": [
              "signatures:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Jeton d'horodatage RFC 3161 (404 sans autorité configurée)"
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/search": {
      "get": {
        "summary": "Recherche globale (texte : contexte utilisateur ; identifiant externe : les deux realms)",
        "description": "Les HUIT enregistrements (T-1430, ADR-176 D2 ; commandes depuis #427) : sociétés, contacts, devis, contrats, commandes, factures, requêtes, activités commerciales - mêmes règles que la recherche de l'UI web (5 par groupe, casse et accents repliés, corbeille et contacts anonymisés exclus), visibilité du principal appliquée groupe par groupe. Mode texte (`q`) : requête vide = les plus récents par catégorie ; réservé aux sessions utilisateur (§2bis), 403 pour une app connectée. Mode identifiant externe (`externalId`, `externalSource` facultatif, T-1197) : les objets qui portent cet identifiant exact, ouvert aux apps connectées dans leur périmètre et pour les objets de leurs scopes de lecture (un objet hors scope = liste vide) ; il ne couvre que les objets qu'`external_ref` porte (société, contact, devis, facture, contrat), `requests` et `activities` y répondent vide ; `q` et `externalId` ne se combinent pas (422). Les contrats et les commandes se lisent sous `quotes:read`, comme la ressource `/contracts` ; `orders` répond vide en mode identifiant externe (external_ref ne porte pas la commande). La facture et l'activité n'ont pas de page de fiche : leur `ref` porte la clé de loupe de leur liste.",
        "tags": [
          "mobile"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Texte recherché (vide = récents) - contexte utilisateur",
              "type": "string"
            }
          },
          {
            "name": "externalId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Objets qui portent cet identifiant externe (exact) - avec `externalSource` pour une source précise",
              "type": "string"
            }
          },
          {
            "name": "externalSource",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Source de l'identifiant externe (`tacto`…)",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Résultats par catégorie",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "companies": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact",
                              "quote",
                              "contract",
                              "order",
                              "invoice",
                              "request",
                              "salesActivity",
                              "article"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "title": {
                            "type": "string"
                          },
                          "sub": {
                            "type": "string"
                          },
                          "ref": {
                            "description": "Clé de loupe des objets sans page de fiche (numéro de facture, titre d'activité) : de quoi ouvrir la liste correspondante sur la ligne visée",
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "id",
                          "title",
                          "sub"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Résultats sociétés (5 au plus)"
                    },
                    "contacts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact",
                              "quote",
                              "contract",
                              "order",
                              "invoice",
                              "request",
                              "salesActivity",
                              "article"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "title": {
                            "type": "string"
                          },
                          "sub": {
                            "type": "string"
                          },
                          "ref": {
                            "description": "Clé de loupe des objets sans page de fiche (numéro de facture, titre d'activité) : de quoi ouvrir la liste correspondante sur la ligne visée",
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "id",
                          "title",
                          "sub"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Résultats contacts (5 au plus)"
                    },
                    "quotes": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact",
                              "quote",
                              "contract",
                              "order",
                              "invoice",
                              "request",
                              "salesActivity",
                              "article"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "title": {
                            "type": "string"
                          },
                          "sub": {
                            "type": "string"
                          },
                          "ref": {
                            "description": "Clé de loupe des objets sans page de fiche (numéro de facture, titre d'activité) : de quoi ouvrir la liste correspondante sur la ligne visée",
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "id",
                          "title",
                          "sub"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Résultats devis (5 au plus)"
                    },
                    "contracts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact",
                              "quote",
                              "contract",
                              "order",
                              "invoice",
                              "request",
                              "salesActivity",
                              "article"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "title": {
                            "type": "string"
                          },
                          "sub": {
                            "type": "string"
                          },
                          "ref": {
                            "description": "Clé de loupe des objets sans page de fiche (numéro de facture, titre d'activité) : de quoi ouvrir la liste correspondante sur la ligne visée",
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "id",
                          "title",
                          "sub"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Résultats contrats (5 au plus)"
                    },
                    "orders": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact",
                              "quote",
                              "contract",
                              "order",
                              "invoice",
                              "request",
                              "salesActivity",
                              "article"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "title": {
                            "type": "string"
                          },
                          "sub": {
                            "type": "string"
                          },
                          "ref": {
                            "description": "Clé de loupe des objets sans page de fiche (numéro de facture, titre d'activité) : de quoi ouvrir la liste correspondante sur la ligne visée",
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "id",
                          "title",
                          "sub"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Résultats commandes (5 au plus)"
                    },
                    "invoices": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact",
                              "quote",
                              "contract",
                              "order",
                              "invoice",
                              "request",
                              "salesActivity",
                              "article"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "title": {
                            "type": "string"
                          },
                          "sub": {
                            "type": "string"
                          },
                          "ref": {
                            "description": "Clé de loupe des objets sans page de fiche (numéro de facture, titre d'activité) : de quoi ouvrir la liste correspondante sur la ligne visée",
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "id",
                          "title",
                          "sub"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Résultats factures (5 au plus)"
                    },
                    "requests": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact",
                              "quote",
                              "contract",
                              "order",
                              "invoice",
                              "request",
                              "salesActivity",
                              "article"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "title": {
                            "type": "string"
                          },
                          "sub": {
                            "type": "string"
                          },
                          "ref": {
                            "description": "Clé de loupe des objets sans page de fiche (numéro de facture, titre d'activité) : de quoi ouvrir la liste correspondante sur la ligne visée",
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "id",
                          "title",
                          "sub"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Résultats requêtes (5 au plus)"
                    },
                    "activities": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact",
                              "quote",
                              "contract",
                              "order",
                              "invoice",
                              "request",
                              "salesActivity",
                              "article"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "title": {
                            "type": "string"
                          },
                          "sub": {
                            "type": "string"
                          },
                          "ref": {
                            "description": "Clé de loupe des objets sans page de fiche (numéro de facture, titre d'activité) : de quoi ouvrir la liste correspondante sur la ligne visée",
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "id",
                          "title",
                          "sub"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Résultats activités commerciales (5 au plus)"
                    },
                    "articles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "company",
                              "contact",
                              "quote",
                              "contract",
                              "order",
                              "invoice",
                              "request",
                              "salesActivity",
                              "article"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "title": {
                            "type": "string"
                          },
                          "sub": {
                            "type": "string"
                          },
                          "ref": {
                            "description": "Clé de loupe des objets sans page de fiche (numéro de facture, titre d'activité) : de quoi ouvrir la liste correspondante sur la ligne visée",
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "id",
                          "title",
                          "sub"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Résultats articles publiés de la base de connaissances (#1061) (5 au plus)"
                    }
                  },
                  "required": [
                    "companies",
                    "contacts",
                    "quotes",
                    "contracts",
                    "orders",
                    "invoices",
                    "requests",
                    "activities",
                    "articles"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/home": {
      "get": {
        "summary": "Accueil terrain : récents + prochaines activités (contexte utilisateur uniquement)",
        "description": "Agrégat personnel en un appel : 5 derniers consultés par catégorie (visibilité appliquée), 10 prochaines activités planifiées de l'utilisateur (retards compris), compteur de notifications non lues. Réservé aux sessions utilisateur (§2bis).",
        "tags": [
          "mobile"
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Agrégat de l'accueil",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "recents": {
                      "type": "object",
                      "properties": {
                        "companies": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              "title": {
                                "type": "string"
                              },
                              "sub": {
                                "type": "string"
                              },
                              "viewedAt": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "title",
                              "sub",
                              "viewedAt"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "contacts": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              "title": {
                                "type": "string"
                              },
                              "sub": {
                                "type": "string"
                              },
                              "viewedAt": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "title",
                              "sub",
                              "viewedAt"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "quotes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              "title": {
                                "type": "string"
                              },
                              "sub": {
                                "type": "string"
                              },
                              "viewedAt": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "title",
                              "sub",
                              "viewedAt"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "companies",
                        "contacts",
                        "quotes"
                      ],
                      "additionalProperties": false
                    },
                    "upcomingActivities": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "call",
                              "meeting",
                              "task"
                            ]
                          },
                          "title": {
                            "type": "string"
                          },
                          "dueAt": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "startsAt": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "endsAt": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "location": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "companyId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "contactId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "quoteId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "kind",
                          "title",
                          "dueAt",
                          "startsAt",
                          "endsAt",
                          "location",
                          "companyId",
                          "contactId",
                          "quoteId"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "unreadNotifications": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "recents",
                    "upcomingActivities",
                    "unreadNotifications"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/notifications": {
      "get": {
        "summary": "Notifications in-app de l'utilisateur (contexte utilisateur uniquement)",
        "description": "Les 30 dernières + compteur de non-lues, comme le panel web (T-015). Page complète bornée, sans curseur. Réservé aux sessions utilisateur (§2bis).",
        "tags": [
          "mobile"
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Notifications + compteur",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "type": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "sub": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "target": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "kind": {
                                    "type": "string"
                                  },
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                  }
                                },
                                "required": [
                                  "kind",
                                  "id"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "readAt": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "type",
                          "title",
                          "sub",
                          "target",
                          "readAt",
                          "createdAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "unreadCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "nextCursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "data",
                    "unreadCount",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/notifications/{id}/read": {
      "post": {
        "summary": "Marquer une notification lue (idempotent)",
        "tags": [
          "mobile"
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Notification lue",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "read": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "read"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/notifications/read-all": {
      "post": {
        "summary": "Marquer toutes les notifications lues",
        "tags": [
          "mobile"
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Nombre de notifications marquées",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "read": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "read"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/comments": {
      "get": {
        "summary": "Notes d'une fiche (contexte utilisateur uniquement)",
        "description": "Notes de la fiche ciblée (exactement un de companyId/contactId/quoteId). Anté-chronologique par curseur `before`, servi en ordre chronologique. La fiche doit être visible. Les pièces jointes ne sont pas servies (téléchargement hors contrat bearer V1). Réservé aux sessions utilisateur (§2bis).",
        "tags": [
          "mobile"
        ],
        "parameters": [
          {
            "name": "companyId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "contactId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "quoteId",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur createdAt (ISO) de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          }
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Notes de la fiche",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "authorId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "authorName": {
                            "type": "string"
                          },
                          "authorAvatar": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "body": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "authorId",
                          "authorName",
                          "authorAvatar",
                          "body",
                          "createdAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextBefore": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextBefore"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Créer une note sur une fiche (contexte utilisateur uniquement)",
        "tags": [
          "mobile"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "companyId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "contactId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "quoteId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 5000
                  }
                },
                "required": [
                  "body"
                ]
              }
            }
          }
        },
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Note créée",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "required": [
                    "id"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/users/me": {
      "get": {
        "summary": "Mon profil et mes préférences (contexte utilisateur uniquement)",
        "tags": [
          "mobile"
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Mon profil",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "email": {
                      "type": "string"
                    },
                    "role": {
                      "type": "string"
                    },
                    "avatar": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "phone": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "twoFactorEnabled": {
                      "type": "boolean"
                    },
                    "defaultCycleId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "defaultBusinessUnitId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "email",
                    "role",
                    "avatar",
                    "phone",
                    "twoFactorEnabled",
                    "defaultCycleId",
                    "defaultBusinessUnitId"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Modifier mes préférences (téléphone, cycle et entité par défaut)",
        "description": "Fusion partielle : null efface la préférence, les clés absentes sont préservées.",
        "tags": [
          "mobile"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "phone": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 40
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "defaultCycleId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "defaultBusinessUnitId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Mon profil à jour",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "email": {
                      "type": "string"
                    },
                    "role": {
                      "type": "string"
                    },
                    "avatar": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "phone": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "twoFactorEnabled": {
                      "type": "boolean"
                    },
                    "defaultCycleId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "defaultBusinessUnitId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "email",
                    "role",
                    "avatar",
                    "phone",
                    "twoFactorEnabled",
                    "defaultCycleId",
                    "defaultBusinessUnitId"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/chat/conversations": {
      "get": {
        "summary": "Mes conversations (messagerie interne)",
        "description": "Les fils de l'utilisateur, tri dernier message, non-lus par fil + total. Page complète bornée (30, comme le dock web) - pas de curseur V1. Réservé aux sessions utilisateur (§2bis).",
        "tags": [
          "chat"
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Conversations + total de non-lus",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "dm",
                              "group"
                            ]
                          },
                          "title": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "other": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                  },
                                  "name": {
                                    "type": "string"
                                  },
                                  "avatar": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "online": {
                                    "type": "boolean"
                                  }
                                },
                                "required": [
                                  "id",
                                  "name",
                                  "avatar",
                                  "online"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "participants": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "format": "uuid",
                                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                },
                                "name": {
                                  "type": "string"
                                },
                                "avatar": {
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "online": {
                                  "type": "boolean"
                                }
                              },
                              "required": [
                                "id",
                                "name",
                                "avatar",
                                "online"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "lastMessage": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "body": {
                                    "type": "string"
                                  },
                                  "authorId": {
                                    "type": "string",
                                    "format": "uuid",
                                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                                  },
                                  "createdAt": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "body",
                                  "authorId",
                                  "createdAt"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "unread": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "id",
                          "kind",
                          "title",
                          "other",
                          "participants",
                          "lastMessage",
                          "unread"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "unreadTotal": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "nextCursor": {
                      "type": "null"
                    }
                  },
                  "required": [
                    "data",
                    "unreadTotal",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Ouvrir un fil : DM (idempotent) ou GROUPE (T-768, ADR-110)",
        "description": "userId (ou userIds à 1) = message direct, idempotent - le fil existant est rendu tel quel. userIds à 2+ = groupe (créateur inclus d'office, titre optionnel) - pas de dédoublonnage entre groupes.",
        "tags": [
          "chat"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "userId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "userIds": {
                    "minItems": 1,
                    "maxItems": 24,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "title": {
                    "type": "string",
                    "maxLength": 80
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Le fil (créé ou existant)",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "conversationId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "required": [
                    "conversationId"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/chat/conversations/{id}/messages": {
      "get": {
        "summary": "Le fil, paginé du plus récent",
        "description": "Pagination par `before` ISO (précédent comments : pas d'updated_at sur les messages). Fil inconnu ou pas à moi = 404. Curseurs de lecture des deux participants inclus.",
        "tags": [
          "chat"
        ],
        "parameters": [
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "anyOf": [
                {
                  "type": "string",
                  "format": "date-time",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                },
                {
                  "type": "string",
                  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z))$"
                }
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          }
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Messages (ordre chronologique) + curseurs",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "authorId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "body": {
                            "type": "string"
                          },
                          "quoted": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "messageId": {
                                    "type": "string"
                                  },
                                  "author": {
                                    "type": "string"
                                  },
                                  "excerpt": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "messageId",
                                  "author",
                                  "excerpt"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "attachments": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "kind": {
                                  "type": "string",
                                  "enum": [
                                    "image",
                                    "file",
                                    "gif",
                                    "audio",
                                    "video"
                                  ]
                                },
                                "path": {
                                  "type": "string"
                                },
                                "url": {
                                  "type": "string"
                                },
                                "name": {
                                  "type": "string"
                                },
                                "size": {
                                  "type": "number"
                                },
                                "mime": {
                                  "type": "string"
                                }
                              },
                              "required": [
                                "kind",
                                "name"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "reactions": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {
                              "type": "array",
                              "items": {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              }
                            }
                          },
                          "createdAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "authorId",
                          "body",
                          "quoted",
                          "attachments",
                          "reactions",
                          "createdAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextBefore": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "myLastReadAt": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "otherLastReadAt": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "items",
                    "nextBefore",
                    "myLastReadAt",
                    "otherLastReadAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Envoyer un message texte",
        "description": "Texte 1-4000 caractères (bornes du composer web).",
        "tags": [
          "chat"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  }
                },
                "required": [
                  "body"
                ]
              }
            }
          }
        },
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Message créé",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "messageId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "required": [
                    "messageId"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/chat/conversations/{id}/read": {
      "post": {
        "summary": "Accusé de lecture du fil (idempotent)",
        "tags": [
          "chat"
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Fil lu",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "read": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "read"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/chat/messages/{id}/reactions": {
      "post": {
        "summary": "Poser une réaction emoji (idempotent)",
        "tags": [
          "chat"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "emoji": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 16
                  }
                },
                "required": [
                  "emoji"
                ]
              }
            }
          }
        },
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Réactions à jour du message",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "reactions": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        }
                      }
                    }
                  },
                  "required": [
                    "reactions"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Retirer une réaction emoji (idempotent, emoji en query)",
        "tags": [
          "chat"
        ],
        "parameters": [
          {
            "name": "emoji",
            "in": "query",
            "required": true,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "minLength": 1,
              "maxLength": 16
            }
          }
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Réactions à jour du message",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "reactions": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        }
                      }
                    }
                  },
                  "required": [
                    "reactions"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/devices": {
      "post": {
        "summary": "Enregistrer l'appareil pour le push (idempotent par token)",
        "description": "Contexte utilisateur uniquement. Sans adaptateur push configuré sur l'instance, l'enregistrement reste accepté mais aucun envoi n'a lieu (ADR-108).",
        "tags": [
          "mobile"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "platform": {
                    "type": "string",
                    "enum": [
                      "ios",
                      "android"
                    ]
                  },
                  "pushToken": {
                    "type": "string"
                  }
                },
                "required": [
                  "platform",
                  "pushToken"
                ]
              }
            }
          }
        },
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Appareil enregistré",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "registered": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "registered"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Révoquer un token d'appareil (logout) - no-op si inconnu",
        "tags": [
          "mobile"
        ],
        "parameters": [
          {
            "name": "pushToken",
            "in": "query",
            "required": true,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Token révoqué",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "revoked": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "revoked"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/sync/pull": {
      "get": {
        "summary": "Pull incrémental du briefcase (contexte utilisateur uniquement)",
        "description": "Sans curseur : amorçage complet du briefcase (spec offline-briefcase, filtré record-access + permissions objet). Avec curseur : créations/modifications, retraits de visibilité (removals) et suppressions physiques (tombstones) depuis le dernier pull. Reprise exacte après coupure (le curseur porte la position). Réservé aux sessions utilisateur (§2bis).",
        "tags": [
          "sync"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque du pull précédent",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Changes max par page (défaut 200)",
              "type": "integer",
              "minimum": 1,
              "maximum": 500
            }
          }
        ],
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de synchronisation",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "changes": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "enum": [
                              "cycle",
                              "businessUnit",
                              "user",
                              "product",
                              "company",
                              "contact",
                              "affiliation",
                              "quote",
                              "salesActivity",
                              "comment",
                              "notification"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "version": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "sync_version serveur (T-695) - la base des mutations"
                          },
                          "updatedAt": {
                            "type": "string"
                          },
                          "data": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {},
                            "description": "Formes API v1 de l'objet"
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "version",
                          "updatedAt",
                          "data"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "removals": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "enum": [
                              "cycle",
                              "businessUnit",
                              "user",
                              "product",
                              "company",
                              "contact",
                              "affiliation",
                              "quote",
                              "salesActivity",
                              "comment",
                              "notification"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          }
                        },
                        "required": [
                          "object",
                          "id"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Sortis du briefcase (visibilité, corbeille, réattribution) - à purger localement"
                    },
                    "tombstones": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "enum": [
                              "cycle",
                              "businessUnit",
                              "user",
                              "product",
                              "company",
                              "contact",
                              "affiliation",
                              "quote",
                              "salesActivity",
                              "comment",
                              "notification"
                            ]
                          },
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "deletedAt": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "deletedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "cursor": {
                      "type": "string"
                    },
                    "hasMore": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "changes",
                    "removals",
                    "tombstones",
                    "cursor",
                    "hasMore"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/sync/push": {
      "post": {
        "summary": "Push d'un batch ordonné de mutations idempotentes",
        "description": "Mutations V1 : salesActivity.create/update/transition (done), comment.create, notification.markRead. Chaque mutation porte un id client (journal sync_mutation : rejouer un batch déjà traité est un no-op à réponse identique) ; les updates portent baseVersion - version périmée = fusion par champ T-697 (`merged`, même champ = LWW tracé dans l'historique + perdant notifié ; champ critique = `conflict` strict), refus métier = `rejected` motivé, jamais silencieux. Réservé aux sessions utilisateur (§2bis).",
        "tags": [
          "sync"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "mutations": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "object": {
                          "type": "string",
                          "enum": [
                            "salesActivity",
                            "comment",
                            "notification"
                          ]
                        },
                        "op": {
                          "type": "string",
                          "enum": [
                            "create",
                            "update",
                            "markRead",
                            "transition"
                          ]
                        },
                        "recordId": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        "baseVersion": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 9007199254740991
                        },
                        "data": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {}
                        }
                      },
                      "required": [
                        "id",
                        "object",
                        "op"
                      ]
                    }
                  }
                },
                "required": [
                  "mutations"
                ]
              }
            }
          }
        },
        "security": [
          {
            "oauth2": []
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Réponse par mutation, dans l'ordre du batch",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "applied",
                              "merged",
                              "conflict",
                              "rejected"
                            ]
                          },
                          "recordId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "serverVersion": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "reason": {
                            "type": "string"
                          },
                          "overwrittenFields": {
                            "description": "T-697 : libellés des champs écrasés par une fusion LWW (tracés + notifiés)",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "criticalFields": {
                            "description": "T-697 : champs en résolution stricte à l'origine d'un conflict",
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        },
                        "required": [
                          "id",
                          "status"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "results"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/exports": {
      "get": {
        "summary": "Lister les exports de l'organisation (50 au plus, du plus récent au plus ancien)",
        "tags": [
          "Exports"
        ],
        "security": [
          {
            "oauth2": [
              "exports:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Exports, sans curseur (liste bornée)",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "done",
                              "failed"
                            ]
                          },
                          "trigger": {
                            "type": "string",
                            "enum": [
                              "scheduled",
                              "manual"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "finishedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "expiresAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Après cette date, l'archive n'est plus servie (404)"
                          },
                          "bytes": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "sha256": {
                            "description": "Empreinte SHA-256 de l'archive, aussi renvoyée en ETag au téléchargement",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "available": {
                            "type": "boolean",
                            "description": "Réussie, non expirée, présente : téléchargeable"
                          },
                          "url": {
                            "description": "URL de téléchargement (jeton d'app connectée, scope exports:read)",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "error": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "status",
                          "trigger",
                          "createdAt",
                          "finishedAt",
                          "expiresAt",
                          "bytes",
                          "sha256",
                          "available",
                          "url",
                          "error"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/exports/latest": {
      "get": {
        "summary": "Le dernier export réussi",
        "description": "404 tant qu'aucun export n'a abouti. L'événement webhook `export.ready` annonce chaque nouvel export.",
        "tags": [
          "Exports"
        ],
        "security": [
          {
            "oauth2": [
              "exports:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Le dernier export réussi",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "done",
                        "failed"
                      ]
                    },
                    "trigger": {
                      "type": "string",
                      "enum": [
                        "scheduled",
                        "manual"
                      ]
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "finishedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "expiresAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Après cette date, l'archive n'est plus servie (404)"
                    },
                    "bytes": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "sha256": {
                      "description": "Empreinte SHA-256 de l'archive, aussi renvoyée en ETag au téléchargement",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "available": {
                      "type": "boolean",
                      "description": "Réussie, non expirée, présente : téléchargeable"
                    },
                    "url": {
                      "description": "URL de téléchargement (jeton d'app connectée, scope exports:read)",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "error": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "status",
                    "trigger",
                    "createdAt",
                    "finishedAt",
                    "expiresAt",
                    "bytes",
                    "sha256",
                    "available",
                    "url",
                    "error"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/exports/{id}/download": {
      "get": {
        "summary": "Télécharger l'archive (tar.gz : tables en JSONL, fichiers, manifeste)",
        "description": "Flux `application/gzip`, `Content-Length` et `ETag` (SHA-256). 404 pour un export en échec, expiré ou dont l'archive a été purgée.",
        "tags": [
          "Exports"
        ],
        "security": [
          {
            "oauth2": [
              "exports:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "L'archive"
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/campaigns": {
      "get": {
        "summary": "Lister les campagnes (hors archivées)",
        "tags": [
          "Marketing"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "draft",
                "scheduled",
                "sending",
                "paused",
                "sent",
                "cancelled"
              ]
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "email",
                "invitation",
                "container"
              ]
            }
          },
          {
            "name": "archived",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "true = archivées comprises",
              "type": "boolean"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "marketing:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de campagnes",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "email",
                              "invitation",
                              "container"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "scheduled",
                              "sending",
                              "paused",
                              "sent",
                              "cancelled"
                            ]
                          },
                          "pauseReason": {
                            "description": "user, bounces, quota, transport, domain, provider, health ou suspended (organisation suspendue)",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "subject": {
                            "type": "string"
                          },
                          "segmentId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "templateId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "senderMode": {
                            "type": "string",
                            "enum": [
                              "org",
                              "owner"
                            ]
                          },
                          "businessUnitId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "ownerId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "scheduledAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "startedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "finishedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "archivedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "occasion": {
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "title": {
                                    "type": "string"
                                  },
                                  "startsAt": {
                                    "type": "string",
                                    "description": "ISO 8601 avec décalage (heure murale de l'organisation)"
                                  },
                                  "location": {
                                    "type": "string"
                                  },
                                  "address": {
                                    "type": "string"
                                  },
                                  "capacity": {
                                    "anyOf": [
                                      {
                                        "type": "integer",
                                        "minimum": -9007199254740991,
                                        "maximum": 9007199254740991
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "replyBy": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "guestsMax": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "companyQuota": {
                                    "anyOf": [
                                      {
                                        "type": "integer",
                                        "minimum": -9007199254740991,
                                        "maximum": 9007199254740991
                                      },
                                      {
                                        "type": "null"
                                      }
                                    ]
                                  },
                                  "eventId": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "reminders": {
                                    "type": "boolean"
                                  }
                                },
                                "required": [
                                  "title",
                                  "startsAt",
                                  "location",
                                  "address",
                                  "capacity",
                                  "replyBy",
                                  "guestsMax",
                                  "companyQuota",
                                  "eventId",
                                  "reminders"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "parentId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#450 : la campagne conteneur de cet envoi, nulle pour une campagne autonome ou un conteneur"
                          },
                          "costCents": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#450 : le coût saisi d'un conteneur, en centimes ; nul sans coût"
                          },
                          "topicId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "#734 : la thématique de l'envoi (Réglages › Marketing › Consentement), nulle sans thématique"
                          },
                          "counts": {
                            "type": "object",
                            "properties": {
                              "queued": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "sent": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "delivered": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "bounced": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "complained": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "failed": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "skipped": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991,
                                "description": "Total des destinataires écartés (opposition, suppression, doublon…)"
                              },
                              "clicks": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991,
                                "description": "Clics agrégés : jamais par contact par l'API"
                              },
                              "opens": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991,
                                "description": "Ouvertures des seuls contacts consentant à la mesure"
                              },
                              "unsubscribes": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "replies": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              }
                            },
                            "required": [
                              "queued",
                              "sent",
                              "delivered",
                              "bounced",
                              "complained",
                              "failed",
                              "skipped",
                              "clicks",
                              "opens",
                              "unsubscribes",
                              "replies"
                            ],
                            "additionalProperties": false
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "kind",
                          "status",
                          "pauseReason",
                          "subject",
                          "segmentId",
                          "templateId",
                          "senderMode",
                          "businessUnitId",
                          "ownerId",
                          "scheduledAt",
                          "startedAt",
                          "finishedAt",
                          "archivedAt",
                          "occasion",
                          "parentId",
                          "costCents",
                          "topicId",
                          "counts",
                          "createdAt",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Créer une campagne en brouillon",
        "description": "Un brouillon, jamais plus : l'envoi est un geste à part (`POST /campaigns/{id}/send`). Segment et modèle doivent exister et ne pas être archivés (422).",
        "tags": [
          "Marketing"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "subject": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "kind": {
                    "description": "Défaut : email",
                    "type": "string",
                    "enum": [
                      "email",
                      "invitation",
                      "container"
                    ]
                  },
                  "segmentId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "templateId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "senderMode": {
                    "type": "string",
                    "enum": [
                      "org",
                      "owner"
                    ]
                  },
                  "senderUserId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "businessUnitId": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "ownerId": {
                    "description": "Défaut : l'utilisateur d'intégration du jeton",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "text": {
                    "description": "Contenu brut sans modèle (sinon le modèle rend le message)",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 20000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "name",
                  "subject"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "marketing:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Campagne créée (brouillon)",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "email",
                        "invitation",
                        "container"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "scheduled",
                        "sending",
                        "paused",
                        "sent",
                        "cancelled"
                      ]
                    },
                    "pauseReason": {
                      "description": "user, bounces, quota, transport, domain, provider, health ou suspended (organisation suspendue)",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subject": {
                      "type": "string"
                    },
                    "segmentId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "templateId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "senderMode": {
                      "type": "string",
                      "enum": [
                        "org",
                        "owner"
                      ]
                    },
                    "businessUnitId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "ownerId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "scheduledAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "startedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "finishedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "archivedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "occasion": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "title": {
                              "type": "string"
                            },
                            "startsAt": {
                              "type": "string",
                              "description": "ISO 8601 avec décalage (heure murale de l'organisation)"
                            },
                            "location": {
                              "type": "string"
                            },
                            "address": {
                              "type": "string"
                            },
                            "capacity": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "replyBy": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "guestsMax": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "companyQuota": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "eventId": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "reminders": {
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "title",
                            "startsAt",
                            "location",
                            "address",
                            "capacity",
                            "replyBy",
                            "guestsMax",
                            "companyQuota",
                            "eventId",
                            "reminders"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "parentId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#450 : la campagne conteneur de cet envoi, nulle pour une campagne autonome ou un conteneur"
                    },
                    "costCents": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#450 : le coût saisi d'un conteneur, en centimes ; nul sans coût"
                    },
                    "topicId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#734 : la thématique de l'envoi (Réglages › Marketing › Consentement), nulle sans thématique"
                    },
                    "counts": {
                      "type": "object",
                      "properties": {
                        "queued": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "sent": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "delivered": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "bounced": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "complained": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "failed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "skipped": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Total des destinataires écartés (opposition, suppression, doublon…)"
                        },
                        "clicks": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Clics agrégés : jamais par contact par l'API"
                        },
                        "opens": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Ouvertures des seuls contacts consentant à la mesure"
                        },
                        "unsubscribes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "replies": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "queued",
                        "sent",
                        "delivered",
                        "bounced",
                        "complained",
                        "failed",
                        "skipped",
                        "clicks",
                        "opens",
                        "unsubscribes",
                        "replies"
                      ],
                      "additionalProperties": false
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "kind",
                    "status",
                    "pauseReason",
                    "subject",
                    "segmentId",
                    "templateId",
                    "senderMode",
                    "businessUnitId",
                    "ownerId",
                    "scheduledAt",
                    "startedAt",
                    "finishedAt",
                    "archivedAt",
                    "occasion",
                    "parentId",
                    "costCents",
                    "topicId",
                    "counts",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/campaigns/{id}": {
      "get": {
        "summary": "Lire une campagne : compteurs agrégés, liens suivis, invitations",
        "tags": [
          "Marketing"
        ],
        "security": [
          {
            "oauth2": [
              "marketing:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Campagne",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "email",
                        "invitation",
                        "container"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "scheduled",
                        "sending",
                        "paused",
                        "sent",
                        "cancelled"
                      ]
                    },
                    "pauseReason": {
                      "description": "user, bounces, quota, transport, domain, provider, health ou suspended (organisation suspendue)",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "subject": {
                      "type": "string"
                    },
                    "segmentId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "templateId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "senderMode": {
                      "type": "string",
                      "enum": [
                        "org",
                        "owner"
                      ]
                    },
                    "businessUnitId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "ownerId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "scheduledAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "startedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "finishedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "archivedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "occasion": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "title": {
                              "type": "string"
                            },
                            "startsAt": {
                              "type": "string",
                              "description": "ISO 8601 avec décalage (heure murale de l'organisation)"
                            },
                            "location": {
                              "type": "string"
                            },
                            "address": {
                              "type": "string"
                            },
                            "capacity": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "replyBy": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "guestsMax": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "companyQuota": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "eventId": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "reminders": {
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "title",
                            "startsAt",
                            "location",
                            "address",
                            "capacity",
                            "replyBy",
                            "guestsMax",
                            "companyQuota",
                            "eventId",
                            "reminders"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "parentId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#450 : la campagne conteneur de cet envoi, nulle pour une campagne autonome ou un conteneur"
                    },
                    "costCents": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#450 : le coût saisi d'un conteneur, en centimes ; nul sans coût"
                    },
                    "topicId": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "#734 : la thématique de l'envoi (Réglages › Marketing › Consentement), nulle sans thématique"
                    },
                    "counts": {
                      "type": "object",
                      "properties": {
                        "queued": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "sent": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "delivered": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "bounced": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "complained": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "failed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "skipped": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Total des destinataires écartés (opposition, suppression, doublon…)"
                        },
                        "clicks": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Clics agrégés : jamais par contact par l'API"
                        },
                        "opens": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Ouvertures des seuls contacts consentant à la mesure"
                        },
                        "unsubscribes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "replies": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "queued",
                        "sent",
                        "delivered",
                        "bounced",
                        "complained",
                        "failed",
                        "skipped",
                        "clicks",
                        "opens",
                        "unsubscribes",
                        "replies"
                      ],
                      "additionalProperties": false
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "segmentName": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "templateName": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "links": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "url": {
                            "type": "string"
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "clickCount": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "uniqueClickCount": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "id",
                          "url",
                          "label",
                          "clickCount",
                          "uniqueClickCount"
                        ],
                        "additionalProperties": false
                      },
                      "description": "Liens suivis et clics agrégés (T-1551)"
                    },
                    "invitations": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "invited": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "registered": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "declined": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "waitlisted": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "attended": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "noShow": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "placesLeft": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            }
                          },
                          "required": [
                            "invited",
                            "registered",
                            "declined",
                            "waitlisted",
                            "attended",
                            "noShow",
                            "placesLeft"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Compteurs d'une campagne d'invitation, null pour un email"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "kind",
                    "status",
                    "pauseReason",
                    "subject",
                    "segmentId",
                    "templateId",
                    "senderMode",
                    "businessUnitId",
                    "ownerId",
                    "scheduledAt",
                    "startedAt",
                    "finishedAt",
                    "archivedAt",
                    "occasion",
                    "parentId",
                    "costCents",
                    "topicId",
                    "counts",
                    "createdAt",
                    "updatedAt",
                    "segmentName",
                    "templateName",
                    "links",
                    "invitations"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/campaigns/{id}/deliveries": {
      "get": {
        "summary": "Les destinataires d'une campagne et le sort de chaque envoi",
        "description": "Liste bornée (200 au plus), filtrable par statut ; aucune donnée de mesure nominative (clics, ouvertures) : les compteurs de la campagne sont agrégés.",
        "tags": [
          "Marketing"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "queued",
                "sent",
                "delivered",
                "bounced",
                "complained",
                "failed",
                "skipped"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Destinataires - défaut 50, max 200 (liste bornée, pas de curseur)",
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "marketing:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Destinataires",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "contactId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "email": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "queued",
                              "sent",
                              "delivered",
                              "bounced",
                              "complained",
                              "failed",
                              "skipped"
                            ]
                          },
                          "skipReason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "error": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "sentAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "deliveredAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "bouncedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "contactId",
                          "email",
                          "status",
                          "skipReason",
                          "error",
                          "sentAt",
                          "deliveredAt",
                          "bouncedAt"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/campaigns/{id}/send": {
      "post": {
        "summary": "Envoyer une campagne maintenant",
        "description": "Mêmes contrôles nommés que le bouton de l'UI : domaine d'envoi vérifié, transport, modèle, objet, audience, quota du mois. Un contrôle rouge répond 409 `campaign-not-ready` en les nommant, rien n'est enfilé. Un jeton au seul scope `marketing:read` reçoit 403 avec le scope manquant. L'envoi est direct et tracé avec l'utilisateur d'intégration du jeton ; par MCP (client IA), `send_campaign` est toujours sous approbation (ADR-168).",
        "tags": [
          "Marketing"
        ],
        "security": [
          {
            "oauth2": [
              "marketing:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Campagne en cours d'envoi",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "sending",
                        "scheduled"
                      ]
                    },
                    "queued": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "skipped": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "status",
                    "queued",
                    "skipped"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/campaigns/{id}/invitations": {
      "get": {
        "summary": "Les invités d'une campagne d'invitation et leur réponse",
        "tags": [
          "Marketing"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "string",
              "enum": [
                "invited",
                "registered",
                "declined",
                "waitlisted",
                "attended",
                "no_show",
                "cancelled"
              ]
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "marketing:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Invités",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "campaignId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "contactId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "invited",
                              "registered",
                              "declined",
                              "waitlisted",
                              "attended",
                              "no_show",
                              "cancelled"
                            ]
                          },
                          "guests": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "guestNames": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "note": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "respondedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "checkedInAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "campaignId",
                          "contactId",
                          "status",
                          "guests",
                          "guestNames",
                          "note",
                          "respondedAt",
                          "checkedInAt"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/campaigns/{id}/invitations/{contactId}": {
      "put": {
        "summary": "Poser la réponse d'un invité ou l'émarger",
        "description": "`status` pour une réponse reçue par un autre canal ou une annulation ; `attended` pour l'émargement (présent) ou son annulation. L'invité doit exister (404 sinon).",
        "tags": [
          "Marketing"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "status": {
                    "description": "Réponse reçue par un autre canal, ou annulation",
                    "type": "string",
                    "enum": [
                      "registered",
                      "declined",
                      "cancelled"
                    ]
                  },
                  "attended": {
                    "description": "true = émarger (présent), false = annuler l'émargement",
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "marketing:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Invitation",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "campaignId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "contactId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "invited",
                        "registered",
                        "declined",
                        "waitlisted",
                        "attended",
                        "no_show",
                        "cancelled"
                      ]
                    },
                    "guests": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "guestNames": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "note": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "respondedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "checkedInAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "campaignId",
                    "contactId",
                    "status",
                    "guests",
                    "guestNames",
                    "note",
                    "respondedAt",
                    "checkedInAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/segments": {
      "get": {
        "summary": "Lister les segments (hors archivés)",
        "tags": [
          "Marketing"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          },
          {
            "name": "archived",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "boolean"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "marketing:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de segments",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "dynamic",
                              "static"
                            ]
                          },
                          "object": {
                            "type": "string",
                            "enum": [
                              "contact",
                              "company"
                            ]
                          },
                          "memberCount": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "computedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "definition": {
                            "type": "object",
                            "properties": {},
                            "additionalProperties": {},
                            "description": "Définition (contactable, all, anyGroups) : le même schéma que l'écran Segments"
                          },
                          "archivedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "kind",
                          "object",
                          "memberCount",
                          "computedAt",
                          "definition",
                          "archivedAt",
                          "createdAt",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Créer un segment",
        "description": "Dynamique : la définition est validée et compilée par le même code que l'écran Segments (422 sur un champ inconnu). Quota `segments` du plan (429).",
        "tags": [
          "Marketing"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "dynamic",
                      "static"
                    ]
                  },
                  "object": {
                    "description": "Défaut : contact",
                    "type": "string",
                    "enum": [
                      "contact",
                      "company"
                    ]
                  },
                  "definition": {
                    "description": "Dynamique : critères validés et compilés comme dans l'UI (422 sinon)",
                    "type": "object",
                    "properties": {
                      "contactable": {
                        "default": true,
                        "type": "boolean"
                      },
                      "all": {
                        "default": [],
                        "maxItems": 20,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "object": {
                              "type": "string",
                              "enum": [
                                "contact",
                                "company",
                                "affiliation",
                                "quote",
                                "order",
                                "contract",
                                "invoice",
                                "sales_activity",
                                "marketing_consent",
                                "marketing_delivery",
                                "event_invitation",
                                "marketing_touch",
                                "tag"
                              ]
                            },
                            "field": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 64
                            },
                            "op": {
                              "type": "string",
                              "enum": [
                                "is",
                                "is_not",
                                "contains",
                                "gt",
                                "lt",
                                "between",
                                "in",
                                "empty",
                                "not_empty",
                                "within_days",
                                "older_than_days"
                              ]
                            },
                            "value": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "maxLength": 200
                                },
                                {
                                  "type": "number"
                                },
                                {
                                  "type": "boolean"
                                },
                                {
                                  "maxItems": 50,
                                  "type": "array",
                                  "items": {
                                    "type": "string",
                                    "maxLength": 200
                                  }
                                }
                              ]
                            },
                            "not": {
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "object",
                            "field",
                            "op"
                          ]
                        }
                      },
                      "anyGroups": {
                        "default": [],
                        "maxItems": 5,
                        "type": "array",
                        "items": {
                          "minItems": 1,
                          "maxItems": 10,
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "object": {
                                "type": "string",
                                "enum": [
                                  "contact",
                                  "company",
                                  "affiliation",
                                  "quote",
                                  "order",
                                  "contract",
                                  "invoice",
                                  "sales_activity",
                                  "marketing_consent",
                                  "marketing_delivery",
                                  "event_invitation",
                                  "marketing_touch",
                                  "tag"
                                ]
                              },
                              "field": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 64
                              },
                              "op": {
                                "type": "string",
                                "enum": [
                                  "is",
                                  "is_not",
                                  "contains",
                                  "gt",
                                  "lt",
                                  "between",
                                  "in",
                                  "empty",
                                  "not_empty",
                                  "within_days",
                                  "older_than_days"
                                ]
                              },
                              "value": {
                                "anyOf": [
                                  {
                                    "type": "string",
                                    "maxLength": 200
                                  },
                                  {
                                    "type": "number"
                                  },
                                  {
                                    "type": "boolean"
                                  },
                                  {
                                    "maxItems": 50,
                                    "type": "array",
                                    "items": {
                                      "type": "string",
                                      "maxLength": 200
                                    }
                                  }
                                ]
                              },
                              "not": {
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "object",
                              "field",
                              "op"
                            ]
                          }
                        }
                      }
                    }
                  }
                },
                "required": [
                  "name",
                  "kind"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "marketing:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Segment créé",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "dynamic",
                        "static"
                      ]
                    },
                    "object": {
                      "type": "string",
                      "enum": [
                        "contact",
                        "company"
                      ]
                    },
                    "memberCount": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "computedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "definition": {
                      "type": "object",
                      "properties": {},
                      "additionalProperties": {},
                      "description": "Définition (contactable, all, anyGroups) : le même schéma que l'écran Segments"
                    },
                    "archivedAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "kind",
                    "object",
                    "memberCount",
                    "computedAt",
                    "definition",
                    "archivedAt",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/segments/{id}/members": {
      "get": {
        "summary": "Les membres d'un segment (contacts), paginés",
        "description": "Statique : les membres figés ; dynamique : compilé à l'instant. Les contacts hors visibilité du jeton (périmètre) ne sont pas rendus.",
        "tags": [
          "Marketing"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "marketing:read",
              "contacts:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de contacts",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "salutation": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "mr",
                                  "mrs"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "firstName": {
                            "type": "string"
                          },
                          "lastName": {
                            "type": "string"
                          },
                          "email": {
                            "description": "Adresse PRINCIPALE du contact (T-809 : multi-emails - la fiche peut porter d'autres adresses, ce champ reste le miroir de la principale).",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "phone": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "title": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "avatar": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "linkedin": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "birthday": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "Date de naissance « YYYY-MM-DD », null = inconnue"
                          },
                          "timeZone": {
                            "description": "Fuseau IANA explicitement connu ; null = inconnu, jamais déduit du pays",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "addressLine1": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "addressLine2": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "postalCode": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "city": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "country": {
                            "description": "Code pays ISO 3166-1 alpha-2",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "customFields": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {
                              "type": [
                                "string",
                                "number",
                                "boolean"
                              ]
                            }
                          },
                          "doNotContact": {
                            "type": "boolean",
                            "description": "Opposition RGPD : le contact ne doit pas être sollicité (E183 #514, badge « Ne pas contacter » à côté de l'email)"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "externalRefs": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "source": {
                                  "type": "string",
                                  "description": "Système source (minuscules) - `tacto`, `erp`…"
                                },
                                "externalId": {
                                  "type": "string"
                                },
                                "sourceUpdatedAt": {
                                  "anyOf": [
                                    {
                                      "type": "string",
                                      "format": "date-time",
                                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ],
                                  "description": "Dernière modification connue dans la source (curseur du delta), null si inconnue"
                                }
                              },
                              "required": [
                                "source",
                                "externalId",
                                "sourceUpdatedAt"
                              ],
                              "additionalProperties": false
                            },
                            "description": "Identifiants de cet objet dans les systèmes tiers (external_ref, ADR-138 D1, ADR-156 D6)"
                          }
                        },
                        "required": [
                          "id",
                          "salutation",
                          "firstName",
                          "lastName",
                          "email",
                          "phone",
                          "title",
                          "avatar",
                          "linkedin",
                          "birthday",
                          "timeZone",
                          "addressLine1",
                          "addressLine2",
                          "postalCode",
                          "city",
                          "country",
                          "customFields",
                          "doNotContact",
                          "createdAt",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/tags": {
      "get": {
        "summary": "Lister les étiquettes",
        "tags": [
          "Marketing"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "marketing:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page d'étiquettes",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "color",
                          "createdAt",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Créer une étiquette (ou retrouver celle du même nom)",
        "description": "Unique par organisation, insensible à la casse et aux accents ; couleur parmi cinq teintes de la marque ; quota `tags` du plan (429).",
        "tags": [
          "Marketing"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "color": {
                    "type": "string",
                    "enum": [
                      "brand",
                      "comp",
                      "blend",
                      "muted",
                      "deep"
                    ]
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "marketing:write"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "201": {
            "description": "Étiquette",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "color": {
                      "type": "string"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "color",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/contacts/{id}/tags": {
      "post": {
        "summary": "Poser des étiquettes sur un contact",
        "description": "`tagIds` existantes et/ou `names` (créées si absentes, quota du plan). Idempotent : une étiquette déjà posée ne compte pas.",
        "tags": [
          "Marketing"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "tagIds": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "names": {
                    "description": "Créées si absentes (quota du plan)",
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 40
                    }
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "marketing:write",
              "contacts:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Étiquettes posées",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "added": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "color": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "color",
                          "createdAt",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "added",
                    "tags"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/contacts/{id}/marketing-consent": {
      "get": {
        "summary": "Le consentement marketing d'un contact (canal email)",
        "tags": [
          "Marketing"
        ],
        "security": [
          {
            "oauth2": [
              "marketing:read",
              "contacts:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Consentement",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "contactId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "channel": {
                      "type": "string",
                      "const": "email"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "opted_in",
                        "opt_out_allowed",
                        "opted_out",
                        "blocked"
                      ]
                    },
                    "basis": {
                      "type": "string",
                      "enum": [
                        "consent",
                        "legitimate_interest"
                      ]
                    },
                    "source": {
                      "type": "string"
                    },
                    "proof": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "text": {
                              "type": "string"
                            },
                            "version": {
                              "type": "string"
                            },
                            "at": {
                              "type": "string"
                            },
                            "note": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "text",
                            "version",
                            "at"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "measureConsentAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "optedOutAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "contactId",
                    "channel",
                    "status",
                    "basis",
                    "source",
                    "proof",
                    "measureConsentAt",
                    "optedOutAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Écrire le consentement marketing d'un contact, preuve obligatoire",
        "description": "`opted_in` exige la preuve (texte, version, note : où le consentement a été recueilli) ; refusé 409 sur un contact en opposition ou sur la liste de suppression. `opted_out` désinscrit. Source journalisée « preuve saisie », acteur = l'utilisateur d'intégration. `measure` pose ou retire le consentement à la mesure nominative.",
        "tags": [
          "Marketing"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "opted_in",
                      "opted_out"
                    ]
                  },
                  "proof": {
                    "type": "object",
                    "properties": {
                      "text": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 2000,
                        "description": "Texte de consentement montré à la personne"
                      },
                      "version": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 40
                      },
                      "at": {
                        "description": "Instant du geste de la personne (défaut : maintenant)",
                        "anyOf": [
                          {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          {
                            "type": "string",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z))$"
                          }
                        ]
                      },
                      "note": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 500,
                        "description": "Où et comment le consentement a été recueilli (obligatoire)"
                      }
                    },
                    "required": [
                      "text",
                      "version",
                      "note"
                    ],
                    "additionalProperties": false
                  },
                  "measure": {
                    "description": "Consentement à la mesure nominative des clics et ouvertures",
                    "type": "boolean"
                  }
                },
                "required": [
                  "status",
                  "proof"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "oauth2": [
              "marketing:write",
              "contacts:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Consentement après écriture",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "contactId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "channel": {
                      "type": "string",
                      "const": "email"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "opted_in",
                        "opt_out_allowed",
                        "opted_out",
                        "blocked"
                      ]
                    },
                    "basis": {
                      "type": "string",
                      "enum": [
                        "consent",
                        "legitimate_interest"
                      ]
                    },
                    "source": {
                      "type": "string"
                    },
                    "proof": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "text": {
                              "type": "string"
                            },
                            "version": {
                              "type": "string"
                            },
                            "at": {
                              "type": "string"
                            },
                            "note": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "text",
                            "version",
                            "at"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "measureConsentAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "optedOutAt": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                    }
                  },
                  "required": [
                    "contactId",
                    "channel",
                    "status",
                    "basis",
                    "source",
                    "proof",
                    "measureConsentAt",
                    "optedOutAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/forms": {
      "get": {
        "summary": "Lister les formulaires (hors archivés)",
        "tags": [
          "Marketing"
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Curseur opaque de la page précédente",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Taille de page - défaut 50, max 200 (clampé)",
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "ISO 8601 - objets modifiés depuis (inclusif), le filtre des syncs incrémentales",
              "type": "string"
            }
          },
          {
            "name": "archived",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "type": "boolean"
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "marketing:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Page de formulaires",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "slug": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "published",
                              "archived"
                            ]
                          },
                          "doubleOptIn": {
                            "type": "boolean"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "slug",
                          "status",
                          "doubleOptIn",
                          "createdAt",
                          "updatedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/forms/{id}/submissions": {
      "get": {
        "summary": "Les soumissions d'un formulaire",
        "description": "Liste bornée (200 au plus), les plus récentes d'abord ; les champs saisis ne sortent pas (la fiche contact les porte).",
        "tags": [
          "Marketing"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "description": "Soumissions - défaut 50, max 200 (liste bornée, pas de curseur)",
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          }
        ],
        "security": [
          {
            "oauth2": [
              "marketing:read"
            ]
          },
          {
            "userSession": []
          }
        ],
        "responses": {
          "200": {
            "description": "Soumissions",
            "content": {
              "application/json": {
                "schema": {
                  "$schema": "https://json-schema.org/draft/2020-12/schema",
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "formId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "status": {
                            "type": "string"
                          },
                          "receivedAt": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                          },
                          "confirmedAt": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "date-time",
                                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "contactId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "companyId": {
                            "anyOf": [
                              {
                                "type": "string",
                                "format": "uuid",
                                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "note": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "formId",
                          "status",
                          "receivedAt",
                          "confirmedAt",
                          "contactId",
                          "companyId",
                          "note"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Erreur - enveloppe problem+json (RFC 9457)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "oauth2": {
        "type": "oauth2",
        "description": "Grant client_credentials - token Bearer opaque, TTL 1 h.",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "/api/v1/oauth/token",
            "scopes": {
              "referentials:read": "Référentiels - lecture (cycles, entités, secteurs, users)",
              "referentials:write": "Référentiels - écriture (identité légale & bancaire des entités)",
              "companies:read": "Sociétés - lecture (+ affiliations)",
              "companies:write": "Sociétés - écriture (+ affiliations)",
              "contacts:read": "Contacts - lecture (+ affiliations)",
              "contacts:write": "Contacts - écriture (+ affiliations)",
              "products:read": "Produits - lecture (+ tarifs)",
              "products:write": "Produits - écriture (+ tarifs)",
              "quotes:read": "Devis - lecture",
              "quotes:write": "Devis - écriture (CRUD + transitions)",
              "invoices:read": "Factures - lecture (avoirs, échéances)",
              "invoices:write": "Factures - écriture (avoirs, échéances)",
              "requests:read": "Requêtes - lecture",
              "requests:write": "Requêtes - écriture (CRUD + transitions)",
              "sales_activities:read": "Activités commerciales - lecture",
              "sales_activities:write": "Activités commerciales - écriture (CRUD + transitions)",
              "signatures:read": "Signature électronique - lecture des enveloppes et du dossier de preuve",
              "signatures:write": "Signature électronique - création, relance, annulation d'enveloppes",
              "webhooks:manage": "Webhooks sortants - gestion des abonnements",
              "exports:read": "Exports de l'organisation - liste et téléchargement des archives",
              "users:read": "Utilisateurs - lecture d'administration (comptes, profils, état, invitation en attente)",
              "users:write": "Utilisateurs - inviter, modifier le profil, désactiver, réactiver, renvoyer l'invitation (toujours soumis à l'approbation d'un administrateur)",
              "marketing:read": "Marketing - lecture (campagnes, segments, étiquettes, consentement, formulaires, invitations)",
              "marketing:write": "Marketing - écriture (brouillons, segments, étiquettes, consentement prouvé, envoi d'une campagne)",
              "documents:read": "Documents des fiches - liste et lien de téléchargement signé (15 minutes)",
              "settings:write": "Réglages - objectifs individuels des commerciaux (lecture et écriture)"
            }
          }
        }
      },
      "userSession": {
        "type": "http",
        "scheme": "bearer",
        "description": "Session utilisateur Better Auth en Bearer (T-685, docs/08-API §2bis) - obtenue à la connexion (header set-auth-token). Les scopes publiés ne s'appliquent pas : les droits sont les permissions objet et la visibilité de l'utilisateur, à l'identique de l'UI web."
      }
    },
    "schemas": {
      "Problem": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "URN stable urn:cercla:problem:<slug> - la clé à tester"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "detail": {
            "type": "string"
          },
          "instance": {
            "type": "string",
            "description": "Id de corrélation des logs serveur"
          },
          "errors": {
            "description": "Détail par champ - uniquement sur les erreurs de validation",
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              },
              "required": [
                "path",
                "message"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "instance"
        ],
        "additionalProperties": false
      }
    }
  },
  "security": [
    {
      "oauth2": []
    },
    {
      "userSession": []
    }
  ]
}
