{
  "openapi": "3.1.0",
  "info": {
    "title": "API Docoki",
    "version": "1.0.0",
    "description": "Déposez vos documents, estimez leur consommation, lancez vos traitements et téléchargez vos résultats. Consultez /v1/capabilities pour connaître les opérations disponibles et leurs limites.",
    "contact": {
      "name": "Équipe Docoki"
    }
  },
  "servers": [
    {
      "url": "/",
      "description": "Adresse de votre environnement Docoki ; utilisez HTTPS pour vos intégrations."
    }
  ],
  "security": [
    {
      "apiKeyAuth": []
    },
    {
      "sessionAuth": []
    }
  ],
  "tags": [
    {
      "name": "Catalogue",
      "description": "Utiliser les fonctions de catalogue."
    },
    {
      "name": "Espaces",
      "description": "Utiliser les fonctions de espaces."
    },
    {
      "name": "Fichiers",
      "description": "Utiliser les fonctions de fichiers."
    },
    {
      "name": "Traitements",
      "description": "Utiliser les fonctions de traitements."
    },
    {
      "name": "Secrets",
      "description": "Utiliser les fonctions de secrets."
    },
    {
      "name": "Consommation",
      "description": "Utiliser les fonctions de consommation."
    },
    {
      "name": "Préréglages",
      "description": "Utiliser les fonctions de préréglages."
    },
    {
      "name": "Administration développeur",
      "description": "Utiliser les fonctions de administration développeur."
    },
    {
      "name": "Notifications",
      "description": "Utiliser les fonctions de notifications."
    }
  ],
  "paths": {
    "/v1/capabilities": {
      "get": {
        "operationId": "getCapabilities",
        "summary": "Lire les capacités publiées",
        "tags": [
          "Catalogue"
        ],
        "description": "Lire les capacités publiées. Catalogue public ; le devis applique les limites du compte.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Lire les capacités publiées",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Capabilities"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [],
        "security": []
      }
    },
    "/v1/workspaces": {
      "get": {
        "operationId": "listWorkspaces",
        "summary": "Lister mes espaces accessibles",
        "tags": [
          "Espaces"
        ],
        "description": "Session web requise ; aucune clé API. Liste uniquement les appartenances actives du compte. Un espace personnel est créé à la première connexion ; pas de création d’équipe dans ce lot.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Lister mes espaces accessibles",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Workspace"
                      }
                    }
                  },
                  "required": [
                    "items"
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [],
        "security": [
          {
            "sessionAuth": []
          }
        ]
      }
    },
    "/v1/workspaces/{workspaceId}": {
      "get": {
        "operationId": "getWorkspace",
        "summary": "Consulter un espace",
        "tags": [
          "Espaces"
        ],
        "description": "Session et appartenance active requises. X-Workspace-Id doit correspondre au chemin (400 sinon). Espace inconnu ou étranger : 404 identique, sans divulgation de son existence. Tous les rôles actifs peuvent consulter.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Consulter un espace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [],
        "security": [
          {
            "sessionAuth": []
          }
        ]
      },
      "patch": {
        "operationId": "renameWorkspace",
        "summary": "Renommer un espace",
        "tags": [
          "Espaces"
        ],
        "description": "Session, Origin, CSRF et appartenance propriétaire/administrateur requis. Nom seul modifiable ; les champs de propriété et de rôle sont refusés. Lecteur/membre : 403. Espace étranger ou inconnu : 404. Aucun fichier ni quota ne change.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenameWorkspace"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Renommer un espace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [],
        "security": [
          {
            "sessionAuth": []
          }
        ]
      }
    },
    "/v1/uploads": {
      "post": {
        "operationId": "createUpload",
        "summary": "Créer une session de téléversement",
        "tags": [
          "Fichiers"
        ],
        "description": "Point 3 : session web, Origin/CSRF pour les mutations et espace autorisé ; clé Bearer avec les scopes indiqués. Écriture : owner/admin/member, lecture : toute appartenance active. PDF simples (100 Mio/500 pages) et images JPEG/PNG/WebP fixes (50 Mio/20 MP), inspection préalable obligatoire. Une référence étrangère retourne 404. Authentification alternative : Bearer avec scopes assets:write. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UploadRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Créer une session de téléversement",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Upload"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "assets:write"
        ]
      }
    },
    "/v1/uploads/{uploadId}": {
      "get": {
        "operationId": "getUpload",
        "summary": "Reprendre un téléversement avec les parties reçues",
        "tags": [
          "Fichiers"
        ],
        "description": "Point 3 : session web, Origin/CSRF pour les mutations et espace autorisé ; clé Bearer avec les scopes indiqués. Écriture : owner/admin/member, lecture : toute appartenance active. PDF simples (100 Mio/500 pages) et images JPEG/PNG/WebP fixes (50 Mio/20 MP), inspection préalable obligatoire. Une référence étrangère retourne 404. Authentification alternative : Bearer avec scopes assets:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "uploadId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Reprendre un téléversement avec les parties reçues",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Upload"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "assets:read"
        ]
      },
      "delete": {
        "operationId": "abortUpload",
        "summary": "Abandonner un téléversement",
        "tags": [
          "Fichiers"
        ],
        "description": "Point 3 : session web, Origin/CSRF pour les mutations et espace autorisé ; clé Bearer avec les scopes indiqués. Écriture : owner/admin/member, lecture : toute appartenance active. PDF simples (100 Mio/500 pages) et images JPEG/PNG/WebP fixes (50 Mio/20 MP), inspection préalable obligatoire. Une référence étrangère retourne 404. Authentification alternative : Bearer avec scopes assets:write. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "uploadId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Abandonner un téléversement"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "assets:write"
        ]
      }
    },
    "/v1/uploads/{uploadId}/parts": {
      "post": {
        "operationId": "signUploadParts",
        "summary": "Autoriser des parties de téléversement",
        "tags": [
          "Fichiers"
        ],
        "description": "Point 3 : session web, Origin/CSRF pour les mutations et espace autorisé ; clé Bearer avec les scopes indiqués. Écriture : owner/admin/member, lecture : toute appartenance active. PDF simples (100 Mio/500 pages) et images JPEG/PNG/WebP fixes (50 Mio/20 MP), inspection préalable obligatoire. Une référence étrangère retourne 404. Authentification alternative : Bearer avec scopes assets:write. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite. Liens d’envoi signés : 900 secondes maximum en session web, 60 secondes maximum avec Bearer, bornés par expiration de la clé.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "uploadId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "part_numbers": {
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 20
                    },
                    "minItems": 1,
                    "maxItems": 20,
                    "uniqueItems": true
                  }
                },
                "required": [
                  "part_numbers"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Autoriser des parties de téléversement",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "parts": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/UploadPart"
                      }
                    }
                  },
                  "required": [
                    "parts"
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "assets:write"
        ]
      }
    },
    "/v1/uploads/{uploadId}/complete": {
      "post": {
        "operationId": "completeUpload",
        "summary": "Compléter et lancer inspection",
        "tags": [
          "Fichiers"
        ],
        "description": "Point 3 : session web, Origin/CSRF pour les mutations et espace autorisé ; clé Bearer avec les scopes indiqués. Écriture : owner/admin/member, lecture : toute appartenance active. PDF simples (100 Mio/500 pages) et images JPEG/PNG/WebP fixes (50 Mio/20 MP), inspection préalable obligatoire. Une référence étrangère retourne 404. Authentification alternative : Bearer avec scopes assets:write. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "uploadId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "parts": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/CompletedPart"
                    },
                    "minItems": 1,
                    "maxItems": 20
                  }
                },
                "required": [
                  "parts"
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Compléter et lancer inspection",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Asset"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "assets:write"
        ]
      }
    },
    "/v1/assets": {
      "get": {
        "operationId": "listAssets",
        "summary": "Lister les 50 dépôts temporaires les plus récents",
        "tags": [
          "Fichiers"
        ],
        "description": "Point 3 : session web, Origin/CSRF pour les mutations et espace autorisé ; clé Bearer avec les scopes indiqués. Écriture : owner/admin/member, lecture : toute appartenance active. PDF simples (100 Mio/500 pages) et images JPEG/PNG/WebP fixes (50 Mio/20 MP), inspection préalable obligatoire. Une référence étrangère retourne 404. Authentification alternative : Bearer avec scopes assets:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Lister les 50 dépôts temporaires les plus récents",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Asset"
                      }
                    }
                  },
                  "required": [
                    "items"
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "assets:read"
        ]
      }
    },
    "/v1/assets/{assetId}": {
      "get": {
        "operationId": "getAsset",
        "summary": "Lire les métadonnées et inspection",
        "tags": [
          "Fichiers"
        ],
        "description": "Point 3 : session web, Origin/CSRF pour les mutations et espace autorisé ; clé Bearer avec les scopes indiqués. Écriture : owner/admin/member, lecture : toute appartenance active. PDF simples (100 Mio/500 pages) et images JPEG/PNG/WebP fixes (50 Mio/20 MP), inspection préalable obligatoire. Une référence étrangère retourne 404. Authentification alternative : Bearer avec scopes assets:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "assetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lire les métadonnées et inspection",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Asset"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "assets:read"
        ]
      },
      "delete": {
        "operationId": "deleteAsset",
        "summary": "Révoquer accès et demander suppression",
        "tags": [
          "Fichiers"
        ],
        "description": "Point 3 : session web, Origin/CSRF pour les mutations et espace autorisé ; clé Bearer avec les scopes indiqués. Écriture : owner/admin/member, lecture : toute appartenance active. PDF simples (100 Mio/500 pages) et images JPEG/PNG/WebP fixes (50 Mio/20 MP), inspection préalable obligatoire. Une référence étrangère retourne 404. Authentification alternative : Bearer avec scopes assets:write. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "assetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Révoquer accès et demander suppression",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "asset_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "deleting",
                        "deleted"
                      ]
                    }
                  },
                  "required": [
                    "asset_id",
                    "status"
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "assets:write"
        ]
      }
    },
    "/v1/assets/{assetId}/download-url": {
      "post": {
        "operationId": "createDownloadUrl",
        "summary": "Obtenir un lien temporaire",
        "tags": [
          "Fichiers"
        ],
        "description": "Point 3 : session web, Origin/CSRF pour les mutations et espace autorisé ; clé Bearer avec les scopes indiqués. Écriture : owner/admin/member, lecture : toute appartenance active. PDF simples (100 Mio/500 pages) et images JPEG/PNG/WebP fixes (50 Mio/20 MP), inspection préalable obligatoire. Une référence étrangère retourne 404. Authentification alternative : Bearer avec scopes assets:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "assetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Obtenir un lien temporaire",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DownloadLink"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "assets:read"
        ]
      }
    },
    "/v1/assets/{assetId}/content": {
      "get": {
        "operationId": "downloadAsset",
        "summary": "Télécharger un original inspecté",
        "tags": [
          "Fichiers"
        ],
        "description": "Point 3 : session web, Origin/CSRF pour les mutations et espace autorisé ; clé Bearer avec les scopes indiqués. Écriture : owner/admin/member, lecture : toute appartenance active. PDF simples (100 Mio/500 pages) et images JPEG/PNG/WebP fixes (50 Mio/20 MP), inspection préalable obligatoire. Une référence étrangère retourne 404. Authentification alternative : Bearer avec scopes assets:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "name": "X-Workspace-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Obligatoire avec Bearer ; le lien signé fournit le contexte pour une session web."
          },
          {
            "name": "assetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Lien signé lié au principal et à l’espace, 60 s maximum ; authentification session ou Bearer requise, droits, suppression et expiration revérifiés."
          }
        ],
        "responses": {
          "200": {
            "description": "Original inspecté, servi en pièce jointe ; aucune conversion.",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "assets:read"
        ]
      }
    },
    "/v1/estimates": {
      "post": {
        "operationId": "estimateProcessing",
        "summary": "Pré-estimer un traitement sans réservation",
        "tags": [
          "Traitements"
        ],
        "description": "Session owner/admin/member, Origin/CSRF ; clé Bearer avec les scopes indiqués. Pré-estimation merge/split/organize/compress/image_to_pdf/pdf_to_image/office_to_pdf/ocr sur fichiers inspectés sans réservation. Une conversion images/PDF coûte 1 DU par job réussi ; Office/PDF coûte 2 DU par document réussi. Empreinte des entrées, ordre et paramètres ; expiration cinq minutes. PDF natif activable, maximum 1 DU ; compression sans gain à 0 DU ; OCR réserve 1 DU et une page OCR par page sélectionnée ; seules les pages analysées sont consommées. Pages déjà textuelles : zéro DU ; un PDF et un texte UTF-8 publiés ensemble. Région development-local. Ajouts visuels, protect et unlock : maximum 1 DU. Le devis ne contient aucun mot de passe ; requires_secret est vrai pour protect/unlock. Notification terminale facultative au lancement du job. Authentification alternative : Bearer avec scopes jobs:write, assets:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlanningIntent"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Pré-estimer un traitement sans réservation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Estimate"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "jobs:write",
          "assets:read"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      }
    },
    "/v1/jobs": {
      "post": {
        "operationId": "createJob",
        "summary": "Lancer un traitement avec réservation",
        "tags": [
          "Traitements"
        ],
        "description": "Déposez vos fichiers et obtenez un devis avant de lancer. Une réponse 202 confirme l’acceptation ; suivez ensuite l’état du traitement. Réutilisez exactement la demande et sa clé d’idempotence après une réponse incertaine pour éviter un second lancement. Une opération indisponible renvoie 503 sans réservation. Les résultats sont téléchargeables après réussite. protect/unlock exigent secret_ref créé par le même utilisateur dans le même espace ; les autres opérations refusent ce paramètre. webhook_endpoint_id sélectionne un webhook actif du même espace et doit rester identique lors d’une reprise. Authentification alternative : Bearer avec scopes jobs:write, assets:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._-]+$"
            },
            "description": "Conservée 30 jours avec le job par espace et principal. Même clé et requête : même job. Contenu différent : 409."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlannedJobRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Job existant après répétition idempotente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            },
            "headers": {
              "Idempotency-Replayed": {
                "schema": {
                  "type": "boolean",
                  "const": true
                },
                "description": "Réponse issue de la liaison déjà enregistrée."
              }
            }
          },
          "202": {
            "description": "Lancer un traitement avec réservation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "jobs:write",
          "assets:read"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      },
      "get": {
        "operationId": "listJobs",
        "summary": "Lister les jobs de l’espace",
        "tags": [
          "Traitements"
        ],
        "description": "Lister les jobs de l’espace. Clé API : scopes jobs:read requis. Autorisation de l’espace vérifiée côté serveur. Authentification alternative : Bearer avec scopes jobs:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "operation",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/OperationName"
            },
            "description": "Filtrer une opération, combinable avec état et curseur."
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/JobStatus"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lister les jobs de l’espace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobList"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "jobs:read"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      }
    },
    "/v1/jobs/{jobId}": {
      "get": {
        "operationId": "getJob",
        "summary": "Lire l’état du job",
        "tags": [
          "Traitements"
        ],
        "description": "Lire l’état du job. Clé API : scopes jobs:read requis. Autorisation de l’espace vérifiée côté serveur. Authentification alternative : Bearer avec scopes jobs:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lire l’état du job",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "jobs:read"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      }
    },
    "/v1/jobs/{jobId}/cancel": {
      "post": {
        "operationId": "cancelJob",
        "summary": "Demander annulation du job",
        "tags": [
          "Traitements"
        ],
        "description": "Session owner/admin/member, Origin et CSRF. queued devient canceled avec libération de la réservation ; running devient cancel_requested et conserve sa réservation jusqu’à constat d’arrêt. Job terminal : 409. Aucun débit sur échec/annulation, compteur de lancements conservé. Authentification alternative : Bearer avec scopes jobs:write. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Demander annulation du job",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "jobs:write"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      }
    },
    "/v1/jobs/{jobId}/manifest": {
      "get": {
        "operationId": "getJobManifest",
        "summary": "Consulter le bilan du traitement réussi",
        "tags": [
          "Traitements"
        ],
        "description": "Session et appartenance active ; clé Bearer avec les scopes indiqués. Job non réussi : 409 JOB_NOT_SUCCEEDED. Espace étranger : 404. Empreintes des entrées/sorties, paramètres normalisés, provenance page par page pour PDF/images ou au document pour Office, consommation et date de fin. Aucun chemin, contenu ni URL signée. Conservé avec le job même après expiration des octets. Authentification alternative : Bearer avec scopes jobs:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Consulter le bilan du traitement réussi",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Manifest"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "jobs:read"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      }
    },
    "/v1/jobs/{jobId}/archive-url": {
      "post": {
        "operationId": "createArchiveUrl",
        "summary": "Obtenir une archive des sorties disponibles",
        "tags": [
          "Traitements"
        ],
        "description": "Session, Origin et CSRF ; appartenance active, lecteurs inclus. ZIP de toutes les sorties du job réussi, 100 membres et 250 Mio maximum, sans préparation ni débit supplémentaire. Lien lié à l’acteur/espace/job/bail, 60 secondes maximum. 409 OUTPUTS_UNAVAILABLE si un membre a expiré ou a été supprimé. Les noms générés ne divulguent aucun nom d’entrée. Authentification alternative : Bearer avec scopes jobs:read, assets:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Obtenir une archive des sorties disponibles",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DownloadLink"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "jobs:read",
          "assets:read"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      }
    },
    "/v1/jobs/{jobId}/archive-content": {
      "get": {
        "operationId": "downloadArchive",
        "summary": "Télécharger le ZIP privé",
        "tags": [
          "Traitements"
        ],
        "description": "Session et lien signé, appartenance et disponibilité revérifiées avant chaque membre. ZIP diffusé sans copie persistée ; CRC32 et SHA-256 contrôlés. Une interruption ne produit pas d’archive complète. Authentification alternative : Bearer avec scopes jobs:read, assets:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "name": "X-Workspace-Id",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Obligatoire avec Bearer ; le lien signé fournit le contexte pour une session web."
          },
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Archive privée en pièce jointe, sans cache.",
            "content": {
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "jobs:read",
          "assets:read"
        ]
      }
    },
    "/v1/secrets": {
      "post": {
        "operationId": "createSecretReference",
        "summary": "Protéger un secret temporaire de job",
        "tags": [
          "Secrets"
        ],
        "description": "Session owner/admin/member, Origin/CSRF et espace obligatoires ; clé Bearer avec les scopes indiqués. Corps fermé de 2048 octets maximum. Dix secrets non liés actifs maximum par principal/espace. Cinq minutes pour attachement unique, trente minutes maximum depuis création ; suppression à la fin du traitement ou à expiration. Aucun endpoint de lecture. 503 si clé ou canal indisponible. Authentification alternative : Bearer avec scopes jobs:write. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SecretRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Protéger un secret temporaire de job",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretRef"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "jobs:write"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Lire enveloppe et consommation",
        "tags": [
          "Consommation"
        ],
        "description": "Session owner/admin/member. Périodes et jours UTC, plafonds DU/OCR/lancements distincts, initialisation idempotente des compteurs sans réservation. Barème de pré-lancement configurable, aucun paiement. Authentification alternative : Bearer avec scopes usage:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Lire enveloppe et consommation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "usage:read"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      }
    },
    "/v1/usage/entries": {
      "get": {
        "operationId": "listUsageEntries",
        "summary": "Consulter les 50 derniers mouvements de consommation",
        "tags": [
          "Consommation"
        ],
        "description": "Session owner/admin/member. Réservations, débits et libérations avec période et barème ; aucun nom de document ni secret. Maximum 50 écritures les plus récentes. Authentification alternative : Bearer avec scopes usage:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Consulter les 50 derniers mouvements de consommation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/UsageEntry"
                      }
                    }
                  },
                  "required": [
                    "items"
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "usage:read"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      }
    },
    "/v1/presets": {
      "get": {
        "operationId": "listPresets",
        "summary": "Lister les préréglages",
        "tags": [
          "Préréglages"
        ],
        "description": "Session et appartenance active, tous rôles. Au plus cent préréglages par espace, triés par nom. Métadonnées et paramètres sans fichier ni secret ; conservation jusqu’à suppression ou suppression du compte. Aucun cache. Authentification alternative : Bearer avec scopes presets:read. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Lister les préréglages",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Preset"
                      },
                      "maxItems": 100
                    },
                    "can_write": {
                      "type": "boolean"
                    },
                    "contract_version": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "items",
                    "can_write",
                    "contract_version"
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "presets:read"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      },
      "post": {
        "operationId": "createPreset",
        "summary": "Créer un préréglage sans fichier ni secret",
        "tags": [
          "Préréglages"
        ],
        "description": "Session owner/admin/member, Origin/CSRF. Corps objet fermé au plus 64 Kio, nom de 1–100 caractères après retrait des espaces aux extrémités, unique dans l’espace sans distinction de casse. Cent préréglages maximum. Paramètres normalisés et versionnés côté serveur ; aucun asset, secret_ref, mot de passe ou image référencée. Aucun job ni débit. Retourne ETag de la révision. Authentification alternative : Bearer avec scopes presets:write. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePresetRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Créer un préréglage sans fichier ni secret",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preset"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "presets:write"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      }
    },
    "/v1/presets/{presetId}": {
      "patch": {
        "operationId": "updatePreset",
        "summary": "Remplacer les réglages du préréglage",
        "tags": [
          "Préréglages"
        ],
        "description": "Remplacement complet de nom/opération/paramètres avec contrôle de révision. Nouvelle version des paramètres validée côté serveur, révision incrémentée. Droits owner/admin/member et Origin/CSRF. Référence étrangère ou inconnue : 404 identique. Aucun job, fichier ou débit modifié. Authentification alternative : Bearer avec scopes presets:write. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "presetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"[1-9][0-9]*\"$"
            },
            "description": "Révision courante entre guillemets. Absente : 428 ; périmée : 412 PRESET_CHANGED."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePresetRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Remplacer les réglages du préréglage",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Preset"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "presets:write"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      },
      "delete": {
        "operationId": "deletePreset",
        "summary": "Supprimer un préréglage",
        "tags": [
          "Préréglages"
        ],
        "description": "Session owner/admin/member et Origin/CSRF, révision courante obligatoire. Supprime seulement le préréglage ; les jobs et fichiers conservent leur rétention et consommation. Authentification alternative : Bearer avec scopes presets:write. X-Workspace-Id obligatoire avec Bearer, y compris pour les contenus signés ; Origin/CSRF seulement avec session. Les mêmes plafonds et règles de consommation s’appliquent dans votre espace Docoki. Identité, espace et clé recontrôlés à chaque accès ; aucun droit implicite.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "presetId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\"[1-9][0-9]*\"$"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Supprimer un préréglage"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [
          "presets:write"
        ],
        "x-supported-planning-operations": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr"
        ]
      }
    },
    "/v1/api-keys": {
      "get": {
        "operationId": "listApiKeys",
        "summary": "Lister les clés sans leur valeur",
        "tags": [
          "Administration développeur"
        ],
        "description": "Session web du propriétaire actif uniquement. Métadonnées sans valeur ni empreinte, actives en premier, cent dernières au maximum. Une clé Bearer ne peut pas gérer les clés.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Lister les clés sans leur valeur",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiKey"
                      },
                      "maxItems": 100
                    },
                    "maximum_active_keys": {
                      "const": 20
                    },
                    "available_scopes": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Scope"
                      }
                    },
                    "default_expiry_days": {
                      "const": 30
                    },
                    "maximum_expiry_days": {
                      "const": 365
                    }
                  },
                  "required": [
                    "items",
                    "maximum_active_keys",
                    "available_scopes",
                    "default_expiry_days",
                    "maximum_expiry_days"
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [],
        "security": [
          {
            "sessionAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createApiKey",
        "summary": "Créer une clé et afficher sa valeur une fois",
        "tags": [
          "Administration développeur"
        ],
        "description": "Session propriétaire, Origin et CSRF. Corps fermé 4096 octets ; nom 1–100 caractères, un à sept scopes explicites distincts. Expiration obligatoire côté serveur : trente jours par défaut, entre soixante secondes et 365 jours. Vingt clés actives maximum par espace (429). Valeur opaque dko_test_ affichée uniquement dans cette réponse no-store ; seul SHA-256 persiste. Pour une rotation, créer une nouvelle clé puis révoquer l’ancienne.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Scope"
                    },
                    "minItems": 1,
                    "maxItems": 7,
                    "uniqueItems": true
                  },
                  "expires_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "required": [
                  "name",
                  "scopes"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Créer une clé et afficher sa valeur une fois",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NewApiKey"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [],
        "security": [
          {
            "sessionAuth": []
          }
        ]
      }
    },
    "/v1/api-keys/{keyId}": {
      "delete": {
        "operationId": "revokeApiKey",
        "summary": "Révoquer une clé",
        "tags": [
          "Administration développeur"
        ],
        "description": "Session propriétaire, Origin et CSRF. Révocation idempotente, empreinte détruite, prochains appels refusés sans cache et en moins de soixante secondes. Jobs déjà acceptés conservés ; liens d’envoi déjà émis utilisables au plus soixante secondes. Les métadonnées expirées/révoquées sont purgées après trente jours.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Révoquer une clé"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [],
        "security": [
          {
            "sessionAuth": []
          }
        ]
      }
    },
    "/v1/webhook-endpoints": {
      "get": {
        "operationId": "listWebhookEndpoints",
        "summary": "Lister les endpoints de notification",
        "tags": [
          "Notifications"
        ],
        "description": "Session propriétaire uniquement. Dix endpoints actifs, vingt créations par jour et cent métadonnées récentes au maximum. Valeur de signature jamais relue.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Lister les endpoints de notification",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookEndpoint"
                      },
                      "maxItems": 100
                    },
                    "maximum_active_endpoints": {
                      "const": 10
                    },
                    "maximum_attempts": {
                      "const": 6
                    }
                  },
                  "required": [
                    "items",
                    "maximum_active_endpoints",
                    "maximum_attempts"
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [],
        "security": [
          {
            "sessionAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createWebhookEndpoint",
        "summary": "Créer un endpoint HTTPS et son secret",
        "tags": [
          "Notifications"
        ],
        "description": "Session propriétaire, Origin et CSRF. HTTPS sur port 443 et nom DNS public, sans identifiants, query ou fragment ; corps fermé limité à 4096 octets, un à trois événements distincts. DNS/IPv4/IPv6 contrôlés ; secret affiché une fois et chiffré en base avec clé hors dépôt.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "pattern": "^https://"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "job.succeeded",
                        "job.failed",
                        "job.canceled"
                      ]
                    },
                    "minItems": 1,
                    "uniqueItems": true
                  }
                },
                "required": [
                  "url",
                  "events"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Créer un endpoint HTTPS et son secret",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NewWebhookEndpoint"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [],
        "security": [
          {
            "sessionAuth": []
          }
        ]
      }
    },
    "/v1/webhook-endpoints/{endpointId}": {
      "delete": {
        "operationId": "deleteWebhookEndpoint",
        "summary": "Désactiver un endpoint et ses livraisons",
        "tags": [
          "Notifications"
        ],
        "description": "Désactivation idempotente, secret chiffré détruit, tentatives en attente annulées. Envoi déjà en cours borné à dix secondes ; aucun autre job ni quota modifié.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "endpointId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Désactiver un endpoint et ses livraisons"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [],
        "security": [
          {
            "sessionAuth": []
          }
        ]
      }
    },
    "/v1/webhook-endpoints/{endpointId}/deliveries": {
      "get": {
        "operationId": "listWebhookDeliveries",
        "summary": "Lire le journal des livraisons sans contenu",
        "tags": [
          "Notifications"
        ],
        "description": "Session propriétaire. Journal sans payload, URL ni signature ; cursor UUID de dernier événement, limit de 1 à 100. Six tentatives maximum, conservation trente jours.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "endpointId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Lire le journal des livraisons sans contenu",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "uuid"
                    },
                    "maximum_attempts": {
                      "const": 6
                    }
                  },
                  "required": [
                    "items",
                    "next_cursor",
                    "maximum_attempts"
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [],
        "security": [
          {
            "sessionAuth": []
          }
        ]
      }
    },
    "/v1/webhook-endpoints/{endpointId}/deliveries/{eventId}/replay": {
      "post": {
        "operationId": "replayWebhookDelivery",
        "summary": "Avancer une reprise dans le budget restant",
        "tags": [
          "Notifications"
        ],
        "description": "Session propriétaire, Origin et CSRF. Tentative antérieure échouée et reprise encore en attente (1 à 5 tentatives). Avance la prochaine échéance sans ajouter ni remettre à zéro le budget de six tentatives. Livré, épuisé ou en cours : 409 WEBHOOK_REPLAY_UNAVAILABLE.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WorkspaceId"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Requis pour une mutation avec session cookie ; absent avec Bearer."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Adresse d’origine de votre application Docoki ; obligatoire avec la session."
          },
          {
            "name": "endpointId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "eventId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Avancer une reprise dans le budget restant"
          },
          "default": {
            "$ref": "#/components/responses/Error"
          }
        },
        "x-required-scopes": [],
        "security": [
          {
            "sessionAuth": []
          }
        ]
      }
    }
  },
  "webhooks": {
    "jobTerminal": {
      "post": {
        "operationId": "receiveJobTerminal",
        "tags": [
          "Notifications"
        ],
        "summary": "Recevoir un événement terminal signé",
        "description": "Appel HTTPS envoyé au client. Vérifier HMAC-SHA256 sur timestamp + point + event_id + point + corps brut avec le secret d’endpoint ; fenêtre 5 min ; dédupliquer event_id. Six tentatives maximum. Aucun fichier ni URL signé.",
        "security": [],
        "parameters": [
          {
            "name": "Docoki-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "t=timestamp_unix,v1=signature_hex ; timestamp renouvelé à chaque tentative."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Événement accepté. Tout code 2xx acquitte la livraison."
          },
          "default": {
            "description": "Échec de livraison, reprise selon politique. Le client traite les doublons sans nouvel effet."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "opaque API key",
        "description": "Clé Docoki liée à un espace et restreinte par scopes ; pas un JWT."
      },
      "sessionAuth": {
        "type": "apiKey",
        "in": "cookie",
        "name": "docoki_session",
        "description": "Session web HttpOnly/Secure ; contrôle CSRF et Origin requis pour les mutations."
      }
    },
    "parameters": {
      "WorkspaceId": {
        "name": "X-Workspace-Id",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        },
        "description": "Contexte demandé, revérifié par le serveur. Doit correspondre à l’espace de la clé ou à une appartenance de la session."
      }
    },
    "responses": {
      "Error": {
        "description": "Erreur normalisée. Pour un traitement déjà accepté, consultez son état ou les événements reçus par webhook.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Workspace": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "kind": {
            "type": "string",
            "enum": [
              "personal",
              "team"
            ]
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "admin",
              "member",
              "reader"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "kind",
          "role",
          "created_at"
        ]
      },
      "RenameWorkspace": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80,
            "pattern": "^[^\\u0000-\\u001F\\u007F]+$",
            "description": "Sans caractères de contrôle ni espaces aux extrémités."
          }
        },
        "required": [
          "name"
        ]
      },
      "OperationName": {
        "type": "string",
        "enum": [
          "merge",
          "split",
          "organize",
          "compress",
          "image_to_pdf",
          "pdf_to_image",
          "office_to_pdf",
          "ocr",
          "watermark",
          "page_numbers",
          "protect",
          "unlock",
          "annotate"
        ]
      },
      "JobStatus": {
        "type": "string",
        "enum": [
          "queued",
          "running",
          "cancel_requested",
          "succeeded",
          "failed",
          "canceled"
        ]
      },
      "AssetStatus": {
        "type": "string",
        "enum": [
          "uploading",
          "inspecting",
          "ready",
          "rejected",
          "deleting",
          "deleted"
        ]
      },
      "Scope": {
        "type": "string",
        "enum": [
          "assets:read",
          "assets:write",
          "jobs:read",
          "jobs:write",
          "usage:read",
          "presets:read",
          "presets:write"
        ]
      },
      "Problem": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "request_id": {
            "type": "string"
          },
          "retryable": {
            "type": "boolean"
          },
          "details": {
            "type": "object",
            "additionalProperties": true,
            "description": "Détails non sensibles ; jamais de stack, chemin, secret, contenu ou URL signée."
          }
        },
        "required": [
          "code",
          "message",
          "request_id",
          "retryable"
        ]
      },
      "Error": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "error": {
            "$ref": "#/components/schemas/Problem"
          }
        },
        "required": [
          "error"
        ]
      },
      "Warning": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "page": {
            "type": "integer",
            "minimum": 1
          }
        },
        "required": [
          "code",
          "message"
        ]
      },
      "Asset": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "$ref": "#/components/schemas/AssetStatus"
          },
          "detected_mime_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "byte_size": {
            "type": "integer",
            "minimum": 0
          },
          "sha256": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[a-f0-9]{64}$"
          },
          "page_count": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "description": "Null pour les documents Office inspectés et les sorties texte UTF-8. La pagination PDF est mesurée ; aucune pagination inventée pour le texte. Null également pour un PDF chiffré déposé : seul le déverrouillage permet son inspection complète. Un résultat protect conserve une pagination et une géométrie vérifiées."
          },
          "flags": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "encrypted": {
                "type": "boolean"
              },
              "signed": {
                "type": "boolean"
              },
              "has_forms": {
                "type": "boolean"
              },
              "active_content": {
                "type": "boolean"
              },
              "unsupported_structure": {
                "type": "boolean"
              }
            },
            "required": [
              "encrypted",
              "signed",
              "has_forms",
              "active_content",
              "unsupported_structure"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Problem"
              },
              {
                "type": "null"
              }
            ]
          },
          "properties": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PdfGeometry"
              },
              {
                "$ref": "#/components/schemas/ImageGeometry"
              },
              {
                "type": "object",
                "additionalProperties": false,
                "properties": {},
                "required": []
              },
              {
                "$ref": "#/components/schemas/OfficeProperties"
              },
              {
                "$ref": "#/components/schemas/TextProperties"
              },
              {
                "$ref": "#/components/schemas/ProtectedPdfGeometry"
              },
              {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "encrypted_unverified": {
                    "const": true
                  }
                },
                "required": [
                  "encrypted_unverified"
                ]
              }
            ]
          },
          "file_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Nom privé, effacé lors de la purge."
          },
          "upload_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "purged_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "status",
          "detected_mime_type",
          "byte_size",
          "sha256",
          "page_count",
          "flags",
          "created_at",
          "expires_at"
        ]
      },
      "PageRange": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "from": {
            "type": "integer",
            "minimum": 1
          },
          "to": {
            "type": "integer",
            "minimum": 1
          }
        },
        "required": [
          "from",
          "to"
        ],
        "description": "Bornes inclusives ; from <= to <= nombre de pages. Chevauchement entre plages permis et signalé."
      },
      "PageSelection": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "rotation": {
            "type": "integer",
            "enum": [
              0,
              90,
              180,
              270
            ],
            "description": "Rotation additionnelle en degrés ; défaut 0.",
            "default": 0
          }
        },
        "required": [
          "page"
        ]
      },
      "Point": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "x": {
            "type": "number"
          },
          "y": {
            "type": "number"
          }
        },
        "required": [
          "x",
          "y"
        ]
      },
      "TextAnnotation": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "type": {
            "const": "text"
          },
          "page": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500
          },
          "x": {
            "type": "number",
            "minimum": 0,
            "maximum": 14400
          },
          "y": {
            "type": "number",
            "minimum": 0,
            "maximum": 14400
          },
          "width": {
            "type": "number",
            "minimum": 0.1,
            "maximum": 14400
          },
          "height": {
            "type": "number",
            "minimum": 0.1,
            "maximum": 14400
          },
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 5000
          },
          "font_size": {
            "type": "number",
            "minimum": 6,
            "maximum": 144,
            "default": 12
          },
          "color": {
            "type": "string",
            "pattern": "^#[0-9a-fA-F]{6}$",
            "default": "#000000"
          }
        },
        "required": [
          "type",
          "page",
          "x",
          "y",
          "width",
          "height",
          "text"
        ]
      },
      "ImageAnnotation": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "type": {
            "const": "image"
          },
          "page": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500
          },
          "x": {
            "type": "number",
            "minimum": 0,
            "maximum": 14400
          },
          "y": {
            "type": "number",
            "minimum": 0,
            "maximum": 14400
          },
          "width": {
            "type": "number",
            "minimum": 0.1,
            "maximum": 14400
          },
          "height": {
            "type": "number",
            "minimum": 0.1,
            "maximum": 14400
          },
          "image_asset_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "type",
          "page",
          "x",
          "y",
          "width",
          "height",
          "image_asset_id"
        ],
        "description": "Asset image ready du même espace. Cette référence auxiliaire entre dans les limites de taille, pixels, accès et expiration."
      },
      "StrokeAnnotation": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "type": {
            "const": "stroke"
          },
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "points": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Point"
            },
            "minItems": 2,
            "maxItems": 2000
          },
          "line_width": {
            "type": "number",
            "minimum": 0.1,
            "maximum": 30,
            "default": 1
          },
          "color": {
            "type": "string",
            "pattern": "^#[0-9a-fA-F]{6}$",
            "default": "#000000"
          }
        },
        "required": [
          "type",
          "page",
          "points"
        ]
      },
      "Annotation": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/TextAnnotation"
          },
          {
            "$ref": "#/components/schemas/ImageAnnotation"
          },
          {
            "$ref": "#/components/schemas/StrokeAnnotation"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "text": "#/components/schemas/TextAnnotation",
            "image": "#/components/schemas/ImageAnnotation",
            "stroke": "#/components/schemas/StrokeAnnotation"
          }
        },
        "description": "Coordonnées en points PDF, origine en bas à gauche de la CropBox non tournée. Le client transforme les coordonnées écran selon CropBox et rotation ; toute boîte ou épaisseur hors page est refusée. Caractères latins et ponctuation FR/EN acceptés. Texte avec sauts explicites, sans retour automatique ; débordement refusé. 100 annotations, 2 000 points/trait, 4 000 points cumulés et 10 images auxiliaires/40 MP cumulés. Ajouts aplatis sans caviardage ni preuve de signature."
      },
      "MergeParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      },
      "MergeIntent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "merge",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 2,
            "maxItems": 20,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/MergeParameters"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters"
        ]
      },
      "MergePresetRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "operation": {
            "type": "string",
            "const": "merge"
          },
          "parameters": {
            "$ref": "#/components/schemas/MergeParameters"
          }
        },
        "required": [
          "name",
          "operation",
          "parameters"
        ]
      },
      "SplitParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "ranges": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PageRange"
            },
            "minItems": 1,
            "maxItems": 100
          }
        },
        "required": [
          "ranges"
        ]
      },
      "SplitIntent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "split",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/SplitParameters"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters"
        ]
      },
      "SplitPresetRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "operation": {
            "type": "string",
            "const": "split"
          },
          "parameters": {
            "$ref": "#/components/schemas/SplitParameters"
          }
        },
        "required": [
          "name",
          "operation",
          "parameters"
        ]
      },
      "OrganizeParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "pages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PageSelection"
            },
            "minItems": 1,
            "maxItems": 500
          }
        },
        "required": [
          "pages"
        ]
      },
      "OrganizeIntent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "organize",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/OrganizeParameters"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters"
        ]
      },
      "OrganizePresetRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "operation": {
            "type": "string",
            "const": "organize"
          },
          "parameters": {
            "$ref": "#/components/schemas/OrganizeParameters"
          }
        },
        "required": [
          "name",
          "operation",
          "parameters"
        ]
      },
      "CompressParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "profile": {
            "type": "string",
            "enum": [
              "light",
              "balanced",
              "strong"
            ],
            "default": "balanced",
            "description": "Choisissez un effort de compression léger, équilibré ou fort. La qualité et la résolution des images sont conservées."
          },
          "target_bytes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 104857600,
            "description": "Cible facultative, non garantie. Déjà atteinte : original conservé sans débit. Sinon TARGET_NOT_REACHED si aucun candidat admissible ne la satisfait."
          },
          "minimum_image_dpi": {
            "type": "integer",
            "minimum": 72,
            "maximum": 300,
            "default": 96,
            "description": "Seuil conservé dans les paramètres ; la résolution des images est conservée. La résolution de l’entrée reste inchangée, y compris si elle est déjà inférieure au seuil."
          }
        },
        "required": [],
        "description": "PDF simples, compression structurelle sans perte. Aucun transcodage JPEG, réduction de résolution ou rasterisation. 1 DU si réduction, 0 DU si original conservé."
      },
      "CompressIntent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "compress",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/CompressParameters"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters"
        ]
      },
      "CompressPresetRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "operation": {
            "type": "string",
            "const": "compress"
          },
          "parameters": {
            "$ref": "#/components/schemas/CompressParameters"
          }
        },
        "required": [
          "name",
          "operation",
          "parameters"
        ]
      },
      "ImageToPdfParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "page_size": {
            "type": "string",
            "enum": [
              "A4",
              "fit"
            ],
            "default": "A4"
          },
          "orientation": {
            "type": "string",
            "enum": [
              "auto",
              "portrait",
              "landscape"
            ],
            "default": "auto"
          },
          "margin_pt": {
            "type": "number",
            "minimum": 0,
            "maximum": 144,
            "default": 12
          },
          "background_color": {
            "type": "string",
            "pattern": "^#[0-9a-fA-F]{6}$",
            "default": "#FFFFFF"
          }
        },
        "required": []
      },
      "ImageToPdfIntent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "image_to_pdf",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 20,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/ImageToPdfParameters"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters"
        ]
      },
      "ImageToPdfPresetRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "operation": {
            "type": "string",
            "const": "image_to_pdf"
          },
          "parameters": {
            "$ref": "#/components/schemas/ImageToPdfParameters"
          }
        },
        "required": [
          "name",
          "operation",
          "parameters"
        ]
      },
      "PdfToImageParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "pages": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            },
            "minItems": 1,
            "maxItems": 100,
            "uniqueItems": true,
            "description": "Pages base 1. Absence du champ : toutes les pages admissibles. Une page inexistante est refusée."
          },
          "format": {
            "type": "string",
            "enum": [
              "jpeg",
              "png"
            ],
            "default": "jpeg"
          },
          "dpi": {
            "type": "integer",
            "minimum": 72,
            "maximum": 200,
            "default": 144
          }
        },
        "required": [],
        "description": "1 image par page ; 20 MP/image, 100 MP cumulés et estimation RGB majorante sous 250 Mio ; refus avant réservation si dépassement. CropBox incluse dans MediaBox et UserUnit=1 requis."
      },
      "PdfToImageIntent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "pdf_to_image",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/PdfToImageParameters"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters"
        ]
      },
      "PdfToImagePresetRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "operation": {
            "type": "string",
            "const": "pdf_to_image"
          },
          "parameters": {
            "$ref": "#/components/schemas/PdfToImageParameters"
          }
        },
        "required": [
          "name",
          "operation",
          "parameters"
        ]
      },
      "OfficeToPdfParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "spreadsheet_fit_width": {
            "type": "boolean",
            "default": false,
            "description": "XLSX seulement : une page en largeur, hauteur libre, zones d’impression conservées. False : mise en page d’origine."
          }
        },
        "required": [],
        "description": "Un DOCX/XLSX/PPTX de 50 Mio maximum ; 2 DU par réussite, zéro en cas d’échec. Pagination inconnue avant rendu. Macros, liens externes, objets incorporés et structures non qualifiées refusés."
      },
      "OfficeToPdfIntent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "office_to_pdf",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/OfficeToPdfParameters"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters"
        ]
      },
      "OfficeToPdfPresetRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "operation": {
            "type": "string",
            "const": "office_to_pdf"
          },
          "parameters": {
            "$ref": "#/components/schemas/OfficeToPdfParameters"
          }
        },
        "required": [
          "name",
          "operation",
          "parameters"
        ]
      },
      "OcrParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "languages": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "fra",
                "eng"
              ]
            },
            "minItems": 1,
            "maxItems": 2,
            "uniqueItems": true,
            "default": [
              "fra"
            ]
          },
          "pages": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            },
            "minItems": 1,
            "maxItems": 100,
            "uniqueItems": true,
            "description": "Sélection traitée dans l’ordre du document. PDF complet conservé ; texte limité aux pages choisies."
          },
          "deskew": {
            "type": "boolean",
            "default": true
          },
          "strategy": {
            "const": "skip_text",
            "default": "skip_text"
          }
        },
        "required": []
      },
      "OcrIntent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "ocr",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/OcrParameters"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters"
        ]
      },
      "OcrPresetRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "operation": {
            "type": "string",
            "const": "ocr"
          },
          "parameters": {
            "$ref": "#/components/schemas/OcrParameters"
          }
        },
        "required": [
          "name",
          "operation",
          "parameters"
        ]
      },
      "WatermarkParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300
          },
          "pages": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            },
            "minItems": 1,
            "maxItems": 500,
            "uniqueItems": true,
            "description": "Pages base 1. Absence du champ : toutes les pages admissibles. Une page inexistante est refusée."
          },
          "position": {
            "type": "string",
            "enum": [
              "top_left",
              "top_center",
              "top_right",
              "center",
              "bottom_left",
              "bottom_center",
              "bottom_right"
            ],
            "default": "center"
          },
          "opacity": {
            "type": "number",
            "minimum": 0.05,
            "maximum": 1,
            "default": 0.3
          },
          "angle": {
            "type": "number",
            "minimum": -180,
            "maximum": 180,
            "default": 0
          },
          "font_size": {
            "type": "number",
            "minimum": 6,
            "maximum": 144,
            "default": 24
          }
        },
        "required": [
          "text"
        ],
        "description": "Ajout visuel noir, positions selon la page affichée, marge 18 pt, angle anti-horaire. Sélection canonique croissante. Texte hors page refusé avant réservation ; 1 DU par réussite."
      },
      "WatermarkIntent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "watermark",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/WatermarkParameters"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters"
        ]
      },
      "WatermarkPresetRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "operation": {
            "type": "string",
            "const": "watermark"
          },
          "parameters": {
            "$ref": "#/components/schemas/WatermarkParameters"
          }
        },
        "required": [
          "name",
          "operation",
          "parameters"
        ]
      },
      "PageNumbersParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "pages": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            },
            "minItems": 1,
            "maxItems": 500,
            "uniqueItems": true,
            "description": "Pages base 1. Absence du champ : toutes les pages admissibles. Une page inexistante est refusée."
          },
          "position": {
            "type": "string",
            "enum": [
              "top_left",
              "top_center",
              "top_right",
              "center",
              "bottom_left",
              "bottom_center",
              "bottom_right"
            ],
            "default": "bottom_center"
          },
          "start_number": {
            "type": "integer",
            "minimum": 1,
            "maximum": 999999,
            "default": 1
          },
          "prefix": {
            "type": "string",
            "maxLength": 100,
            "default": ""
          }
        },
        "required": [],
        "description": "Texte noir de 12 pt, marge 18 pt, position selon la page affichée. Numérotation successive uniquement sur la sélection croissante, maximum 999999 ; 1 DU par réussite."
      },
      "PageNumbersIntent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "page_numbers",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/PageNumbersParameters"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters"
        ]
      },
      "PageNumbersPresetRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "operation": {
            "type": "string",
            "const": "page_numbers"
          },
          "parameters": {
            "$ref": "#/components/schemas/PageNumbersParameters"
          }
        },
        "required": [
          "name",
          "operation",
          "parameters"
        ]
      },
      "ProtectParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      },
      "ProtectIntent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "protect",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/ProtectParameters"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters"
        ]
      },
      "ProtectPresetRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "operation": {
            "type": "string",
            "const": "protect"
          },
          "parameters": {
            "$ref": "#/components/schemas/ProtectParameters"
          }
        },
        "required": [
          "name",
          "operation",
          "parameters"
        ]
      },
      "UnlockParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {},
        "required": []
      },
      "UnlockIntent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "unlock",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/UnlockParameters"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters"
        ]
      },
      "UnlockPresetRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "operation": {
            "type": "string",
            "const": "unlock"
          },
          "parameters": {
            "$ref": "#/components/schemas/UnlockParameters"
          }
        },
        "required": [
          "name",
          "operation",
          "parameters"
        ]
      },
      "AnnotateParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Annotation"
            },
            "minItems": 1,
            "maxItems": 100
          }
        },
        "required": [
          "annotations"
        ]
      },
      "AnnotateIntent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "annotate",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 11,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/AnnotateParameters"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters"
        ]
      },
      "AnnotatePresetParameters": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "annotations": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/TextAnnotation"
                },
                {
                  "$ref": "#/components/schemas/StrokeAnnotation"
                }
              ]
            },
            "minItems": 1,
            "maxItems": 100
          }
        },
        "required": [
          "annotations"
        ]
      },
      "AnnotatePresetRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "operation": {
            "type": "string",
            "const": "annotate"
          },
          "parameters": {
            "$ref": "#/components/schemas/AnnotatePresetParameters"
          }
        },
        "required": [
          "name",
          "operation",
          "parameters"
        ]
      },
      "ProcessingIntent": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/MergeIntent"
          },
          {
            "$ref": "#/components/schemas/SplitIntent"
          },
          {
            "$ref": "#/components/schemas/OrganizeIntent"
          },
          {
            "$ref": "#/components/schemas/CompressIntent"
          },
          {
            "$ref": "#/components/schemas/ImageToPdfIntent"
          },
          {
            "$ref": "#/components/schemas/PdfToImageIntent"
          },
          {
            "$ref": "#/components/schemas/OfficeToPdfIntent"
          },
          {
            "$ref": "#/components/schemas/OcrIntent"
          },
          {
            "$ref": "#/components/schemas/WatermarkIntent"
          },
          {
            "$ref": "#/components/schemas/PageNumbersIntent"
          },
          {
            "$ref": "#/components/schemas/ProtectIntent"
          },
          {
            "$ref": "#/components/schemas/UnlockIntent"
          },
          {
            "$ref": "#/components/schemas/AnnotateIntent"
          }
        ],
        "discriminator": {
          "propertyName": "operation",
          "mapping": {
            "merge": "#/components/schemas/MergeIntent",
            "split": "#/components/schemas/SplitIntent",
            "organize": "#/components/schemas/OrganizeIntent",
            "compress": "#/components/schemas/CompressIntent",
            "image_to_pdf": "#/components/schemas/ImageToPdfIntent",
            "pdf_to_image": "#/components/schemas/PdfToImageIntent",
            "office_to_pdf": "#/components/schemas/OfficeToPdfIntent",
            "ocr": "#/components/schemas/OcrIntent",
            "watermark": "#/components/schemas/WatermarkIntent",
            "page_numbers": "#/components/schemas/PageNumbersIntent",
            "protect": "#/components/schemas/ProtectIntent",
            "unlock": "#/components/schemas/UnlockIntent",
            "annotate": "#/components/schemas/AnnotateIntent"
          }
        },
        "description": "Une seule opération. Les contrôles dynamiques de pages, formats, secret nécessaire et taille sont appliqués côté serveur.",
        "examples": [
          {
            "operation": "ocr",
            "input_asset_ids": [
              "10000000-0000-4000-8000-000000000001"
            ],
            "parameters": {
              "languages": [
                "fra",
                "eng"
              ],
              "strategy": "skip_text"
            }
          }
        ]
      },
      "PlanningIntent": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/MergeIntent"
          },
          {
            "$ref": "#/components/schemas/SplitIntent"
          },
          {
            "$ref": "#/components/schemas/OrganizeIntent"
          },
          {
            "$ref": "#/components/schemas/CompressIntent"
          },
          {
            "$ref": "#/components/schemas/ImageToPdfIntent"
          },
          {
            "$ref": "#/components/schemas/PdfToImageIntent"
          },
          {
            "$ref": "#/components/schemas/OfficeToPdfIntent"
          },
          {
            "$ref": "#/components/schemas/OcrIntent"
          },
          {
            "$ref": "#/components/schemas/WatermarkIntent"
          },
          {
            "$ref": "#/components/schemas/PageNumbersIntent"
          },
          {
            "$ref": "#/components/schemas/AnnotateIntent"
          },
          {
            "$ref": "#/components/schemas/ProtectIntent"
          },
          {
            "$ref": "#/components/schemas/UnlockIntent"
          }
        ],
        "description": "PDF natif, compression, conversions images/PDF, Office/PDF, OCR FR/EN, ajouts visuels et protection/déverrouillage exécutables selon leurs drapeaux de configuration."
      },
      "PlannedMergeJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "merge",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 2,
            "maxItems": 20,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/MergeParameters"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_endpoint_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters",
          "estimate_id"
        ]
      },
      "PlannedSplitJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "split",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/SplitParameters"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_endpoint_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters",
          "estimate_id"
        ]
      },
      "PlannedOrganizeJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "organize",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/OrganizeParameters"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_endpoint_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters",
          "estimate_id"
        ]
      },
      "PlannedCompressJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "compress",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/CompressParameters"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_endpoint_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters",
          "estimate_id"
        ]
      },
      "PlannedImageToPdfJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "image_to_pdf",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 20,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/ImageToPdfParameters"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_endpoint_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters",
          "estimate_id"
        ]
      },
      "PlannedPdfToImageJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "pdf_to_image",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/PdfToImageParameters"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_endpoint_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters",
          "estimate_id"
        ]
      },
      "PlannedOfficeToPdfJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "office_to_pdf",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/OfficeToPdfParameters"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_endpoint_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters",
          "estimate_id"
        ]
      },
      "PlannedOcrJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "ocr",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/OcrParameters"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_endpoint_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters",
          "estimate_id"
        ]
      },
      "PlannedWatermarkJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "watermark",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/WatermarkParameters"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_endpoint_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters",
          "estimate_id"
        ]
      },
      "PlannedPageNumbersJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "page_numbers",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/PageNumbersParameters"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_endpoint_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters",
          "estimate_id"
        ]
      },
      "PlannedAnnotateJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "annotate",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 11,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/AnnotateParameters"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_endpoint_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters",
          "estimate_id"
        ]
      },
      "PlannedProtectJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "protect",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/ProtectParameters"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "secret_ref": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_endpoint_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters",
          "estimate_id",
          "secret_ref"
        ]
      },
      "PlannedUnlockJobRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "unlock",
            "type": "string"
          },
          "input_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 1,
            "description": "Ordre significatif. Toutes les références sont ready dans le même espace. Annotate : PDF en premier, puis images auxiliaires dans leur ordre de première occurrence ; leurs UUID sont aussi acceptés uniquement dans image_asset_id et ajoutés à l’intention canonique."
          },
          "parameters": {
            "$ref": "#/components/schemas/UnlockParameters"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "secret_ref": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_endpoint_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "operation",
          "input_asset_ids",
          "parameters",
          "estimate_id",
          "secret_ref"
        ]
      },
      "PlannedJobRequest": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/PlannedMergeJobRequest"
          },
          {
            "$ref": "#/components/schemas/PlannedSplitJobRequest"
          },
          {
            "$ref": "#/components/schemas/PlannedOrganizeJobRequest"
          },
          {
            "$ref": "#/components/schemas/PlannedCompressJobRequest"
          },
          {
            "$ref": "#/components/schemas/PlannedImageToPdfJobRequest"
          },
          {
            "$ref": "#/components/schemas/PlannedPdfToImageJobRequest"
          },
          {
            "$ref": "#/components/schemas/PlannedOfficeToPdfJobRequest"
          },
          {
            "$ref": "#/components/schemas/PlannedOcrJobRequest"
          },
          {
            "$ref": "#/components/schemas/PlannedWatermarkJobRequest"
          },
          {
            "$ref": "#/components/schemas/PlannedPageNumbersJobRequest"
          },
          {
            "$ref": "#/components/schemas/PlannedAnnotateJobRequest"
          },
          {
            "$ref": "#/components/schemas/PlannedProtectJobRequest"
          },
          {
            "$ref": "#/components/schemas/PlannedUnlockJobRequest"
          }
        ],
        "description": "Contrat implémenté : protect/unlock exigent secret_ref, sans valeur de mot de passe dans l’intention. webhook_endpoint_id facultatif, lié à un endpoint actif du même espace et inclus dans l’idempotence."
      },
      "CreatePresetRequest": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/MergePresetRequest"
          },
          {
            "$ref": "#/components/schemas/SplitPresetRequest"
          },
          {
            "$ref": "#/components/schemas/OrganizePresetRequest"
          },
          {
            "$ref": "#/components/schemas/CompressPresetRequest"
          },
          {
            "$ref": "#/components/schemas/ImageToPdfPresetRequest"
          },
          {
            "$ref": "#/components/schemas/PdfToImagePresetRequest"
          },
          {
            "$ref": "#/components/schemas/OfficeToPdfPresetRequest"
          },
          {
            "$ref": "#/components/schemas/OcrPresetRequest"
          },
          {
            "$ref": "#/components/schemas/WatermarkPresetRequest"
          },
          {
            "$ref": "#/components/schemas/PageNumbersPresetRequest"
          },
          {
            "$ref": "#/components/schemas/ProtectPresetRequest"
          },
          {
            "$ref": "#/components/schemas/UnlockPresetRequest"
          },
          {
            "$ref": "#/components/schemas/AnnotatePresetRequest"
          }
        ],
        "discriminator": {
          "propertyName": "operation",
          "mapping": {
            "merge": "#/components/schemas/MergePresetRequest",
            "split": "#/components/schemas/SplitPresetRequest",
            "organize": "#/components/schemas/OrganizePresetRequest",
            "compress": "#/components/schemas/CompressPresetRequest",
            "image_to_pdf": "#/components/schemas/ImageToPdfPresetRequest",
            "pdf_to_image": "#/components/schemas/PdfToImagePresetRequest",
            "office_to_pdf": "#/components/schemas/OfficeToPdfPresetRequest",
            "ocr": "#/components/schemas/OcrPresetRequest",
            "watermark": "#/components/schemas/WatermarkPresetRequest",
            "page_numbers": "#/components/schemas/PageNumbersPresetRequest",
            "protect": "#/components/schemas/ProtectPresetRequest",
            "unlock": "#/components/schemas/UnlockPresetRequest",
            "annotate": "#/components/schemas/AnnotatePresetRequest"
          }
        },
        "description": "Aucun fichier ni secret. Un préréglage annotate contenant une image_asset_id est refusé ; seules les annotations autonomes sont enregistrables."
      },
      "Estimate": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "intent_sha256": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "pricing_version": {
            "type": "string"
          },
          "maximum_units": {
            "type": "integer",
            "minimum": 0,
            "description": "DU entières ; pas une valeur monétaire."
          },
          "region": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "warnings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Warning"
            }
          },
          "requires_secret": {
            "type": "boolean"
          },
          "execution_available": {
            "type": "boolean",
            "description": "Indique si le traitement peut être lancé. Une estimation ne réserve aucune unité ; consultez les opérations disponibles dans /v1/capabilities."
          },
          "maximum_ocr_pages": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "id",
          "intent_sha256",
          "pricing_version",
          "maximum_units",
          "region",
          "created_at",
          "expires_at",
          "warnings",
          "requires_secret",
          "execution_available",
          "maximum_ocr_pages"
        ]
      },
      "Job": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "$ref": "#/components/schemas/JobStatus"
          },
          "intent": {
            "$ref": "#/components/schemas/ProcessingIntent"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "maximum_units": {
            "type": "integer",
            "minimum": 0,
            "description": "DU entières ; pas une valeur monétaire."
          },
          "consumed_units": {
            "type": "integer",
            "minimum": 0,
            "description": "DU entières ; pas une valeur monétaire."
          },
          "output_assets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Asset"
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Warning"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "started_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Problem"
              },
              {
                "type": "null"
              }
            ]
          },
          "webhook_endpoint_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ]
          },
          "history_expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "Métadonnées conservées trente jours après terminaison. Aucun renouvellement des fichiers."
          },
          "decoration": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DecorationReport"
              },
              {
                "type": "null"
              }
            ]
          },
          "compression": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CompressionReport"
              },
              {
                "type": "null"
              }
            ]
          },
          "ocr": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/OcrReport"
              },
              {
                "type": "null"
              }
            ]
          },
          "conversion": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ConversionReport"
              },
              {
                "type": "null"
              }
            ]
          },
          "security": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SecurityReport"
              },
              {
                "type": "null"
              }
            ]
          },
          "maximum_ocr_pages": {
            "type": "integer",
            "minimum": 0
          },
          "consumed_ocr_pages": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "id",
          "status",
          "intent",
          "estimate_id",
          "maximum_units",
          "consumed_units",
          "output_assets",
          "warnings",
          "created_at"
        ]
      },
      "JobList": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Job"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "items",
          "next_cursor"
        ]
      },
      "DownloadLink": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "url",
          "expires_at"
        ],
        "description": "URL HTTPS signée, valable au plus 60 s. Ne pas enregistrer dans une trace ou un événement."
      },
      "Preset": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "operation": {
            "$ref": "#/components/schemas/OperationName"
          },
          "parameters": {
            "type": "object",
            "additionalProperties": true
          },
          "contract_version": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "revision": {
            "type": "integer",
            "minimum": 1
          }
        },
        "required": [
          "id",
          "name",
          "operation",
          "parameters",
          "contract_version",
          "created_at",
          "updated_at",
          "revision"
        ]
      },
      "ManifestAsset": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "asset_id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": [
              "input",
              "auxiliary",
              "document",
              "text",
              "page_image"
            ]
          },
          "sha256": {
            "type": "string"
          },
          "byte_size": {
            "type": "integer",
            "minimum": 0
          },
          "page_count": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1
          },
          "mime_type": {
            "type": "string",
            "enum": [
              "application/pdf",
              "image/png",
              "image/jpeg",
              "text/plain"
            ]
          },
          "properties": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PdfGeometry"
              },
              {
                "$ref": "#/components/schemas/ImageGeometry"
              },
              {
                "type": "object",
                "additionalProperties": false,
                "properties": {},
                "required": []
              },
              {
                "$ref": "#/components/schemas/OfficeProperties"
              },
              {
                "$ref": "#/components/schemas/TextProperties"
              },
              {
                "$ref": "#/components/schemas/ProtectedPdfGeometry"
              },
              {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "encrypted_unverified": {
                    "const": true
                  }
                },
                "required": [
                  "encrypted_unverified"
                ]
              }
            ]
          }
        },
        "required": [
          "asset_id",
          "kind",
          "sha256",
          "byte_size",
          "page_count"
        ]
      },
      "Manifest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "operation": {
            "$ref": "#/components/schemas/OperationName"
          },
          "parameters": {
            "type": "object",
            "additionalProperties": true
          },
          "contract_version": {
            "type": "string"
          },
          "assets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ManifestAsset"
            }
          },
          "provenance": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "output_asset_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "pages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "properties": {
                          "input_asset_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "page": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "additional_rotation": {
                            "type": "integer",
                            "enum": [
                              0,
                              90,
                              180,
                              270
                            ]
                          }
                        },
                        "required": [
                          "input_asset_id",
                          "page",
                          "additional_rotation"
                        ]
                      }
                    },
                    "additions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "properties": {
                          "annotation_index": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "page": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "text",
                              "image",
                              "stroke"
                            ]
                          },
                          "image_asset_id": {
                            "type": "string",
                            "format": "uuid"
                          }
                        },
                        "required": [
                          "annotation_index",
                          "page",
                          "type"
                        ]
                      },
                      "maxItems": 100
                    }
                  },
                  "required": [
                    "output_asset_id",
                    "pages"
                  ]
                },
                {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "output_asset_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "mapping": {
                      "const": "document"
                    },
                    "source_document_asset_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "pages": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "properties": {},
                        "required": []
                      },
                      "maxItems": 0
                    }
                  },
                  "required": [
                    "output_asset_id",
                    "mapping",
                    "source_document_asset_id",
                    "pages"
                  ]
                }
              ],
              "description": "Office : relation au document source, sans inventer de pagination d’entrée. PDF/images : relation page par page."
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Warning"
            }
          },
          "maximum_units": {
            "type": "integer",
            "minimum": 0,
            "description": "DU entières ; pas une valeur monétaire."
          },
          "consumed_units": {
            "type": "integer",
            "minimum": 0,
            "description": "DU entières ; pas une valeur monétaire."
          },
          "completed_at": {
            "type": "string",
            "format": "date-time"
          },
          "decoration": {
            "$ref": "#/components/schemas/DecorationReport"
          },
          "compression": {
            "$ref": "#/components/schemas/CompressionReport"
          },
          "conversion": {
            "$ref": "#/components/schemas/ConversionReport"
          },
          "ocr": {
            "$ref": "#/components/schemas/OcrReport"
          },
          "maximum_ocr_pages": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "consumed_ocr_pages": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "security": {
            "$ref": "#/components/schemas/SecurityReport"
          }
        },
        "required": [
          "job_id",
          "operation",
          "parameters",
          "contract_version",
          "assets",
          "provenance",
          "warnings",
          "maximum_units",
          "consumed_units",
          "completed_at"
        ]
      },
      "CompressionReport": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "profile": {
            "type": "string",
            "enum": [
              "light",
              "balanced",
              "strong"
            ]
          },
          "input_bytes": {
            "type": "integer",
            "minimum": 1
          },
          "output_bytes": {
            "type": "integer",
            "minimum": 1
          },
          "target_bytes": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "maximum": 104857600
          },
          "target_met": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "original_retained": {
            "type": "boolean"
          },
          "lossless": {
            "const": true,
            "type": "boolean"
          },
          "image_resampling": {
            "const": false,
            "type": "boolean"
          },
          "minimum_image_dpi": {
            "type": "integer",
            "minimum": 72,
            "maximum": 300
          }
        },
        "required": [
          "profile",
          "input_bytes",
          "output_bytes",
          "target_bytes",
          "target_met",
          "original_retained",
          "lossless",
          "image_resampling",
          "minimum_image_dpi"
        ]
      },
      "DecorationReport": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "type": "string",
            "enum": [
              "watermark",
              "page_numbers",
              "annotate"
            ]
          },
          "selected_pages": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            },
            "minItems": 1,
            "maxItems": 500,
            "uniqueItems": true,
            "description": "Pages base 1. Absence du champ : toutes les pages admissibles. Une page inexistante est refusée."
          },
          "annotation_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "coordinate_space": {
            "const": "cropbox_unrotated_bottom_left"
          },
          "flattened": {
            "const": true
          }
        },
        "required": [
          "operation",
          "selected_pages",
          "annotation_count",
          "coordinate_space",
          "flattened"
        ]
      },
      "PdfGeometry": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "pages": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "media_box": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  },
                  "minItems": 4,
                  "maxItems": 4
                },
                "crop_box": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  },
                  "minItems": 4,
                  "maxItems": 4
                },
                "rotation": {
                  "type": "integer",
                  "enum": [
                    0,
                    90,
                    180,
                    270
                  ]
                },
                "user_unit": {
                  "type": "number",
                  "exclusiveMinimum": 0
                }
              },
              "required": [
                "media_box",
                "crop_box",
                "rotation",
                "user_unit"
              ]
            },
            "maxItems": 500
          }
        },
        "required": [
          "pages"
        ]
      },
      "ImageGeometry": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "width": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20000
          },
          "height": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20000
          },
          "pixel_count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20000000
          },
          "native_width": {
            "type": "integer",
            "minimum": 1
          },
          "native_height": {
            "type": "integer",
            "minimum": 1
          },
          "orientation": {
            "type": "integer",
            "minimum": 1,
            "maximum": 8
          },
          "frame_count": {
            "const": 1
          },
          "has_alpha": {
            "type": "boolean"
          },
          "icc_profile": {
            "type": "boolean"
          },
          "color_mode": {
            "type": "string"
          }
        },
        "required": [
          "width",
          "height",
          "pixel_count",
          "native_width",
          "native_height",
          "orientation",
          "frame_count",
          "has_alpha",
          "icc_profile",
          "color_mode"
        ]
      },
      "ConversionReport": {
        "oneOf": [
          {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "operation": {
                "const": "image_to_pdf"
              },
              "input_images": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ImageGeometry"
                },
                "minItems": 1,
                "maxItems": 20
              }
            },
            "required": [
              "operation",
              "input_images"
            ]
          },
          {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "operation": {
                "const": "pdf_to_image"
              },
              "source_pages": {
                "type": "array",
                "items": {
                  "type": "integer",
                  "minimum": 1
                },
                "minItems": 1,
                "maxItems": 100,
                "uniqueItems": true,
                "description": "Pages base 1. Absence du champ : toutes les pages admissibles. Une page inexistante est refusée."
              },
              "dpi": {
                "type": "integer",
                "minimum": 72,
                "maximum": 200
              },
              "pixel_count": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100000000
              }
            },
            "required": [
              "operation",
              "source_pages",
              "dpi",
              "pixel_count"
            ]
          },
          {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "operation": {
                "const": "office_to_pdf"
              },
              "format": {
                "type": "string",
                "enum": [
                  "docx",
                  "xlsx",
                  "pptx"
                ]
              },
              "source_properties": {
                "$ref": "#/components/schemas/OfficeProperties"
              },
              "output_pages": {
                "type": "integer",
                "minimum": 1,
                "maximum": 500
              },
              "spreadsheet_fit_width": {
                "type": "boolean"
              },
              "font_substitutions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "requested": {
                      "type": "string"
                    },
                    "resolved": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "requested",
                    "resolved"
                  ]
                },
                "maxItems": 128
              },
              "macro_execution": {
                "const": "never"
              },
              "external_update": {
                "const": "never"
              }
            },
            "required": [
              "operation",
              "format",
              "source_properties",
              "output_pages",
              "spreadsheet_fit_width",
              "font_substitutions",
              "macro_execution",
              "external_update"
            ]
          }
        ]
      },
      "OfficeProperties": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "office_format": {
            "type": "string",
            "enum": [
              "docx",
              "xlsx",
              "pptx"
            ]
          },
          "archive_entries": {
            "type": "integer",
            "minimum": 3,
            "maximum": 2000
          },
          "expanded_bytes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 209715200
          },
          "declared_fonts": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "maxItems": 128,
            "uniqueItems": true
          },
          "has_notes": {
            "type": "boolean"
          },
          "has_hidden_content": {
            "type": "boolean"
          },
          "sheet_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10
          },
          "slide_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "cell_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100000
          },
          "embedded_pixels": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100000000
          }
        },
        "required": [
          "office_format",
          "archive_entries",
          "expanded_bytes",
          "declared_fonts",
          "has_notes",
          "has_hidden_content",
          "sheet_count",
          "slide_count",
          "cell_count",
          "embedded_pixels"
        ]
      },
      "TextProperties": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "encoding": {
            "const": "UTF-8"
          },
          "character_count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10485760
          }
        },
        "required": [
          "encoding",
          "character_count"
        ]
      },
      "OcrReport": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "operation": {
            "const": "ocr"
          },
          "strategy": {
            "const": "skip_text"
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "fra",
                "eng"
              ]
            },
            "minItems": 1,
            "maxItems": 2,
            "uniqueItems": true
          },
          "deskew": {
            "type": "boolean"
          },
          "minimum_dpi": {
            "const": 300
          },
          "maximum_dpi": {
            "const": 400
          },
          "selected_pages": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            },
            "maxItems": 100,
            "uniqueItems": true
          },
          "processed_pages": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            },
            "maxItems": 100,
            "uniqueItems": true
          },
          "skipped_text_pages": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            },
            "maxItems": 100,
            "uniqueItems": true
          },
          "no_text_pages": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            },
            "maxItems": 100,
            "uniqueItems": true
          },
          "input_has_text": {
            "type": "array",
            "items": {
              "type": "boolean"
            },
            "maxItems": 500
          },
          "text_sha256": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          },
          "text_characters": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10485760
          }
        },
        "required": [
          "operation",
          "strategy",
          "languages",
          "deskew",
          "minimum_dpi",
          "maximum_dpi",
          "selected_pages",
          "processed_pages",
          "skipped_text_pages",
          "no_text_pages",
          "input_has_text",
          "text_sha256",
          "text_characters"
        ]
      },
      "UploadRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "file_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "declared_mime_type": {
            "type": "string"
          },
          "byte_size": {
            "type": "integer",
            "minimum": 1,
            "maximum": 104857600
          },
          "sha256": {
            "type": "string",
            "pattern": "^[a-f0-9]{64}$"
          }
        },
        "required": [
          "file_name",
          "declared_mime_type",
          "byte_size"
        ]
      },
      "Upload": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "upload_id": {
            "type": "string",
            "format": "uuid"
          },
          "asset_id": {
            "type": "string",
            "format": "uuid"
          },
          "part_size_bytes": {
            "type": "integer",
            "minimum": 5242880
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "byte_size": {
            "type": "integer",
            "minimum": 1,
            "maximum": 104857600
          },
          "expected_sha256": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "initiating",
              "uploading",
              "completing",
              "completed",
              "aborted"
            ]
          },
          "parts": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "part_number": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 20
                },
                "etag": {
                  "type": "string"
                },
                "byte_size": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 5242880
                }
              },
              "required": [
                "part_number",
                "etag",
                "byte_size"
              ]
            }
          }
        },
        "required": [
          "upload_id",
          "asset_id",
          "part_size_bytes",
          "expires_at",
          "byte_size",
          "expected_sha256",
          "state",
          "parts"
        ]
      },
      "UploadPart": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "part_number": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "byte_size": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5242880
          }
        },
        "required": [
          "part_number",
          "url",
          "expires_at"
        ]
      },
      "CompletedPart": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "part_number": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000
          },
          "etag": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "part_number",
          "etag"
        ]
      },
      "SecretRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "purpose": {
            "type": "string",
            "enum": [
              "input_password",
              "output_password"
            ]
          },
          "value": {
            "type": "string",
            "minLength": 1,
            "maxLength": 127,
            "writeOnly": true,
            "description": "1–127 octets UTF-8 pour input_password ; 12–127 pour output_password. Sans contrôles ASCII. Limite en octets vérifiée au serveur ; valeur jamais renvoyée."
          }
        },
        "required": [
          "purpose",
          "value"
        ]
      },
      "SecurityReport": {
        "oneOf": [
          {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "operation": {
                "const": "protect"
              },
              "algorithm": {
                "const": "AES-256"
              },
              "revision": {
                "const": 6,
                "type": "integer"
              },
              "page_count": {
                "type": "integer",
                "minimum": 1,
                "maximum": 500
              },
              "output_encrypted": {
                "const": true
              },
              "password_verified": {
                "const": true
              },
              "empty_password_rejected": {
                "const": true
              },
              "metadata_encrypted": {
                "const": true
              }
            },
            "required": [
              "operation",
              "algorithm",
              "revision",
              "page_count",
              "output_encrypted",
              "password_verified",
              "empty_password_rejected",
              "metadata_encrypted"
            ]
          },
          {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "operation": {
                "const": "unlock"
              },
              "algorithm": {
                "const": "AES-256"
              },
              "revision": {
                "const": 6,
                "type": "integer"
              },
              "page_count": {
                "type": "integer",
                "minimum": 1,
                "maximum": 500
              },
              "output_encrypted": {
                "const": false
              },
              "password_verified": {
                "const": true
              },
              "empty_password_rejected": {
                "const": null
              },
              "metadata_encrypted": {
                "type": "boolean"
              }
            },
            "required": [
              "operation",
              "algorithm",
              "revision",
              "page_count",
              "output_encrypted",
              "password_verified",
              "empty_password_rejected",
              "metadata_encrypted"
            ]
          },
          {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "operation": {
                "const": "unlock"
              },
              "algorithm": {
                "const": "AES-128"
              },
              "revision": {
                "const": 4,
                "type": "integer"
              },
              "page_count": {
                "type": "integer",
                "minimum": 1,
                "maximum": 500
              },
              "output_encrypted": {
                "const": false
              },
              "password_verified": {
                "const": true
              },
              "empty_password_rejected": {
                "const": null
              },
              "metadata_encrypted": {
                "type": "boolean"
              }
            },
            "required": [
              "operation",
              "algorithm",
              "revision",
              "page_count",
              "output_encrypted",
              "password_verified",
              "empty_password_rejected",
              "metadata_encrypted"
            ]
          }
        ]
      },
      "ProtectedPdfGeometry": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "pages": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "media_box": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  },
                  "minItems": 4,
                  "maxItems": 4
                },
                "crop_box": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  },
                  "minItems": 4,
                  "maxItems": 4
                },
                "rotation": {
                  "type": "integer",
                  "enum": [
                    0,
                    90,
                    180,
                    270
                  ]
                },
                "user_unit": {
                  "type": "number",
                  "exclusiveMinimum": 0
                }
              },
              "required": [
                "media_box",
                "crop_box",
                "rotation",
                "user_unit"
              ]
            },
            "maxItems": 500
          },
          "encryption": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "algorithm": {
                "const": "AES-256"
              },
              "revision": {
                "const": 6
              }
            },
            "required": [
              "algorithm",
              "revision"
            ]
          }
        },
        "required": [
          "pages",
          "encryption"
        ]
      },
      "SecretRef": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "secret_ref": {
            "type": "string",
            "format": "uuid"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "secret_ref",
          "expires_at"
        ],
        "description": "Cinq minutes pour associer la référence à un seul job ; disponibilité ensuite limitée au job et à 30 minutes maximum. Valeur jamais renvoyée."
      },
      "ApiKey": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "prefix": {
            "type": "string",
            "pattern": "^dko_test_[A-Za-z0-9_-]{8}$"
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Scope"
            },
            "minItems": 1,
            "maxItems": 7,
            "uniqueItems": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "expired",
              "revoked"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "prefix",
          "scopes",
          "status",
          "created_at",
          "expires_at",
          "revoked_at",
          "last_used_at"
        ]
      },
      "NewApiKey": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "key": {
            "type": "string",
            "description": "Affichée une seule fois, à protéger et exclure des journaux."
          },
          "metadata": {
            "$ref": "#/components/schemas/ApiKey"
          }
        },
        "required": [
          "key",
          "metadata"
        ]
      },
      "WebhookEndpoint": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "job.succeeded",
                "job.failed",
                "job.canceled"
              ]
            },
            "minItems": 1,
            "uniqueItems": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "disabled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "status",
          "created_at",
          "disabled_at"
        ]
      },
      "NewWebhookEndpoint": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "endpoint": {
            "$ref": "#/components/schemas/WebhookEndpoint"
          },
          "signing_secret": {
            "type": "string",
            "description": "Affiché une seule fois. Le serveur conserve une valeur chiffrée pour HMAC."
          }
        },
        "required": [
          "endpoint",
          "signing_secret"
        ]
      },
      "WebhookAttempt": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "attempt": {
            "type": "integer",
            "minimum": 1,
            "maximum": 6
          },
          "started_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "http_status": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 100,
            "maximum": 599
          },
          "error_code": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "attempt",
          "started_at",
          "completed_at",
          "http_status",
          "error_code"
        ]
      },
      "WebhookDelivery": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "event_id": {
            "type": "string",
            "format": "uuid"
          },
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": [
              "job.succeeded",
              "job.failed",
              "job.canceled"
            ]
          },
          "attempt": {
            "type": "integer",
            "minimum": 0,
            "maximum": 6
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "delivering",
              "delivered",
              "exhausted",
              "canceled"
            ]
          },
          "http_status": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 100,
            "maximum": 599
          },
          "error_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_attempt_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "next_attempt_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "finished_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "attempts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookAttempt"
            },
            "maxItems": 6
          }
        },
        "required": [
          "event_id",
          "job_id",
          "type",
          "attempt",
          "status",
          "http_status",
          "error_code",
          "created_at",
          "last_attempt_at",
          "next_attempt_at",
          "finished_at",
          "attempts"
        ]
      },
      "WebhookEvent": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "event_id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": [
              "job.succeeded",
              "job.failed",
              "job.canceled"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "succeeded",
              "failed",
              "canceled"
            ]
          },
          "consumed_units": {
            "type": "integer",
            "minimum": 0,
            "description": "DU entières ; pas une valeur monétaire."
          },
          "output_asset_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "error_code": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "event_id",
          "type",
          "created_at",
          "workspace_id",
          "job_id",
          "status",
          "consumed_units",
          "output_asset_ids",
          "error_code"
        ]
      },
      "Usage": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "period_start": {
            "type": "string",
            "format": "date-time"
          },
          "period_end": {
            "type": "string",
            "format": "date-time"
          },
          "plan": {
            "type": "string"
          },
          "limit_units": {
            "type": "integer",
            "minimum": 0,
            "description": "DU entières ; pas une valeur monétaire."
          },
          "reserved_units": {
            "type": "integer",
            "minimum": 0,
            "description": "DU entières ; pas une valeur monétaire."
          },
          "consumed_units": {
            "type": "integer",
            "minimum": 0,
            "description": "DU entières ; pas une valeur monétaire."
          },
          "available_units": {
            "type": "integer",
            "minimum": 0,
            "description": "DU entières ; pas une valeur monétaire."
          },
          "pricing_version": {
            "type": "string"
          },
          "limit_ocr_pages": {
            "type": "integer",
            "minimum": 0
          },
          "reserved_ocr_pages": {
            "type": "integer",
            "minimum": 0
          },
          "consumed_ocr_pages": {
            "type": "integer",
            "minimum": 0
          },
          "daily_limit_jobs": {
            "type": "integer",
            "minimum": 0
          },
          "daily_accepted_jobs": {
            "type": "integer",
            "minimum": 0
          },
          "daily_reset_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "period_start",
          "period_end",
          "plan",
          "limit_units",
          "reserved_units",
          "consumed_units",
          "available_units",
          "pricing_version",
          "limit_ocr_pages",
          "reserved_ocr_pages",
          "consumed_ocr_pages",
          "daily_limit_jobs",
          "daily_accepted_jobs",
          "daily_reset_at"
        ]
      },
      "UsageEntry": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "reserve",
              "commit",
              "release"
            ]
          },
          "units": {
            "type": "integer",
            "minimum": 0,
            "description": "DU entières ; pas une valeur monétaire."
          },
          "ocr_pages": {
            "type": "integer",
            "minimum": 0
          },
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "period_start": {
            "type": "string",
            "format": "date-time"
          },
          "period_end": {
            "type": "string",
            "format": "date-time"
          },
          "pricing_version": {
            "type": "string"
          }
        },
        "required": [
          "kind",
          "units",
          "ocr_pages",
          "job_id",
          "created_at",
          "period_start",
          "period_end",
          "pricing_version"
        ]
      },
      "Capabilities": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "contract_version": {
            "type": "string"
          },
          "operations": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "name": {
                  "$ref": "#/components/schemas/OperationName"
                },
                "execution_modes": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "local",
                      "cloud"
                    ]
                  },
                  "minItems": 1
                },
                "input_mime_types": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "maximum_input_count": {
                  "type": "integer",
                  "minimum": 1
                },
                "maximum_file_bytes": {
                  "type": "integer",
                  "minimum": 1
                },
                "maximum_total_input_bytes": {
                  "type": "integer",
                  "minimum": 1
                },
                "maximum_total_pages": {
                  "type": "integer",
                  "minimum": 1
                },
                "maximum_execution_seconds": {
                  "type": "integer",
                  "minimum": 1
                }
              },
              "required": [
                "name",
                "execution_modes",
                "input_mime_types",
                "maximum_input_count",
                "maximum_file_bytes",
                "maximum_total_input_bytes",
                "maximum_total_pages",
                "maximum_execution_seconds"
              ]
            }
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "fra",
                "eng"
              ]
            }
          },
          "default_retention_seconds": {
            "type": "integer",
            "minimum": 1
          },
          "notice": {
            "type": "string"
          },
          "cloud_planning": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "operations": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "merge",
                    "split",
                    "organize",
                    "compress",
                    "image_to_pdf",
                    "pdf_to_image",
                    "office_to_pdf",
                    "ocr",
                    "watermark",
                    "page_numbers",
                    "annotate",
                    "protect",
                    "unlock"
                  ]
                }
              },
              "execution_available": {
                "type": "boolean"
              },
              "executable_operations": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "merge",
                    "split",
                    "organize",
                    "compress",
                    "image_to_pdf",
                    "pdf_to_image",
                    "office_to_pdf",
                    "ocr",
                    "watermark",
                    "page_numbers",
                    "annotate",
                    "protect",
                    "unlock"
                  ]
                }
              }
            },
            "required": [
              "operations",
              "execution_available",
              "executable_operations"
            ]
          },
          "cloud_processing": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "operations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "name": {
                      "$ref": "#/components/schemas/OperationName"
                    },
                    "execution_modes": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "local",
                          "cloud"
                        ]
                      },
                      "minItems": 1
                    },
                    "input_mime_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "maximum_input_count": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "maximum_file_bytes": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "maximum_total_input_bytes": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "maximum_total_pages": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "maximum_execution_seconds": {
                      "type": "integer",
                      "minimum": 1
                    }
                  },
                  "required": [
                    "name",
                    "execution_modes",
                    "input_mime_types",
                    "maximum_input_count",
                    "maximum_file_bytes",
                    "maximum_total_input_bytes",
                    "maximum_total_pages",
                    "maximum_execution_seconds"
                  ]
                }
              },
              "compression": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "profiles": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "light",
                        "balanced",
                        "strong"
                      ]
                    }
                  },
                  "lossless": {
                    "const": true
                  },
                  "image_resampling": {
                    "const": false
                  },
                  "maximum_target_bytes": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_units": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "DU entières ; pas une valeur monétaire."
                  },
                  "units_without_gain": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "DU entières ; pas une valeur monétaire."
                  }
                },
                "required": [
                  "profiles",
                  "lossless",
                  "image_resampling",
                  "maximum_target_bytes",
                  "maximum_units",
                  "units_without_gain"
                ]
              },
              "security": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "encrypt_algorithm": {
                    "const": "AES-256"
                  },
                  "encrypt_revision": {
                    "const": 6
                  },
                  "unlock_profiles": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "AES-256-R6",
                        "AES-128-R4"
                      ]
                    }
                  },
                  "maximum_secret_bytes": {
                    "const": 127
                  },
                  "minimum_output_secret_bytes": {
                    "const": 12
                  },
                  "reference_attach_seconds": {
                    "const": 300
                  },
                  "reference_maximum_seconds": {
                    "const": 1800
                  },
                  "maximum_unbound_secrets": {
                    "const": 10
                  },
                  "maximum_units": {
                    "const": 1
                  },
                  "secret_endpoint": {
                    "const": "/v1/secrets"
                  }
                },
                "required": [
                  "encrypt_algorithm",
                  "encrypt_revision",
                  "unlock_profiles",
                  "maximum_secret_bytes",
                  "minimum_output_secret_bytes",
                  "reference_attach_seconds",
                  "reference_maximum_seconds",
                  "maximum_unbound_secrets",
                  "maximum_units",
                  "secret_endpoint"
                ]
              },
              "decoration": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "operations": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "watermark",
                        "page_numbers",
                        "annotate"
                      ]
                    }
                  },
                  "coordinate_space": {
                    "const": "cropbox_unrotated_bottom_left"
                  },
                  "maximum_annotations": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_points_per_stroke": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_total_points": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_auxiliary_images": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_auxiliary_pixels": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_units": {
                    "const": 1
                  },
                  "flattened": {
                    "const": true
                  },
                  "drawn_signature": {
                    "const": "visual_only"
                  }
                },
                "required": [
                  "operations",
                  "coordinate_space",
                  "maximum_annotations",
                  "maximum_points_per_stroke",
                  "maximum_total_points",
                  "maximum_auxiliary_images",
                  "maximum_auxiliary_pixels",
                  "maximum_units",
                  "flattened",
                  "drawn_signature"
                ]
              },
              "images": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "input_formats": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "jpeg",
                        "png",
                        "webp"
                      ]
                    }
                  },
                  "output_formats": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "jpeg",
                        "png"
                      ]
                    }
                  },
                  "maximum_pixels_per_image": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_dimension": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_output_count": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_total_pixels": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_total_output_bytes": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "minimum_dpi": {
                    "type": "integer",
                    "minimum": 72
                  },
                  "maximum_dpi": {
                    "type": "integer",
                    "minimum": 72
                  },
                  "animated_images": {
                    "const": false
                  },
                  "archive": {
                    "const": "zip"
                  },
                  "maximum_units": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "DU entières ; pas une valeur monétaire."
                  }
                },
                "required": [
                  "input_formats",
                  "output_formats",
                  "maximum_pixels_per_image",
                  "maximum_dimension",
                  "maximum_output_count",
                  "maximum_total_pixels",
                  "maximum_total_output_bytes",
                  "minimum_dpi",
                  "maximum_dpi",
                  "animated_images",
                  "archive",
                  "maximum_units"
                ]
              },
              "office": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "input_formats": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "docx",
                        "xlsx",
                        "pptx"
                      ]
                    }
                  },
                  "maximum_file_bytes": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_expanded_bytes": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_archive_entries": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_units": {
                    "const": 2
                  },
                  "macros": {
                    "const": false
                  },
                  "external_content": {
                    "const": false
                  },
                  "spreadsheet_fit_width": {
                    "const": true
                  },
                  "page_count_before_conversion": {
                    "type": "null"
                  }
                },
                "required": [
                  "input_formats",
                  "maximum_file_bytes",
                  "maximum_expanded_bytes",
                  "maximum_archive_entries",
                  "maximum_units",
                  "macros",
                  "external_content",
                  "spreadsheet_fit_width",
                  "page_count_before_conversion"
                ]
              },
              "ocr": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "languages": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "fra",
                        "eng"
                      ]
                    }
                  },
                  "strategy": {
                    "const": "skip_text"
                  },
                  "maximum_selected_pages": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_pixels_per_page": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_total_pixels": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "minimum_dpi": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_dpi": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "maximum_text_bytes": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "units_per_processed_page": {
                    "const": 1
                  },
                  "units_per_skipped_page": {
                    "const": 0
                  },
                  "outputs": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "application/pdf",
                        "text/plain"
                      ]
                    }
                  }
                },
                "required": [
                  "languages",
                  "strategy",
                  "maximum_selected_pages",
                  "maximum_pixels_per_page",
                  "maximum_total_pixels",
                  "minimum_dpi",
                  "maximum_dpi",
                  "maximum_text_bytes",
                  "units_per_processed_page",
                  "units_per_skipped_page",
                  "outputs"
                ]
              }
            },
            "required": [
              "enabled",
              "operations"
            ]
          }
        },
        "required": [
          "contract_version",
          "operations",
          "languages",
          "default_retention_seconds",
          "notice"
        ]
      }
    }
  }
}
