{
  "openapi": "3.0.3",
  "info": {
    "title": "API Partenaire Firma",
    "description": "API RESTful pour la signature de documents et la gestion de mod\u00e8les.\n\n**Authentification** : Tous les endpoints n\u00e9cessitent une authentification par cl\u00e9 API via l'en-t\u00eate `Authorization`. Utilisez votre cl\u00e9 API directement sans pr\u00e9fixe (par exemple, `your-api-key`). Le pr\u00e9fixe Bearer est optionnel mais pas obligatoire.\n\n**Fonctionnalit\u00e9s de s\u00e9curit\u00e9** :\n- Validation des entr\u00e9es avec des sch\u00e9mas Zod incluant des messages d'erreur d\u00e9taill\u00e9s au niveau des champs\n- Jetons JWT sign\u00e9s RSA-256 pour l'acc\u00e8s aux mod\u00e8les int\u00e9gr\u00e9s\n\n**Limitation de d\u00e9bit** : Les limites de d\u00e9bit sont hi\u00e9rarchis\u00e9es selon le type d'op\u00e9ration :\n- Op\u00e9rations de lecture (GET) : 200 requ\u00eates par minute\n- Op\u00e9rations d'\u00e9criture (POST/PUT/PATCH/DELETE) : 120 requ\u00eates par minute\n- Op\u00e9rations CRUD sur les webhooks : 60 requ\u00eates par minute\n- Test de webhook : 10 requ\u00eates par minute\n- R\u00e9g\u00e9n\u00e9ration/expiration de cl\u00e9 API : 1 requ\u00eate par minute\n- Rotation du secret de webhook : 1 requ\u00eate par minute\n\nLorsque les limites de d\u00e9bit sont d\u00e9pass\u00e9es, l'API renvoie une r\u00e9ponse `429 Too Many Requests` avec les en-t\u00eates suivants :\n- `X-RateLimit-Limit` : Nombre maximal de requ\u00eates par minute pour cet endpoint\n- `X-RateLimit-Remaining` : Requ\u00eates restantes dans la fen\u00eatre actuelle\n- `X-RateLimit-Reset` : Horodatage Unix de la r\u00e9initialisation de la limite\n- `Retry-After` : Secondes \u00e0 attendre avant de pouvoir r\u00e9essayer\n\n**Gestion des erreurs** : Toutes les erreurs renvoient des r\u00e9ponses JSON structur\u00e9es avec `error` (message lisible par un humain), `code` (identifiant lisible par une machine) et `details` (erreurs de validation au niveau des champs, le cas \u00e9ch\u00e9ant).\n\n**Int\u00e9gration de l'\u00c9diteur de Mod\u00e8les int\u00e9gr\u00e9** : L'\u00c9diteur de Mod\u00e8les Firma peut \u00eatre int\u00e9gr\u00e9 dans votre application \u00e0 l'aide d'une biblioth\u00e8que JavaScript autonome.\n\n```html\n<!-- Charger la biblioth\u00e8que de l'\u00c9diteur de Mod\u00e8les Firma -->\n<script src=\"https://api.firma.dev/functions/v1/embed-proxy/template-editor.js\"></script>\n\n<script>\n// G\u00e9n\u00e9rer d'abord un jeton JWT via l'API\nfetch('https://api.firma.dev/functions/v1/signing-request-api/generate-template-token', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'YOUR_API_KEY',\n    'Content-Type': 'application/json'\n  },\n  body: JSON.stringify({\n    companies_workspaces_templates_id: 'template-id'\n  })\n})\n.then(res => res.json())\n.then(data => {\n  // Initialiser l'\u00e9diteur avec le jeton JWT\n  window.FirmaTemplateEditor.init({\n    container: '#firma-editor-container',\n    jwt: data.token,\n    templateId: 'template-id',\n    theme: 'dark',\n    readOnly: false,\n    onSave: (savedData) => {\n      console.log('Template saved:', savedData);\n    },\n    onError: (error) => {\n      console.error('Editor error:', error);\n    },\n    onLoad: (template) => {\n      console.log('Template loaded:', template);\n    }\n  });\n});\n</script>\n```",
    "version": "01.35.00",
    "contact": {
      "name": "API Support",
      "url": "https://firma.com/support"
    }
  },
  "servers": [
    {
      "url": "https://api.firma.dev/functions/v1/signing-request-api",
      "description": "API de Production - Recommand\u00e9e (Actuelle)"
    },
    {
      "url": "https://api.firma.dev/api/v1",
      "description": "API de Production - Pr\u00e9vue"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Company",
      "description": "Informations et param\u00e8tres de l'entreprise"
    },
    {
      "name": "Workspaces",
      "description": "Op\u00e9rations de gestion des Espaces de Travail"
    },
    {
      "name": "Templates",
      "description": "Op\u00e9rations de gestion des Mod\u00e8les"
    },
    {
      "name": "Signing Requests",
      "description": "Op\u00e9rations de Demande de Signature de documents"
    },
    {
      "name": "Custom Fields",
      "description": "Gestion des d\u00e9finitions de champs personnalis\u00e9s pour les espaces de travail, mod\u00e8les et demandes de signature"
    },
    {
      "name": "Webhooks",
      "description": "Configuration et gestion des webhooks"
    },
    {
      "name": "JWT Management",
      "description": "G\u00e9n\u00e9ration et r\u00e9vocation de jetons JWT pour les mod\u00e8les int\u00e9gr\u00e9s"
    },
    {
      "name": "Workspace Settings",
      "description": "Configuration et param\u00e8tres de l'espace de travail"
    },
    {
      "name": "Email Domains",
      "description": "Configuration et v\u00e9rification de domaine e-mail pour l'envoi d'e-mails de demande de signature depuis des domaines personnalis\u00e9s"
    },
    {
      "name": "Email Templates",
      "description": "Gestion des mod\u00e8les d'e-mail pour la personnalisation des notifications de demande de signature au niveau de l'espace de travail et de l'entreprise"
    },
    {
      "name": "Signer Terms",
      "description": "Conditions d'utilisation / d\u00e9clarations de consentement personnalis\u00e9es pour le signataire, au niveau de l'entreprise avec des surcharges par espace de travail et par langue"
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Cl\u00e9 API pour l'authentification. Utilisez votre cl\u00e9 API directement sans pr\u00e9fixe (par exemple, 'your-api-key'). Le pr\u00e9fixe Bearer est optionnel mais pas obligatoire."
      }
    },
    "responses": {
      "ValidationError": {
        "description": "Requ\u00eate Incorrecte - \u00c9chec de la validation",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Validation Error",
              "message": "Invalid input data",
              "details": {
                "name": "Name is required",
                "email": "Invalid email format"
              }
            }
          }
        }
      },
      "UnauthorizedError": {
        "description": "Non Autoris\u00e9 - Cl\u00e9 API invalide ou manquante",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Unauthorized",
              "message": "Invalid API key"
            }
          }
        }
      },
      "ForbiddenError": {
        "description": "Interdit - Permissions insuffisantes",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Forbidden",
              "message": "You do not have permission to access this resource"
            }
          }
        }
      },
      "NotFoundError": {
        "description": "Non Trouv\u00e9 - La ressource n'existe pas",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Not Found",
              "message": "The requested resource was not found"
            }
          }
        }
      },
      "RateLimitError": {
        "description": "Trop de requ\u00eates - Limite de d\u00e9bit d\u00e9pass\u00e9e",
        "headers": {
          "X-RateLimit-Limit": {
            "schema": {
              "type": "integer"
            },
            "description": "Nombre maximum de requ\u00eates par minute"
          },
          "X-RateLimit-Remaining": {
            "schema": {
              "type": "integer"
            },
            "description": "Requ\u00eates restantes"
          },
          "X-RateLimit-Reset": {
            "schema": {
              "type": "integer"
            },
            "description": "Timestamp Unix de la r\u00e9initialisation"
          },
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Secondes avant de pouvoir r\u00e9essayer"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Rate Limit Exceeded",
              "message": "Too many requests. Please wait before retrying.",
              "details": {
                "retry_after": 45
              }
            }
          }
        }
      }
    },
    "requestBodies": {
      "PatchSigningRequestBody": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/PatchSigningRequestBodySchema"
            },
            "examples": {
              "update-properties": {
                "summary": "Mettre \u00e0 jour les propri\u00e9t\u00e9s",
                "value": {
                  "name": "Updated Contract Name",
                  "expiration_hours": 72
                }
              },
              "update-recipient": {
                "summary": "Mettre \u00e0 jour un seul destinataire",
                "value": {
                  "recipient": {
                    "id": "rec123-e89b-12d3-a456-426614174000",
                    "first_name": "John",
                    "last_name": "Smith",
                    "email": "john.smith@example.com",
                    "designation": "Signer",
                    "order": 1
                  }
                }
              },
              "add-recipient": {
                "summary": "Ajouter un nouveau destinataire",
                "value": {
                  "recipient": {
                    "first_name": "Jane",
                    "last_name": "Doe",
                    "email": "jane@example.com",
                    "designation": "Signer",
                    "order": 2
                  }
                }
              },
              "add-date-field": {
                "summary": "Ajouter un champ date avec formatage",
                "value": {
                  "field": {
                    "type": "date",
                    "position": {
                      "x": 70,
                      "y": 45,
                      "width": 15,
                      "height": 3
                    },
                    "page_number": 1,
                    "required": true,
                    "recipient_id": "rec123-e89b-12d3-a456-426614174000",
                    "date_signing_default": true,
                    "format_rules": {
                      "dateFormat": "MMMM dd, yyyy"
                    }
                  }
                }
              },
              "add-read-only-static-field": {
                "summary": "Ajouter un champ en lecture seule avec valeur statique",
                "description": "Cr\u00e9e un champ texte qui affiche une valeur fixe que le signataire ne peut pas modifier",
                "value": {
                  "field": {
                    "type": "text",
                    "position": {
                      "x": 15,
                      "y": 20,
                      "width": 40,
                      "height": 3
                    },
                    "page_number": 1,
                    "required": false,
                    "recipient_id": "rec123-e89b-12d3-a456-426614174000",
                    "read_only": true,
                    "read_only_value": "Contract #12345 - Acme Corporation"
                  }
                }
              },
              "add-read-only-prefilled-field": {
                "summary": "Ajouter un champ en lecture seule avec les donn\u00e9es du destinataire",
                "description": "Cr\u00e9e un champ texte qui se remplit automatiquement avec l'adresse e-mail du destinataire (le signataire ne peut pas le modifier)",
                "value": {
                  "field": {
                    "type": "text",
                    "position": {
                      "x": 15,
                      "y": 30,
                      "width": 30,
                      "height": 3
                    },
                    "page_number": 1,
                    "required": false,
                    "recipient_id": "rec123-e89b-12d3-a456-426614174000",
                    "read_only": true,
                    "prefilled_data": "email"
                  }
                }
              }
            }
          }
        }
      },
      "UpdateSigningRequestBody": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/UpdateSigningRequestBodySchema"
            },
            "examples": {
              "comprehensive-update": {
                "summary": "Mise \u00e0 jour compl\u00e8te avec toutes les sections",
                "value": {
                  "signing_request_properties": {
                    "name": "Updated Contract Name",
                    "expiration_hours": 72
                  },
                  "recipients": [
                    {
                      "id": "rec1-e89b-12d3-a456-426614174000",
                      "first_name": "John",
                      "last_name": "Smith",
                      "email": "john.smith@example.com",
                      "designation": "Signer",
                      "order": 1
                    },
                    {
                      "first_name": "Jane",
                      "last_name": "Doe",
                      "email": "jane@example.com",
                      "designation": "Signer",
                      "order": 2
                    }
                  ],
                  "deleted_recipients": [
                    {
                      "recipient_id": "rec2-e89b-12d3-a456-426614174000",
                      "field_action": "reassign",
                      "reassign_to_recipient_id": "rec1-e89b-12d3-a456-426614174000"
                    }
                  ],
                  "fields": [
                    {
                      "id": "field1-e89b-12d3-a456-426614174000",
                      "type": "signature",
                      "position": {
                        "x": 15,
                        "y": 85,
                        "width": 30,
                        "height": 10
                      },
                      "page_number": 1,
                      "required": true,
                      "recipient_id": "rec1-e89b-12d3-a456-426614174000"
                    }
                  ],
                  "reminders": [
                    {
                      "hours": 48,
                      "all_users": true,
                      "subject": "Reminder: Please sign the document",
                      "message": "This is a reminder to complete your signature."
                    }
                  ]
                }
              },
              "update-with-temp-ids": {
                "summary": "Mise \u00e0 jour avec de nouveaux destinataires via des ID temporaires",
                "description": "Mise \u00e0 jour compl\u00e8te ajoutant de nouveaux destinataires avec des ID temporaires en plus des destinataires existants",
                "value": {
                  "signing_request_properties": {
                    "name": "Updated NDA Agreement"
                  },
                  "recipients": [
                    {
                      "id": "existing-recipient-uuid",
                      "email": "updated@example.com"
                    },
                    {
                      "_temp_id": "temp_new_signer",
                      "first_name": "New",
                      "last_name": "Signer",
                      "email": "newsigner@example.com",
                      "designation": "Signer",
                      "order": 2
                    }
                  ],
                  "fields": [
                    {
                      "id": "existing-field-uuid",
                      "position": {
                        "x": 10,
                        "y": 70,
                        "width": 30,
                        "height": 10
                      }
                    },
                    {
                      "recipient_id": "temp_new_signer",
                      "type": "signature",
                      "page_number": 1,
                      "position": {
                        "x": 10,
                        "y": 55,
                        "width": 30,
                        "height": 10
                      },
                      "required": true
                    }
                  ],
                  "reminders": [
                    {
                      "recipient_id": "temp_new_signer",
                      "hours": 24,
                      "all_users": false,
                      "subject": "Reminder: Sign Document",
                      "message": "Please sign the updated NDA."
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "Company": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique de l'entreprise"
          },
          "name": {
            "type": "string",
            "description": "Nom de l'entreprise",
            "maxLength": 255
          },
          "language": {
            "type": "string",
            "description": "Langue par d\u00e9faut de l'entreprise",
            "enum": [
              "en",
              "es",
              "it",
              "pt",
              "fr",
              "de",
              "el",
              "ru",
              "pl",
              "cs",
              "sv",
              "nl",
              "ro",
              "nb"
            ],
            "default": "en"
          },
          "account_owner": {
            "type": "string",
            "description": "Nom du propri\u00e9taire du compte",
            "maxLength": 255
          },
          "account_owner_email": {
            "type": "string",
            "format": "email",
            "description": "Adresse e-mail du propri\u00e9taire du compte"
          },
          "website": {
            "type": "string",
            "format": "uri",
            "description": "URL du site web de l'entreprise",
            "nullable": true
          },
          "icon_url": {
            "type": "string",
            "format": "uri",
            "description": "URL publiquement accessible vers le logo de l'entreprise. Retourne null si aucun logo n'est d\u00e9fini.",
            "nullable": true,
            "example": "https://ielmshcswdhuacyjlpiy.supabase.co/functions/v1/logo/company/3feb35a8-5aaf-4603-8b50-acd807176b38"
          },
          "credits": {
            "type": "integer",
            "description": "Cr\u00e9dits disponibles pour l'entreprise (lecture seule, g\u00e9r\u00e9 en interne)",
            "minimum": 0,
            "readOnly": true
          },
          "created_date": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp de cr\u00e9ation du compte entreprise"
          },
          "updated_date": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp de derni\u00e8re mise \u00e0 jour du compte entreprise"
          }
        },
        "required": [
          "id",
          "name",
          "account_owner",
          "account_owner_email",
          "created_date"
        ]
      },
      "Workspace": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique de l'espace de travail"
          },
          "name": {
            "type": "string",
            "description": "Nom de l'espace de travail",
            "maxLength": 255
          },
          "protected": {
            "type": "boolean",
            "description": "Les espaces de travail prot\u00e9g\u00e9s ne peuvent pas \u00eatre supprim\u00e9s"
          },
          "api_key": {
            "type": "string",
            "description": "Cl\u00e9 API en mode production pour cet espace de travail. Utilis\u00e9e pour authentifier les requ\u00eates API propres \u00e0 cet espace de travail.",
            "nullable": true
          },
          "test_api_key": {
            "type": "string",
            "description": "Cl\u00e9 API en mode test pour cet espace de travail. Les requ\u00eates authentifi\u00e9es avec cette cl\u00e9 ne consomment pas de cr\u00e9dits et produisent des demandes de signature marqu\u00e9es test et filigran\u00e9es.",
            "nullable": true
          },
          "created_date": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp de cr\u00e9ation de l'espace de travail"
          },
          "updated_date": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp de derni\u00e8re mise \u00e0 jour de l'espace de travail"
          },
          "webhook_enabled": {
            "type": "boolean",
            "description": "Indique si les webhooks au niveau de l'espace de travail sont activ\u00e9s"
          },
          "webhook_secret": {
            "type": "string",
            "description": "Secret de signature webhook pour cet espace de travail",
            "nullable": true
          },
          "webhook_secret_rotated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp de la derni\u00e8re rotation du secret webhook",
            "nullable": true
          },
          "webhook_secret_created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp de la premi\u00e8re cr\u00e9ation du secret webhook",
            "nullable": true
          },
          "ignore_company_webhooks": {
            "type": "boolean",
            "description": "Si true, les webhooks au niveau de l'entreprise ne se d\u00e9clenchent pas pour les \u00e9v\u00e9nements de cet espace de travail"
          },
          "icon_url": {
            "type": "string",
            "format": "uri",
            "description": "URL publiquement accessible vers le logo de l'espace de travail. Retourne le logo propre \u00e0 l'espace de travail, ou null s'il n'est pas d\u00e9fini (le logo de l'entreprise n'est PAS inclus comme solution de repli dans ce champ).",
            "nullable": true,
            "example": "https://ielmshcswdhuacyjlpiy.supabase.co/functions/v1/logo/workspace/company-id/workspace-id"
          }
        },
        "required": [
          "id",
          "name",
          "created_date"
        ]
      },
      "Template": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique du mod\u00e8le"
          },
          "name": {
            "type": "string",
            "description": "Nom du mod\u00e8le",
            "maxLength": 255
          },
          "description": {
            "type": "string",
            "description": "Description du mod\u00e8le",
            "nullable": true
          },
          "document_url": {
            "type": "string",
            "format": "uri",
            "description": "URL pr\u00e9-sign\u00e9e vers le document PDF. Il s'agit d'une URL sign\u00e9e \u00e0 dur\u00e9e limit\u00e9e pour un acc\u00e8s s\u00e9curis\u00e9, voir document_url_expires_at pour la date d'expiration. Les URL initiales sont valables 7 jours ; les URL rafra\u00eechies sont valables 1 heure. Demandez une nouvelle r\u00e9cup\u00e9ration du mod\u00e8le pour obtenir une URL fra\u00eeche si elle a expir\u00e9."
          },
          "document_url_expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Timestamp ISO 8601 auquel document_url expirera. Apr\u00e8s cette heure, l'URL retournera une erreur d'acc\u00e8s refus\u00e9. R\u00e9cup\u00e9rez \u00e0 nouveau le mod\u00e8le pour recevoir une nouvelle URL sign\u00e9e."
          },
          "page_count": {
            "type": "integer",
            "minimum": 1,
            "description": "Nombre de pages dans le document"
          },
          "expiration_hours": {
            "type": "integer",
            "minimum": 1,
            "default": 168,
            "description": "Nombre d'heures avant l'expiration des demandes de signature cr\u00e9\u00e9es \u00e0 partir de ce mod\u00e8le"
          },
          "credit_cost": {
            "type": "integer",
            "minimum": 1,
            "default": 1,
            "description": "Nombre de cr\u00e9dits consomm\u00e9s lorsqu'une demande de signature est envoy\u00e9e \u00e0 partir de ce mod\u00e8le. La valeur minimale est 1."
          },
          "settings": {
            "$ref": "#/components/schemas/SigningRequestSettings"
          },
          "recipients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateUser"
            },
            "description": "Destinataires du mod\u00e8le (inclus dans la r\u00e9cup\u00e9ration d'un seul mod\u00e8le)"
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateField"
            },
            "description": "Champs du mod\u00e8le (inclus dans la r\u00e9cup\u00e9ration d'un seul mod\u00e8le)"
          },
          "created_date": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp de cr\u00e9ation du mod\u00e8le"
          },
          "updated_date": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp de derni\u00e8re mise \u00e0 jour du mod\u00e8le"
          }
        },
        "required": [
          "id",
          "name",
          "created_date"
        ]
      },
      "TemplateUser": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique de l'utilisateur du mod\u00e8le"
          },
          "name": {
            "type": "string",
            "description": "Nom du destinataire (pr\u00e9nom et nom combin\u00e9s)"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Adresse e-mail du destinataire"
          },
          "first_name": {
            "type": "string",
            "nullable": true,
            "description": "Pr\u00e9nom du destinataire"
          },
          "last_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de famille du destinataire"
          },
          "designation": {
            "type": "string",
            "enum": [
              "Signer",
              "Approver",
              "CC"
            ],
            "description": "R\u00f4le du destinataire. Signer signe le document, Approver approuve avec des champs d'approbation, CC re\u00e7oit une copie une fois termin\u00e9."
          },
          "order": {
            "type": "integer",
            "minimum": 1,
            "description": "Ordre dans lequel le destinataire doit signer"
          },
          "phone_number": {
            "type": "string",
            "nullable": true,
            "description": "Num\u00e9ro de t\u00e9l\u00e9phone du destinataire"
          },
          "street_address": {
            "type": "string",
            "nullable": true,
            "description": "Adresse postale du destinataire"
          },
          "city": {
            "type": "string",
            "nullable": true,
            "description": "Ville du destinataire"
          },
          "state_province": {
            "type": "string",
            "nullable": true,
            "description": "\u00c9tat ou province du destinataire"
          },
          "postal_code": {
            "type": "string",
            "nullable": true,
            "description": "Code postal du destinataire"
          },
          "country": {
            "type": "string",
            "nullable": true,
            "description": "Pays du destinataire"
          },
          "title": {
            "type": "string",
            "nullable": true,
            "description": "Intitul\u00e9 de poste du destinataire"
          },
          "company": {
            "type": "string",
            "nullable": true,
            "description": "Nom de l'entreprise du destinataire"
          },
          "required_fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Liste des champs de donn\u00e9es du destinataire requis pour l'envoi (bas\u00e9e sur les champs du mod\u00e8le avec des correspondances variable_name). Inclut toujours 'email' et 'first_name'."
          },
          "missing_fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Liste des champs requis actuellement vides pour ce destinataire"
          },
          "required_read_only_fields": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "variable_name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Nom de variable du champ en lecture seule"
                },
                "variable_defined_name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Nom de champ lisible par un humain provenant de la d\u00e9finition du champ personnalis\u00e9 (par exemple 'artist_name'). Pr\u00e9sent uniquement pour les champs li\u00e9s \u00e0 une d\u00e9finition de champ personnalis\u00e9, sinon null."
                },
                "field_type": {
                  "type": "string",
                  "description": "Type du champ (text, date, etc.)"
                }
              }
            },
            "description": "Liste des champs en lecture seule obligatoires qui n\u00e9cessitent des valeurs pr\u00e9remplies avant l'envoi"
          },
          "ready_to_send": {
            "type": "boolean",
            "description": "Indique si ce destinataire a toutes les donn\u00e9es obligatoires renseign\u00e9es pour l'envoi"
          }
        },
        "required": [
          "id",
          "first_name",
          "email",
          "designation",
          "order"
        ]
      },
      "DateFormatRules": {
        "type": "object",
        "description": "R\u00e8gles de formatage pour les champs de date. Sp\u00e9cifie comment les valeurs de date doivent \u00eatre affich\u00e9es et format\u00e9es.",
        "properties": {
          "dateFormat": {
            "type": "string",
            "description": "Mod\u00e8le de format de date. Utilisez des formats pr\u00e9d\u00e9finis ou des mod\u00e8les personnalis\u00e9s avec : yyyy (ann\u00e9e sur 4 chiffres), MM (mois sur 2 chiffres), dd (jour sur 2 chiffres), MMMM (nom complet du mois), MMM (nom abr\u00e9g\u00e9 du mois), HH (heure sur 24h), mm (minute), ss (seconde). Exemples : 'MM/dd/yyyy' s'affiche comme 01/31/2024, 'MMMM dd, yyyy' s'affiche comme January 31, 2024.",
            "enum": [
              "MM/dd/yyyy",
              "dd/MM/yyyy",
              "yyyy-MM-dd",
              "MMMM dd, yyyy",
              "MMM dd, yyyy",
              "dd MMMM yyyy"
            ],
            "default": "MM/dd/yyyy"
          },
          "fontSize": {
            "type": "integer",
            "minimum": 8,
            "maximum": 48,
            "description": "Taille de police initiale/maximale facultative en pixels pour la valeur du champ affich\u00e9e. Le texte se r\u00e9duit automatiquement pour tenir dans le cadre du champ. Omettez-la pour un dimensionnement automatique. Les valeurs hors de la plage 8-48 sont ramen\u00e9es \u00e0 cette plage."
          }
        },
        "example": {
          "dateFormat": "MMMM dd, yyyy"
        }
      },
      "TextFormatRules": {
        "type": "object",
        "description": "R\u00e8gles de formatage pour les champs textuels (text, textarea, email, name, phone, company, title, number, dropdown, url).",
        "properties": {
          "fontSize": {
            "type": "integer",
            "minimum": 8,
            "maximum": 48,
            "description": "Taille de police initiale/maximale facultative en pixels pour la valeur du champ affich\u00e9e, appliqu\u00e9e dans la vue de signature et dans le PDF scell\u00e9. Le texte se r\u00e9duit automatiquement pour tenir dans le cadre du champ ; la taille explicite est donc un plafond, pas une garantie. Omettez-la pour un dimensionnement automatique (base par d\u00e9faut de 14 px). Les valeurs hors de la plage 8-48 sont ramen\u00e9es \u00e0 cette plage ; les valeurs non num\u00e9riques sont ignor\u00e9es. Non applicable aux champs signature, initials, checkbox, radio, file et stamp."
          }
        },
        "example": {
          "fontSize": 12
        }
      },
      "FileFormatRules": {
        "type": "object",
        "description": "R\u00e8gles de formatage pour les champs de t\u00e9l\u00e9versement de fichier. Sp\u00e9cifie quels types de fichiers les signataires sont autoris\u00e9s \u00e0 t\u00e9l\u00e9verser.",
        "properties": {
          "acceptedFileTypes": {
            "type": "string",
            "enum": [
              "image_and_pdf",
              "image",
              "pdf"
            ],
            "default": "image_and_pdf",
            "description": "Types de fichiers accept\u00e9s pour le t\u00e9l\u00e9versement. 'image_and_pdf' accepte les JPG, PNG et PDF. 'image' accepte uniquement les JPG et PNG. 'pdf' accepte uniquement les PDF. Les fichiers sont valid\u00e9s par leurs magic bytes, pas seulement par l'extension. La taille maximale du fichier est de 10 Mo."
          }
        },
        "example": {
          "acceptedFileTypes": "image_and_pdf"
        }
      },
      "FieldValidationRules": {
        "type": "object",
        "nullable": true,
        "description": "R\u00e8gles de validation pour les valeurs des champs. R\u00e9serv\u00e9 pour un usage futur, actuellement non appliqu\u00e9 pour aucun type de champ.",
        "additionalProperties": true
      },
      "TemplateField": {
        "type": "object",
        "description": "Un champ plac\u00e9 sur un document mod\u00e8le",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique du champ"
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "signature",
              "date",
              "checkbox",
              "dropdown",
              "radio_buttons",
              "number",
              "text_area",
              "file",
              "initial",
              "stamp",
              "approval_signature",
              "approval_checkmark",
              "approval_date"
            ],
            "description": "Type du champ"
          },
          "required": {
            "type": "boolean",
            "description": "Indique si le champ est obligatoire"
          },
          "recipient_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "ID du destinataire assign\u00e9"
          },
          "variable_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de variable pour le champ (utilis\u00e9 dans les mod\u00e8les)"
          },
          "variable_defined_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de champ lisible par un humain provenant de la d\u00e9finition du champ personnalis\u00e9 (par exemple 'artist_name'). Pr\u00e9sent uniquement pour les champs li\u00e9s \u00e0 une d\u00e9finition de champ personnalis\u00e9, sinon null."
          },
          "position": {
            "type": "object",
            "description": "Position et dimensions du champ sur le document. Toutes les valeurs sont des pourcentages (0-100). Le champ doit tenir dans la page : x + width <= 100 et y + height <= 100.",
            "properties": {
              "x": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "description": "Coordonn\u00e9e X de la position du champ (pourcentage, 0-100)"
              },
              "y": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "description": "Coordonn\u00e9e Y de la position du champ (pourcentage, 0-100)"
              },
              "width": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "description": "Largeur du champ (pourcentage, 0-100). Remarque : x + width doit \u00eatre <= 100"
              },
              "height": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "description": "Hauteur du champ (pourcentage, 0-100). Remarque : y + height doit \u00eatre <= 100"
              }
            }
          },
          "page_number": {
            "type": "integer",
            "minimum": 1,
            "nullable": true,
            "description": "Num\u00e9ro de la page o\u00f9 se trouve le champ (index\u00e9 \u00e0 partir de 1). Ne doit pas d\u00e9passer le nombre total de pages du document."
          },
          "dropdown_options": {
            "nullable": true,
            "description": "Options pour les champs de type menu d\u00e9roulant",
            "oneOf": [
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              {
                "type": "object"
              }
            ]
          },
          "multi_group_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "ID de groupe pour lier plusieurs champs de case \u00e0 cocher ou de bouton radio ensemble. Les champs partageant le m\u00eame multi_group_id se comportent comme un groupe mutuellement exclusif (comme des boutons radio) : en s\u00e9lectionner un d\u00e9s\u00e9lectionne automatiquement les autres du groupe. Utilisez le m\u00eame UUID sur plusieurs champs pour cr\u00e9er un groupe o\u00f9 une seule option peut \u00eatre s\u00e9lectionn\u00e9e \u00e0 la fois."
          },
          "date_default": {
            "type": "string",
            "format": "date",
            "nullable": true,
            "description": "Valeur de date par d\u00e9faut pour les champs de date (format ISO 8601, par exemple '2024-01-15')"
          },
          "date_signing_default": {
            "type": "boolean",
            "description": "Utiliser la date de signature comme valeur par d\u00e9faut pour les champs de date"
          },
          "format_rules": {
            "$ref": "#/components/schemas/DateFormatRules",
            "nullable": true,
            "description": "R\u00e8gles de formatage, actuellement utilis\u00e9es pour les champs de date afin de sp\u00e9cifier le format d'affichage"
          },
          "validation_rules": {
            "$ref": "#/components/schemas/FieldValidationRules"
          },
          "read_only": {
            "type": "boolean",
            "default": false,
            "description": "Indique si ce champ est en lecture seule (pr\u00e9rempli avant la signature)"
          },
          "read_only_value": {
            "type": "string",
            "nullable": true,
            "description": "Valeur statique pour les champs en lecture seule"
          }
        },
        "required": [
          "id",
          "type",
          "page_number"
        ]
      },
      "Reminder": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique du rappel"
          },
          "hours": {
            "type": "integer",
            "minimum": 1,
            "description": "Nombre d'heures apr\u00e8s l'envoi avant l'envoi du rappel"
          },
          "subject": {
            "type": "string",
            "description": "Objet de l'email pour le rappel",
            "maxLength": 255
          },
          "message": {
            "type": "string",
            "description": "Corps du message de l'email pour le rappel",
            "maxLength": 5000
          },
          "all_users": {
            "type": "boolean",
            "description": "Indique si le rappel s'applique \u00e0 tous les utilisateurs"
          },
          "template_user_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Utilisateur sp\u00e9cifique auquel envoyer le rappel (utilis\u00e9 dans le contexte d'un mod\u00e8le)"
          },
          "recipient_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Destinataire sp\u00e9cifique auquel envoyer le rappel (utilis\u00e9 dans le contexte d'une demande de signature, identique \u00e0 template_user_id)"
          },
          "sent_on": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage du moment o\u00f9 le rappel a r\u00e9ellement \u00e9t\u00e9 envoy\u00e9"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de cr\u00e9ation du rappel"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de derni\u00e8re mise \u00e0 jour du rappel"
          }
        },
        "required": [
          "id",
          "hours",
          "subject",
          "message"
        ]
      },
      "SigningRequestListItem": {
        "type": "object",
        "description": "Demande de signature telle que renvoy\u00e9e par l'endpoint LIST (GET /signing-requests)",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique de la demande de signature"
          },
          "name": {
            "type": "string",
            "description": "Nom de la demande de signature",
            "maxLength": 255
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Description de la demande de signature"
          },
          "status": {
            "type": "string",
            "enum": [
              "not_sent",
              "in_progress",
              "finished",
              "cancelled",
              "declined",
              "deleted",
              "expired"
            ],
            "description": "Statut actuel de la demande de signature"
          },
          "document_url": {
            "type": "string",
            "format": "uri",
            "description": "URL pr\u00e9-sign\u00e9e vers le document PDF. C'est une URL sign\u00e9e \u00e0 dur\u00e9e limit\u00e9e pour un acc\u00e8s s\u00e9curis\u00e9 - voir document_url_expires_at pour l'heure d'expiration. Les URL initiales sont valides 7 jours ; les URL rafra\u00eechies sont valides 1 heure. Demande une nouvelle r\u00e9cup\u00e9ration de la demande de signature pour obtenir une URL fra\u00eeche si elle a expir\u00e9."
          },
          "document_url_expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage ISO 8601 de l'expiration de document_url. Apr\u00e8s cette heure, l'URL renverra une erreur d'acc\u00e8s refus\u00e9. R\u00e9cup\u00e8re \u00e0 nouveau la demande de signature pour recevoir une nouvelle URL sign\u00e9e."
          },
          "page_count": {
            "type": "integer",
            "minimum": 1,
            "description": "Nombre de pages dans le document"
          },
          "expiration_hours": {
            "type": "integer",
            "minimum": 1,
            "default": 168,
            "description": "Nombre d'heures avant l'expiration de la demande de signature (par d\u00e9faut : 168 = 7 jours)"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage ISO 8601 de l'expiration de la demande de signature. Calcul\u00e9 \u00e0 partir de sent_date + expiration_hours. Null si la demande de signature n'a pas encore \u00e9t\u00e9 envoy\u00e9e ou n'a pas de expiration_hours d\u00e9fini."
          },
          "credit_cost": {
            "type": "integer",
            "minimum": 1,
            "default": 1,
            "description": "Nombre de cr\u00e9dits consomm\u00e9s lors de l'envoi de cette demande de signature. La valeur minimale est 1."
          },
          "template_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "ID du mod\u00e8le si cr\u00e9\u00e9 \u00e0 partir d'un mod\u00e8le"
          },
          "settings": {
            "$ref": "#/components/schemas/SigningRequestSettings"
          },
          "created_date": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de cr\u00e9ation"
          },
          "updated_date": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de derni\u00e8re mise \u00e0 jour"
          },
          "sent_date": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date d'envoi de la demande de signature"
          },
          "finished_date": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date \u00e0 laquelle toutes les signatures ont \u00e9t\u00e9 compl\u00e9t\u00e9es"
          },
          "cancelled_date": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date d'annulation de la demande de signature"
          },
          "declined_date": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date de refus de la demande de signature"
          },
          "recipients": {
            "type": "array",
            "description": "Destinataires de la demande de signature (format simplifi\u00e9)",
            "items": {
              "$ref": "#/components/schemas/SigningRequestListRecipient"
            }
          },
          "fields": {
            "type": "array",
            "description": "Champs de la demande de signature avec un objet position imbriqu\u00e9",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "text",
                    "signature",
                    "date",
                    "checkbox",
                    "dropdown",
                    "radio_buttons",
                    "number",
                    "text_area",
                    "file",
                    "initial",
                    "stamp",
                    "approval_signature",
                    "approval_checkmark",
                    "approval_date"
                  ]
                },
                "required": {
                  "type": "boolean"
                },
                "recipient_id": {
                  "type": "string",
                  "format": "uuid",
                  "nullable": true
                },
                "variable_name": {
                  "type": "string",
                  "nullable": true
                },
                "variable_defined_name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Nom de champ lisible provenant de la d\u00e9finition du champ personnalis\u00e9 (par ex. 'artist_name'). Pr\u00e9sent uniquement pour les champs li\u00e9s \u00e0 une d\u00e9finition de champ personnalis\u00e9, null sinon."
                },
                "position": {
                  "type": "object",
                  "properties": {
                    "x": {
                      "type": "number"
                    },
                    "y": {
                      "type": "number"
                    },
                    "width": {
                      "type": "number"
                    },
                    "height": {
                      "type": "number"
                    }
                  }
                },
                "value": {
                  "type": "string",
                  "nullable": true,
                  "description": "Valeur finale du champ apr\u00e8s la signature"
                },
                "dropdown_options": {
                  "nullable": true,
                  "oneOf": [
                    {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    {
                      "type": "object"
                    }
                  ]
                },
                "format_rules": {
                  "$ref": "#/components/schemas/DateFormatRules",
                  "nullable": true
                },
                "validation_rules": {
                  "$ref": "#/components/schemas/FieldValidationRules"
                }
              }
            }
          }
        },
        "required": [
          "id",
          "name",
          "status",
          "created_date"
        ]
      },
      "SigningRequestListRecipient": {
        "type": "object",
        "description": "Destinataire tel que renvoy\u00e9 dans les r\u00e9ponses LIST des demandes de signature (format simplifi\u00e9)",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique du destinataire"
          },
          "name": {
            "type": "string",
            "description": "Nom complet combin\u00e9"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Adresse e-mail du destinataire"
          },
          "designation": {
            "type": "string",
            "enum": [
              "Signer",
              "Approver",
              "CC"
            ],
            "description": "R\u00f4le du destinataire. Signer signe le document, Approver approuve avec des champs d'approbation, CC re\u00e7oit une copie une fois termin\u00e9."
          },
          "order": {
            "type": "integer",
            "minimum": 1,
            "description": "Ordre de signature"
          },
          "finished_date": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date \u00e0 laquelle ce destinataire a termin\u00e9 de signer"
          },
          "signature_details": {
            "type": "object",
            "nullable": true,
            "description": "D\u00e9tails sur la signature du destinataire"
          }
        }
      },
      "SigningRequestCreateResponse": {
        "type": "object",
        "description": "Demande de signature telle que renvoy\u00e9e par les endpoints CREATE (POST /signing-requests)",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique de la demande de signature"
          },
          "name": {
            "type": "string",
            "description": "Nom de la demande de signature",
            "maxLength": 255
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Description de la demande de signature"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft"
            ],
            "description": "Le statut est toujours 'draft' pour les demandes de signature nouvellement cr\u00e9\u00e9es"
          },
          "document_url": {
            "type": "string",
            "format": "uri",
            "description": "URL pr\u00e9-sign\u00e9e vers le document PDF"
          },
          "page_count": {
            "type": "integer",
            "minimum": 1,
            "description": "Nombre de pages dans le document"
          },
          "expiration_hours": {
            "type": "integer",
            "minimum": 1,
            "default": 168,
            "description": "Nombre d'heures avant l'expiration de la demande de signature (par d\u00e9faut : 168 = 7 jours)"
          },
          "template_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "ID du mod\u00e8le si cr\u00e9\u00e9 \u00e0 partir d'un mod\u00e8le"
          },
          "settings": {
            "$ref": "#/components/schemas/SigningRequestSettings"
          },
          "created_date": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de cr\u00e9ation"
          },
          "updated_date": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de derni\u00e8re mise \u00e0 jour"
          },
          "sent_date": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date d'envoi de la demande de signature"
          },
          "finished_date": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date \u00e0 laquelle toutes les signatures ont \u00e9t\u00e9 compl\u00e9t\u00e9es"
          },
          "cancelled_date": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date d'annulation de la demande de signature"
          },
          "recipients": {
            "type": "array",
            "description": "Destinataires de la demande de signature",
            "items": {
              "$ref": "#/components/schemas/SigningRequestCreateRecipient"
            }
          },
          "fields": {
            "type": "array",
            "description": "Champs de la demande de signature avec des valeurs de position \u00e0 plat",
            "items": {
              "$ref": "#/components/schemas/SigningRequestCreateField"
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Avertissements optionnels de validation du format des e-mails. Pr\u00e9sents uniquement lorsque les e-mails des destinataires ont des formats inhabituels."
          }
        },
        "required": [
          "id",
          "name",
          "status"
        ]
      },
      "SigningRequestCreateRecipient": {
        "type": "object",
        "description": "Destinataire tel que renvoy\u00e9 dans les r\u00e9ponses CREATE des demandes de signature",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique du destinataire"
          },
          "first_name": {
            "type": "string",
            "nullable": true,
            "description": "Pr\u00e9nom du destinataire"
          },
          "last_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de famille du destinataire"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Nom complet combin\u00e9 (construit automatiquement \u00e0 partir de first_name + last_name)"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Adresse e-mail du destinataire"
          },
          "designation": {
            "type": "string",
            "enum": [
              "Signer",
              "Approver",
              "CC"
            ],
            "description": "R\u00f4le du destinataire. Signer signe le document, Approver approuve avec des champs d'approbation, CC re\u00e7oit une copie une fois termin\u00e9."
          },
          "order": {
            "type": "integer",
            "minimum": 1,
            "description": "Ordre de signature"
          },
          "phone_number": {
            "type": "string",
            "nullable": true,
            "description": "Num\u00e9ro de t\u00e9l\u00e9phone du destinataire"
          },
          "street_address": {
            "type": "string",
            "nullable": true,
            "description": "Adresse postale"
          },
          "city": {
            "type": "string",
            "nullable": true,
            "description": "Ville"
          },
          "state_province": {
            "type": "string",
            "nullable": true,
            "description": "\u00c9tat ou province"
          },
          "postal_code": {
            "type": "string",
            "nullable": true,
            "description": "Code postal"
          },
          "country": {
            "type": "string",
            "nullable": true,
            "description": "Pays"
          },
          "title": {
            "type": "string",
            "nullable": true,
            "description": "Intitul\u00e9 du poste"
          },
          "company": {
            "type": "string",
            "nullable": true,
            "description": "Nom de l'entreprise"
          },
          "custom_fields": {
            "type": "object",
            "nullable": true,
            "description": "Paires cl\u00e9-valeur personnalis\u00e9es"
          },
          "finished_date": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Date \u00e0 laquelle ce destinataire a termin\u00e9 de signer"
          }
        },
        "required": [
          "first_name",
          "email",
          "designation"
        ]
      },
      "SigningRequestCreateField": {
        "type": "object",
        "description": "Champ tel que renvoy\u00e9 dans les r\u00e9ponses CREATE des demandes de signature (position \u00e0 plat, style base de donn\u00e9es)",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique du champ"
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "signature",
              "date",
              "checkbox",
              "dropdown",
              "radio_buttons",
              "number",
              "text_area",
              "file",
              "initial",
              "stamp",
              "approval_signature",
              "approval_checkmark",
              "approval_date"
            ],
            "description": "Type du champ"
          },
          "recipient_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "ID du destinataire assign\u00e9"
          },
          "page_number": {
            "type": "integer",
            "minimum": 1,
            "description": "Num\u00e9ro de page (index\u00e9 \u00e0 partir de 1)"
          },
          "x_position": {
            "type": "number",
            "description": "Coordonn\u00e9e X en pourcentage (0-100)"
          },
          "y_position": {
            "type": "number",
            "description": "Coordonn\u00e9e Y en pourcentage (0-100)"
          },
          "width": {
            "type": "number",
            "description": "Largeur en pourcentage (0-100)"
          },
          "height": {
            "type": "number",
            "description": "Hauteur en pourcentage (0-100)"
          },
          "required": {
            "type": "boolean",
            "description": "Indique si le champ est requis"
          },
          "read_only": {
            "type": "boolean",
            "description": "Indique si ce champ est en lecture seule"
          },
          "read_only_value": {
            "type": "string",
            "nullable": true,
            "description": "Valeur statique pour les champs en lecture seule"
          },
          "variable_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de variable pour le mappage des donn\u00e9es pr\u00e9remplies"
          },
          "variable_defined_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de champ lisible provenant de la d\u00e9finition du champ personnalis\u00e9 (par ex. 'artist_name'). Pr\u00e9sent uniquement pour les champs li\u00e9s \u00e0 une d\u00e9finition de champ personnalis\u00e9, null sinon."
          },
          "dropdown_options": {
            "nullable": true,
            "description": "Options pour les champs d\u00e9roulants",
            "oneOf": [
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              {
                "type": "object"
              }
            ]
          },
          "format_rules": {
            "type": "object",
            "nullable": true,
            "description": "R\u00e8gles de formatage (par exemple, format de date)"
          },
          "validation_rules": {
            "type": "object",
            "nullable": true,
            "description": "R\u00e8gles de validation pour le champ"
          },
          "date_signing_default": {
            "type": "boolean",
            "description": "Indique s'il faut utiliser la date de signature comme valeur par d\u00e9faut"
          },
          "final_value": {
            "type": "string",
            "nullable": true,
            "description": "Valeur pr\u00e9-remplie ou finale du champ"
          }
        },
        "required": [
          "type",
          "recipient_id",
          "page_number"
        ]
      },
      "SigningRequestDetail": {
        "type": "object",
        "description": "Demande de Signature d\u00e9taill\u00e9e telle que renvoy\u00e9e par GET /signing-requests/{id} (structure imbriqu\u00e9e avec un objet status et des horodatages)",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique de la demande de signature"
          },
          "name": {
            "type": "string",
            "description": "Nom de la demande de signature"
          },
          "template_description": {
            "type": "string",
            "nullable": true,
            "description": "Description issue du mod\u00e8le"
          },
          "companies_workspaces_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de l'espace de travail auquel appartient cette demande de signature"
          },
          "document_url": {
            "type": "string",
            "format": "uri",
            "description": "URL pr\u00e9-sign\u00e9e vers le document PDF"
          },
          "document_url_expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "document_page_count": {
            "type": "integer",
            "minimum": 1,
            "description": "Nombre de pages du document"
          },
          "expiration_hours": {
            "type": "integer",
            "description": "Nombre d'heures avant l'expiration de la demande de signature"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage ISO 8601 correspondant \u00e0 l'expiration de la demande de signature. Calcul\u00e9 \u00e0 partir de sent_on + expiration_hours. Null si elle n'a pas encore \u00e9t\u00e9 envoy\u00e9e ou si aucun expiration_hours n'est d\u00e9fini."
          },
          "credit_cost": {
            "type": "integer",
            "description": "Cr\u00e9dits consomm\u00e9s lors de l'envoi"
          },
          "status": {
            "type": "object",
            "description": "Indicateurs de statut (plusieurs peuvent \u00eatre vrais pour les \u00e9tats terminaux)",
            "properties": {
              "sent": {
                "type": "boolean"
              },
              "finished": {
                "type": "boolean"
              },
              "cancelled": {
                "type": "boolean"
              },
              "declined": {
                "type": "boolean"
              },
              "expired": {
                "type": "boolean"
              }
            }
          },
          "timestamps": {
            "type": "object",
            "description": "Tous les horodatages pertinents pour le cycle de vie de la demande de signature",
            "properties": {
              "created_on": {
                "type": "string",
                "format": "date-time"
              },
              "sent_on": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "finished_on": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "cancelled_on": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "declined_on": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "last_changed_on": {
                "type": "string",
                "format": "date-time"
              },
              "last_signing_action_on": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          },
          "settings": {
            "$ref": "#/components/schemas/SigningRequestSettings"
          },
          "use_signing_order": {
            "type": "integer",
            "enum": [
              0,
              1
            ],
            "deprecated": true
          },
          "allow_download": {
            "type": "integer",
            "enum": [
              0,
              1
            ],
            "deprecated": true
          },
          "allow_editing_before_sending": {
            "type": "integer",
            "enum": [
              0,
              1
            ],
            "deprecated": true
          },
          "hand_drawn_only": {
            "type": "integer",
            "enum": [
              0,
              1
            ],
            "deprecated": true
          },
          "attach_pdf_on_finish": {
            "type": "integer",
            "enum": [
              0,
              1
            ],
            "deprecated": true
          },
          "certificate": {
            "type": "object",
            "nullable": true,
            "description": "Informations sur le statut de g\u00e9n\u00e9ration du certificat",
            "properties": {
              "generated": {
                "type": "boolean",
                "description": "Indique si le certificat PDF final a \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9"
              },
              "generated_on": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Horodatage de la g\u00e9n\u00e9ration du certificat"
              },
              "has_error": {
                "type": "boolean",
                "description": "Indique s'il y a eu une erreur lors de la g\u00e9n\u00e9ration du certificat"
              }
            }
          },
          "final_document_download_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL sign\u00e9e pour t\u00e9l\u00e9charger le document final sign\u00e9 (PDF avec certificat). L'URL expire apr\u00e8s 1 heure."
          },
          "final_document_download_error": {
            "type": "string",
            "nullable": true,
            "enum": [
              "file_not_accessible",
              null
            ]
          },
          "document_only_download_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL sign\u00e9e pour t\u00e9l\u00e9charger le PDF du document seul. L'URL expire apr\u00e8s 1 heure."
          },
          "document_only_download_error": {
            "type": "string",
            "nullable": true,
            "enum": [
              "file_not_accessible",
              null
            ]
          },
          "certificate_only_download_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "URL sign\u00e9e pour t\u00e9l\u00e9charger le PDF du certificat seul. L'URL expire apr\u00e8s 1 heure."
          },
          "certificate_only_download_error": {
            "type": "string",
            "nullable": true,
            "enum": [
              "file_not_accessible",
              null
            ]
          }
        },
        "required": [
          "id",
          "name",
          "status",
          "companies_workspaces_id"
        ]
      },
      "SigningRequestSettings": {
        "type": "object",
        "description": "Param\u00e8tres renvoy\u00e9s par les endpoints de liste et de d\u00e9tail des demandes de signature. Les mod\u00e8les utilisent le sch\u00e9ma TemplateSettings (sans champs d'identit\u00e9).",
        "properties": {
          "allow_download": {
            "type": "boolean",
            "description": "Indique si les destinataires peuvent t\u00e9l\u00e9charger le document",
            "default": true
          },
          "attach_pdf_on_finish": {
            "type": "boolean",
            "description": "Indique s'il faut joindre le PDF une fois la signature termin\u00e9e",
            "default": true
          },
          "allow_editing_before_sending": {
            "type": "boolean",
            "description": "Indique si la demande de signature peut \u00eatre modifi\u00e9e avant l'envoi",
            "default": false
          },
          "use_signing_order": {
            "type": "boolean",
            "description": "Indique si l'ordre de signature est impos\u00e9 entre les destinataires. Quand c'est vrai, les signataires re\u00e7oivent le document dans l'ordre d\u00e9fini par leur order. Quand c'est faux, tous les signataires re\u00e7oivent le document simultan\u00e9ment.",
            "default": true
          },
          "hand_drawn_only": {
            "type": "boolean",
            "description": "Lorsque cette option est activ\u00e9e, les signataires ne peuvent que dessiner leur signature \u00e0 la main et ne peuvent pas utiliser de signatures dactylographi\u00e9es",
            "default": false
          },
          "send_signing_email": {
            "type": "boolean",
            "description": "Indique s'il faut envoyer des e-mails de notification de demande de signature aux signataires",
            "default": true
          },
          "send_finish_email": {
            "type": "boolean",
            "description": "Indique s'il faut envoyer un e-mail de fin lorsque tous les signataires ont termin\u00e9",
            "default": true
          },
          "send_expiration_email": {
            "type": "boolean",
            "description": "Indique s'il faut envoyer un e-mail de notification d'expiration quand la demande expire",
            "default": true
          },
          "send_cancellation_email": {
            "type": "boolean",
            "description": "Indique s'il faut envoyer un e-mail de notification d'annulation quand la demande est annul\u00e9e",
            "default": true
          },
          "require_otp_verification": {
            "type": "boolean",
            "nullable": true,
            "description": "Indique si les signataires doivent v\u00e9rifier leur e-mail avec un code \u00e0 usage unique avant d'acc\u00e9der au document. null = h\u00e9rite du param\u00e8tre de l'espace de travail/de l'entreprise.",
            "default": null
          },
          "disable_guided_navigation": {
            "type": "boolean",
            "nullable": true,
            "description": "D\u00e9sactive le d\u00e9filement automatique vers le prochain champ requis pendant la signature. H\u00e9rite de l'espace de travail ou de l'entreprise si non d\u00e9fini."
          },
          "allow_presigning_download": {
            "type": "boolean",
            "nullable": true,
            "description": "Permet aux signataires de t\u00e9l\u00e9charger le document original avant de signer. H\u00e9rite du param\u00e8tre de l'espace de travail ou de l'entreprise quand null."
          },
          "show_qr_code": {
            "type": "boolean",
            "nullable": true,
            "description": "Affiche un QR code sur la page de signature qui permet aux signataires de continuer sur leur t\u00e9l\u00e9phone. H\u00e9rite du param\u00e8tre de l'espace de travail ou de l'entreprise quand null."
          },
          "identity_editable_fields": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            },
            "description": "Champs d'identit\u00e9 que les signataires peuvent modifier avant de signer (par exemple [\"name\", \"company\"]). null = d\u00e9sactiv\u00e9. Quand c'est d\u00e9fini, une bo\u00eete de dialogue de confirmation permet aux signataires de modifier les champs sp\u00e9cifi\u00e9s."
          },
          "notify_identity_change_email": {
            "type": "boolean",
            "default": false,
            "description": "Envoie une notification par e-mail quand un signataire modifie son identit\u00e9."
          }
        }
      },
      "TemplateSettings": {
        "type": "object",
        "description": "Param\u00e8tres renvoy\u00e9s par les endpoints de mod\u00e8les. Correspond \u00e0 SigningRequestSettings sans les champs d'identit\u00e9 du signataire (identity_editable_fields, notify_identity_change_email), qui s'appliquent uniquement aux demandes de signature.",
        "properties": {
          "allow_download": {
            "type": "boolean",
            "description": "Indique si les destinataires peuvent t\u00e9l\u00e9charger le document",
            "default": true
          },
          "attach_pdf_on_finish": {
            "type": "boolean",
            "description": "Indique s'il faut joindre le PDF une fois la signature termin\u00e9e",
            "default": true
          },
          "allow_editing_before_sending": {
            "type": "boolean",
            "description": "Indique si la demande de signature peut \u00eatre modifi\u00e9e avant l'envoi",
            "default": false
          },
          "use_signing_order": {
            "type": "boolean",
            "description": "Indique si l'ordre de signature est impos\u00e9 entre les destinataires.",
            "default": true
          },
          "hand_drawn_only": {
            "type": "boolean",
            "description": "Lorsque cette option est activ\u00e9e, les signataires ne peuvent que dessiner leur signature \u00e0 la main et ne peuvent pas utiliser de signatures dactylographi\u00e9es",
            "default": false
          },
          "send_signing_email": {
            "type": "boolean",
            "description": "Indique s'il faut envoyer des e-mails de notification de demande de signature aux signataires",
            "default": true
          },
          "send_finish_email": {
            "type": "boolean",
            "description": "Indique s'il faut envoyer un e-mail de fin lorsque tous les signataires ont termin\u00e9",
            "default": true
          },
          "send_expiration_email": {
            "type": "boolean",
            "description": "Indique s'il faut envoyer un e-mail de notification d'expiration quand la demande expire",
            "default": true
          },
          "send_cancellation_email": {
            "type": "boolean",
            "description": "Indique s'il faut envoyer un e-mail de notification d'annulation quand la demande est annul\u00e9e",
            "default": true
          },
          "require_otp_verification": {
            "type": "boolean",
            "nullable": true,
            "description": "Indique si les signataires doivent v\u00e9rifier leur e-mail avec un code \u00e0 usage unique avant d'acc\u00e9der au document. null = h\u00e9rite du param\u00e8tre de l'espace de travail/de l'entreprise.",
            "default": null
          },
          "disable_guided_navigation": {
            "type": "boolean",
            "nullable": true,
            "description": "D\u00e9sactive le d\u00e9filement automatique vers le prochain champ requis pendant la signature. H\u00e9rite de l'espace de travail ou de l'entreprise si non d\u00e9fini."
          },
          "allow_presigning_download": {
            "type": "boolean",
            "nullable": true,
            "description": "Autorise les signataires \u00e0 t\u00e9l\u00e9charger le document original avant de signer. H\u00e9rite du param\u00e8tre de l'espace de travail ou de l'entreprise quand la valeur est null."
          },
          "show_qr_code": {
            "type": "boolean",
            "nullable": true,
            "description": "Affiche un QR code sur la page de signature qui permet aux signataires de continuer sur leur t\u00e9l\u00e9phone. H\u00e9rite du param\u00e8tre de l'espace de travail ou de l'entreprise quand la valeur est null."
          }
        }
      },
      "LegacyDocumentSettings": {
        "type": "object",
        "description": "Param\u00e8tres renvoy\u00e9s par le endpoint d\u00e9pr\u00e9ci\u00e9 POST /documents. Un ensemble r\u00e9duit ; les nouvelles int\u00e9grations devraient utiliser les endpoints de demande de signature, qui renvoient SigningRequestSettings.",
        "properties": {
          "allow_download": {
            "type": "boolean",
            "description": "Indique si les destinataires peuvent t\u00e9l\u00e9charger le document",
            "default": true
          },
          "attach_pdf_on_finish": {
            "type": "boolean",
            "description": "Indique s'il faut joindre le PDF une fois la signature termin\u00e9e",
            "default": true
          },
          "allow_editing_before_sending": {
            "type": "boolean",
            "description": "Indique si la demande de signature peut \u00eatre modifi\u00e9e avant l'envoi",
            "default": false
          },
          "use_signing_order": {
            "type": "boolean",
            "description": "Indique si l'ordre de signature est impos\u00e9 entre les destinataires.",
            "default": true
          },
          "hand_drawn_only": {
            "type": "boolean",
            "description": "Quand activ\u00e9, les signataires ne peuvent que dessiner leur signature \u00e0 la main",
            "default": false
          },
          "send_signing_email": {
            "type": "boolean",
            "description": "Indique s'il faut envoyer les e-mails de notification de demande de signature aux signataires",
            "default": true
          },
          "send_finish_email": {
            "type": "boolean",
            "description": "Indique s'il faut envoyer un e-mail de finalisation quand tous les signataires ont termin\u00e9",
            "default": true
          },
          "send_expiration_email": {
            "type": "boolean",
            "description": "Indique s'il faut envoyer un e-mail de notification d'expiration quand la demande expire",
            "default": true
          },
          "send_cancellation_email": {
            "type": "boolean",
            "description": "Indique s'il faut envoyer un e-mail de notification d'annulation quand la demande est annul\u00e9e",
            "default": true
          },
          "disable_guided_navigation": {
            "type": "boolean",
            "nullable": true,
            "description": "D\u00e9sactive le d\u00e9filement automatique vers le prochain champ requis pendant la signature. H\u00e9rite de l'espace de travail ou de l'entreprise si non d\u00e9fini."
          },
          "allow_presigning_download": {
            "type": "boolean",
            "nullable": true,
            "description": "Autorise les signataires \u00e0 t\u00e9l\u00e9charger le document original avant de signer. H\u00e9rite du param\u00e8tre de l'espace de travail ou de l'entreprise quand la valeur est null."
          }
        }
      },
      "Recipient": {
        "type": "object",
        "required": [
          "first_name",
          "email",
          "designation"
        ],
        "description": "Sch\u00e9ma Destinataire avec comportements de construction automatique et de mapping. **Champ name** : Construit automatiquement \u00e0 partir de first_name et last_name ('Pr\u00e9nom Nom' si les deux sont pr\u00e9sents, sinon 'Pr\u00e9nom'). Les valeurs manuelles du nom sont \u00e9cras\u00e9es. **Attribution de l'ordre** : TOUS les destinataires DOIVENT avoir une valeur order explicite. L'ordre d\u00e9termine la s\u00e9quence de signature, qui est toujours impos\u00e9e. Les destinataires doivent signer dans l'ordre, les num\u00e9ros les plus bas signant en premier. **Champs personnalis\u00e9s** : Prend en charge \u00e0 la fois la structure plate (par exemple, company_name \u00e0 la racine) et la structure imbriqu\u00e9e (objet custom_fields). Les deux formats sont normalis\u00e9s en interne. **Mapping des champs de mod\u00e8le** : Lors de la cr\u00e9ation \u00e0 partir d'un mod\u00e8le avec des destinataires personnalis\u00e9s, utilisez template_user_id ou order pour faire correspondre les utilisateurs du mod\u00e8le. Seules les informations utilisateur (nom, e-mail, t\u00e9l\u00e9phone, etc.) peuvent \u00eatre mises \u00e0 jour - order et designation sont h\u00e9rit\u00e9s du mod\u00e8le. **IDs temporaires** : Pour la cr\u00e9ation bas\u00e9e sur un document, utilisez des IDs temporaires (format : 'temp_1', 'temp_2', etc.) pour r\u00e9f\u00e9rencer les destinataires dans les champs et les rappels avant leur cr\u00e9ation. **Destinataires en copie (CC)** : Les destinataires en copie re\u00e7oivent une copie termin\u00e9e mais ne peuvent ni signer ni se voir attribuer de champs. Au moins un Signataire est requis.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Identifiant unique. Pour les mises \u00e0 jour : utilisez l'UUID existant. Pour la cr\u00e9ation bas\u00e9e sur un document : utilisez \u00e9ventuellement un ID temporaire (format : 'temp_1', 'temp_2', etc.) pour r\u00e9f\u00e9rencer les destinataires dans les champs et les rappels avant la cr\u00e9ation. Les IDs temporaires sont automatiquement r\u00e9solus en UUID r\u00e9els dans la r\u00e9ponse."
          },
          "_temp_id": {
            "type": "string",
            "description": "Identifiant temporaire pour les nouveaux destinataires dans les requ\u00eates PUT (mise \u00e0 jour compl\u00e8te) (par exemple, 'temp_1'). Utilisez-le lors de la cr\u00e9ation de nouveaux destinataires en m\u00eame temps que des destinataires existants dans des mises \u00e0 jour compl\u00e8tes. Doit commencer par 'temp_' et \u00eatre unique au sein de la requ\u00eate. Non utilis\u00e9 pour les requ\u00eates POST (cr\u00e9ation) - utilisez plut\u00f4t le champ 'id'."
          },
          "template_user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Lors de la cr\u00e9ation \u00e0 partir d'un mod\u00e8le, l'ID de l'utilisateur du mod\u00e8le \u00e0 mettre \u00e0 jour. Si fourni, les donn\u00e9es de ce destinataire mettront \u00e0 jour l'utilisateur du mod\u00e8le correspondant. Si non fourni, la correspondance se fait par ordre. Seules les infos utilisateur (nom, email, t\u00e9l\u00e9phone, adresse, titre, entreprise) peuvent \u00eatre mises \u00e0 jour - l'ordre et la d\u00e9signation sont toujours h\u00e9rit\u00e9s du mod\u00e8le."
          },
          "first_name": {
            "type": "string",
            "maxLength": 100,
            "description": "Pr\u00e9nom du destinataire"
          },
          "last_name": {
            "type": "string",
            "maxLength": 100,
            "description": "Nom de famille du destinataire (optionnel, mais requis si vous utilisez les variables pr\u00e9d\u00e9finies full_name ou last_name)"
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 255,
            "description": "Adresse email du destinataire"
          },
          "designation": {
            "type": "string",
            "enum": [
              "Signer",
              "Approver",
              "CC"
            ],
            "description": "R\u00f4le du destinataire. Signataire signe le document, Approbateur approuve avec des champs d'approbation, CC re\u00e7oit une copie une fois termin\u00e9."
          },
          "order": {
            "type": "integer",
            "minimum": 1,
            "description": "Num\u00e9ro de s\u00e9quence de signature. Les destinataires doivent signer dans l'ordre, les num\u00e9ros les plus bas signant en premier. Ce champ est requis pour tous les destinataires."
          },
          "phone_number": {
            "type": "string",
            "maxLength": 50,
            "nullable": true,
            "description": "Num\u00e9ro de t\u00e9l\u00e9phone du destinataire"
          },
          "street_address": {
            "type": "string",
            "maxLength": 255,
            "nullable": true,
            "description": "Adresse postale"
          },
          "city": {
            "type": "string",
            "maxLength": 100,
            "nullable": true,
            "description": "Ville"
          },
          "state_province": {
            "type": "string",
            "maxLength": 100,
            "nullable": true,
            "description": "\u00c9tat ou province"
          },
          "postal_code": {
            "type": "string",
            "maxLength": 20,
            "nullable": true,
            "description": "Code postal"
          },
          "country": {
            "type": "string",
            "maxLength": 100,
            "nullable": true,
            "description": "Pays"
          },
          "title": {
            "type": "string",
            "maxLength": 100,
            "nullable": true,
            "description": "Titre du poste"
          },
          "company": {
            "type": "string",
            "maxLength": 255,
            "nullable": true,
            "description": "Nom de l'entreprise"
          },
          "custom_fields": {
            "type": "object",
            "additionalProperties": true,
            "description": "Paires cl\u00e9-valeur personnalis\u00e9es pour des donn\u00e9es suppl\u00e9mentaires sur le destinataire"
          }
        }
      },
      "Field": {
        "type": "object",
        "required": [
          "type",
          "position",
          "page_number"
        ],
        "description": "D\u00e9finition de champ pour les demandes de signature. **Champs en lecture seule** : d\u00e9finissez read_only=true pour pr\u00e9-remplir une valeur de champ que les signataires ne peuvent pas modifier. Utilisez read_only_value pour du texte statique, ou prefilled_data pour remplir automatiquement \u00e0 partir des attributs du destinataire. **Fusion de champs bas\u00e9e sur un mod\u00e8le** : lors de la cr\u00e9ation \u00e0 partir d'un mod\u00e8le avec un tableau fields, utilisez template_field_id (pr\u00e9f\u00e9r\u00e9) ou variable_name (repli) pour faire correspondre les champs du mod\u00e8le. Seules les propri\u00e9t\u00e9s fournies remplacent les valeurs par d\u00e9faut du mod\u00e8le (mise \u00e0 jour partielle). Les champs non appari\u00e9s sont ignor\u00e9s.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique (\u00e0 inclure pour les mises \u00e0 jour, \u00e0 omettre pour les nouveaux champs)"
          },
          "template_field_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID du champ du mod\u00e8le \u00e0 faire correspondre pour les mises \u00e0 jour partielles (cr\u00e9ation bas\u00e9e sur un mod\u00e8le uniquement). Utilisez ceci pour identifier quel champ du mod\u00e8le remplacer. A priorit\u00e9 sur variable_name pour la correspondance."
          },
          "type": {
            "type": "string",
            "enum": [
              "signature",
              "text",
              "date",
              "checkbox",
              "dropdown",
              "initial",
              "initials",
              "text_area",
              "textarea",
              "image",
              "stamp",
              "approval_signature",
              "approval_checkmark",
              "approval_date"
            ],
            "description": "Type de champ. Accepte 'initial' ou 'initials' (normalis\u00e9 en 'initial'), 'textarea' ou 'text_area' (normalis\u00e9 en 'text_area')."
          },
          "position": {
            "type": "object",
            "required": [
              "x",
              "y",
              "width",
              "height"
            ],
            "description": "Le champ doit tenir dans les limites de la page : x + width <= 100 et y + height <= 100",
            "properties": {
              "x": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "description": "Coordonn\u00e9e X en pourcentage (0-100)"
              },
              "y": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "description": "Coordonn\u00e9e Y en pourcentage (0-100)"
              },
              "width": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "description": "Largeur en pourcentage (0-100). x + width doit \u00eatre <= 100"
              },
              "height": {
                "type": "number",
                "minimum": 0,
                "maximum": 100,
                "description": "Hauteur en pourcentage (0-100). y + height doit \u00eatre <= 100"
              }
            }
          },
          "page_number": {
            "type": "integer",
            "minimum": 1,
            "description": "Num\u00e9ro de la page o\u00f9 se trouve le champ (index\u00e9 \u00e0 partir de 1). Ne doit pas d\u00e9passer le nombre total de pages du document."
          },
          "required": {
            "type": "boolean",
            "default": false,
            "description": "Indique si le champ doit \u00eatre compl\u00e9t\u00e9"
          },
          "recipient_id": {
            "type": "string",
            "description": "ID du destinataire assign\u00e9 \u00e0 ce champ. Utilisez un v\u00e9ritable UUID pour la cr\u00e9ation ou les mises \u00e0 jour bas\u00e9es sur un mod\u00e8le, ou un ID temporaire (par ex. 'temp_1') pour la cr\u00e9ation bas\u00e9e sur un document afin de r\u00e9f\u00e9rencer les destinataires d\u00e9finis dans la m\u00eame requ\u00eate."
          },
          "variable_name": {
            "type": "string",
            "maxLength": 100,
            "nullable": true,
            "description": "Nom de variable pour le champ (utilis\u00e9 dans les mod\u00e8les). \u00c9galement utilis\u00e9 comme repli pour la correspondance de champs lors de la cr\u00e9ation bas\u00e9e sur un mod\u00e8le quand template_field_id n'est pas fourni."
          },
          "variable_defined_name": {
            "type": "string",
            "maxLength": 100,
            "nullable": true,
            "description": "Nom lisible et personnalis\u00e9 de d\u00e9finition du champ. Peut \u00eatre utilis\u00e9 comme alternative \u00e0 variable_name pour cibler des champs lors de la cr\u00e9ation bas\u00e9e sur un mod\u00e8le."
          },
          "dropdown_options": {
            "description": "Options pour les champs de liste d\u00e9roulante",
            "oneOf": [
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              {
                "type": "object"
              }
            ]
          },
          "date_default": {
            "type": "string",
            "format": "date",
            "nullable": true,
            "description": "Valeur de date par d\u00e9faut"
          },
          "date_signing_default": {
            "type": "boolean",
            "default": false,
            "description": "Utiliser la date de signature comme valeur par d\u00e9faut"
          },
          "multi_group_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "ID de groupe pour lier plusieurs champs de case \u00e0 cocher ou de bouton radio ensemble. Les champs partageant le m\u00eame multi_group_id se comportent comme un groupe mutuellement exclusif (comme des boutons radio) - en s\u00e9lectionner un d\u00e9s\u00e9lectionne automatiquement les autres du groupe. Utilisez le m\u00eame UUID sur plusieurs champs pour cr\u00e9er un groupe o\u00f9 une seule option peut \u00eatre s\u00e9lectionn\u00e9e \u00e0 la fois."
          },
          "format_rules": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/DateFormatRules"
              },
              {
                "$ref": "#/components/schemas/FileFormatRules"
              },
              {
                "type": "object",
                "additionalProperties": true
              }
            ],
            "nullable": true,
            "description": "R\u00e8gles de formatage pour la valeur du champ. Pour les champs de date, utilisez le sch\u00e9ma DateFormatRules avec la propri\u00e9t\u00e9 dateFormat. Pour les champs de fichier, utilisez le sch\u00e9ma FileFormatRules avec la propri\u00e9t\u00e9 acceptedFileTypes (image_and_pdf, image, ou pdf). Pour les champs url, utilisez { urlDisplayText: string }. Les champs textuels (text, textarea, email, name, phone, company, title, number, dropdown, url, date) acceptent en plus une propri\u00e9t\u00e9 facultative fontSize (entier en px, 8-48, born\u00e9e) \u2014 voir TextFormatRules."
          },
          "validation_rules": {
            "$ref": "#/components/schemas/FieldValidationRules"
          },
          "read_only": {
            "type": "boolean",
            "default": false,
            "description": "Indique si ce champ est en lecture seule (pr\u00e9-rempli avant la signature). Quand c'est true, le signataire ne peut pas modifier la valeur du champ. Utile pour afficher les termes du contrat, les infos du destinataire, ou d'autres donn\u00e9es fixes."
          },
          "read_only_value": {
            "type": "string",
            "nullable": true,
            "description": "Valeur statique pour les champs en lecture seule. Prend le dessus sur prefilled_data si les deux sont sp\u00e9cifi\u00e9s. Applicable uniquement quand read_only est true. Exemple : 'Contract #12345' ou 'Acme Corporation'."
          },
          "prefilled_data": {
            "type": "string",
            "nullable": true,
            "enum": [
              "first_name",
              "last_name",
              "full_name",
              "email",
              "phone_number",
              "company",
              "title",
              "street_address",
              "city",
              "state_province",
              "postal_code",
              "country"
            ],
            "description": "Attribut utilisateur \u00e0 auto-remplir quand read_only est true. La valeur est r\u00e9cup\u00e9r\u00e9e depuis les donn\u00e9es du destinataire assign\u00e9 au moment de la signature. Peut aussi r\u00e9f\u00e9rencer des cl\u00e9s custom_fields d\u00e9finies sur le destinataire (pas limit\u00e9 aux valeurs enum). Applicable uniquement quand read_only est true et que read_only_value n'est pas d\u00e9fini. Exemple : Mettre 'email' pour afficher l'adresse email du destinataire."
          },
          "required_conditions": {
            "$ref": "#/components/schemas/ConditionSet",
            "nullable": true,
            "description": "R\u00e8gles conditionnelles pour d\u00e9terminer quand ce champ est requis. Quand c'est d\u00e9fini, \u00e7a prend le dessus sur le flag statique 'required'. Le champ n'est requis que quand les conditions \u00e9valuent \u00e0 true en fonction des valeurs d'autres champs."
          },
          "visibility_conditions": {
            "$ref": "#/components/schemas/ConditionSet",
            "nullable": true,
            "description": "R\u00e8gles conditionnelles pour d\u00e9terminer quand ce champ est visible. Quand c'est d\u00e9fini, le champ est cach\u00e9 sauf si les conditions \u00e9valuent \u00e0 true. Les champs cach\u00e9s ne sont pas valid\u00e9s \u00e0 la soumission."
          },
          "background_color": {
            "type": "string",
            "nullable": true,
            "pattern": "^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$",
            "description": "Couleur de fond du champ sous forme de cha\u00eene hexad\u00e9cimale (ex. '#FFFDE7', '#fff'). Utile pour mettre en \u00e9vidence les champs qui n\u00e9cessitent de l'attention.",
            "example": "#FFFDE7"
          }
        }
      },
      "AnchorTag": {
        "type": "object",
        "required": [
          "anchor_string",
          "type",
          "recipient_id"
        ],
        "description": "D\u00e9finition d'un tag d'ancrage pour le placement automatique de champs. Les tags d'ancrage sont des marqueurs de texte int\u00e9gr\u00e9s dans un document PDF (ex. '{{SIGN_HERE}}') qui sont automatiquement localis\u00e9s et convertis en champs positionn\u00e9s. Le texte d'ancrage est retir\u00e9 du PDF apr\u00e8s traitement par d\u00e9faut.",
        "properties": {
          "anchor_string": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Cha\u00eene de texte \u00e0 rechercher dans le document PDF. Les patterns courants incluent '{{SIGN_HERE}}', '{{DATE}}', etc.",
            "example": "{{SIGN_HERE}}"
          },
          "type": {
            "type": "string",
            "enum": [
              "signature",
              "initial",
              "initials",
              "text",
              "date",
              "checkbox",
              "radio_buttons",
              "radio",
              "dropdown",
              "textarea",
              "text_area",
              "url",
              "approval_signature",
              "approval_checkmark",
              "approval_date"
            ],
            "description": "Type de champ \u00e0 placer \u00e0 l'emplacement de l'ancrage"
          },
          "recipient_id": {
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "type": "string"
              }
            ],
            "description": "ID du destinataire assign\u00e9 \u00e0 ce champ. Utilisez un ID temporaire (ex. 'temp_1') pour la cr\u00e9ation bas\u00e9e sur un document, ou un ordre entier pour la cr\u00e9ation bas\u00e9e sur un mod\u00e8le.",
            "example": "temp_1"
          },
          "x_offset": {
            "type": "number",
            "description": "D\u00e9calage horizontal par rapport \u00e0 la position de l'ancrage. Les unit\u00e9s sont d\u00e9termin\u00e9es par offset_units (par d\u00e9faut : pourcentage de la largeur de la page).",
            "default": 0
          },
          "y_offset": {
            "type": "number",
            "description": "D\u00e9calage vertical par rapport \u00e0 la position de l'ancrage. Les unit\u00e9s sont d\u00e9termin\u00e9es par offset_units (par d\u00e9faut : pourcentage de la hauteur de la page).",
            "default": 0
          },
          "offset_units": {
            "type": "string",
            "enum": [
              "percent",
              "pixels"
            ],
            "default": "percent",
            "description": "Type d'unit\u00e9 pour x_offset et y_offset. 'percent' = pourcentage des dimensions de la page, 'pixels' = points PDF (72 DPI)."
          },
          "width": {
            "type": "number",
            "minimum": 0,
            "exclusiveMinimum": true,
            "description": "Largeur du champ en pourcentage de la largeur de la page. Les valeurs par d\u00e9faut varient selon le type de champ (ex. signature=25, text=20, checkbox=3)."
          },
          "height": {
            "type": "number",
            "minimum": 0,
            "exclusiveMinimum": true,
            "description": "Hauteur du champ en pourcentage de la hauteur de la page. Les valeurs par d\u00e9faut varient selon le type de champ (ex. signature=5, text=3, checkbox=3)."
          },
          "case_sensitive": {
            "type": "boolean",
            "default": false,
            "description": "Indique si la correspondance de la cha\u00eene d'ancrage est sensible \u00e0 la casse"
          },
          "match_whole_word": {
            "type": "boolean",
            "default": true,
            "description": "Indique s'il faut faire correspondre uniquement des mots entiers (d\u00e9limit\u00e9s par des caract\u00e8res non-alphanum\u00e9riques)"
          },
          "ignore_if_not_present": {
            "type": "boolean",
            "default": false,
            "description": "Si true, ignore cette ancre sans erreur si elle n'est pas trouv\u00e9e dans le document. Si false (par d\u00e9faut), une ancre manquante provoque une erreur de validation."
          },
          "occurrence": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000,
            "default": 0,
            "description": "Quelle occurrence utiliser pour placer un champ. 0 = toutes les occurrences (par d\u00e9faut), 1 = la premi\u00e8re seulement, 2 = la deuxi\u00e8me seulement, etc."
          },
          "remove_anchor_text": {
            "type": "boolean",
            "default": true,
            "description": "Indique s'il faut retirer le texte d'ancrage du PDF en dessinant un rectangle blanc par-dessus"
          },
          "required": {
            "type": "boolean",
            "default": true,
            "description": "Indique si le champ doit \u00eatre compl\u00e9t\u00e9 par le signataire"
          },
          "read_only": {
            "type": "boolean",
            "default": false,
            "description": "Indique si le champ est en lecture seule (pr\u00e9-rempli)"
          },
          "read_only_value": {
            "type": "string",
            "nullable": true,
            "maxLength": 10000,
            "description": "Valeur statique pour les champs en lecture seule"
          },
          "variable_name": {
            "type": "string",
            "nullable": true,
            "maxLength": 255,
            "description": "Nom de variable pour le champ"
          },
          "variable_defined_name": {
            "type": "string",
            "maxLength": 100,
            "nullable": true,
            "description": "Nom de d\u00e9finition de champ personnalis\u00e9 lisible par un humain. Peut \u00eatre utilis\u00e9 comme alternative \u00e0 variable_name pour cibler des champs dans la cr\u00e9ation bas\u00e9e sur un mod\u00e8le."
          },
          "background_color": {
            "type": "string",
            "nullable": true,
            "pattern": "^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$",
            "description": "Couleur de fond en hexad\u00e9cimal (ex. '#FFFDE7')",
            "example": "#FFFDE7"
          },
          "font_size": {
            "type": "integer",
            "minimum": 8,
            "maximum": 48,
            "description": "Taille de police initiale/maximale facultative en pixels pour les types de champs textuels, enregistr\u00e9e sur le champ r\u00e9solu sous format_rules.fontSize (voir TextFormatRules). Le texte se r\u00e9duit automatiquement pour tenir dans le cadre du champ. Omettez-la pour un dimensionnement automatique. Les valeurs hors de la plage 8-48 sont ramen\u00e9es \u00e0 cette plage ; les valeurs non num\u00e9riques sont ignor\u00e9es.",
            "example": 12
          },
          "dropdown_options": {
            "description": "Options pour les champs d\u00e9roulants",
            "oneOf": [
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              {
                "type": "object"
              }
            ]
          },
          "date_default": {
            "type": "string",
            "nullable": true,
            "maxLength": 50,
            "description": "Valeur de date par d\u00e9faut"
          },
          "date_signing_default": {
            "type": "boolean",
            "default": false,
            "description": "Utiliser la date de signature comme valeur par d\u00e9faut"
          },
          "multi_group_id": {
            "type": "string",
            "nullable": true,
            "maxLength": 255,
            "description": "ID de groupe pour lier des champs checkbox/radio"
          }
        }
      },
      "ConditionSet": {
        "type": "object",
        "required": [
          "logic",
          "groups"
        ],
        "description": "Un ensemble de groupes de conditions avec une logique imbriqu\u00e9e. L'op\u00e9rateur 'logic' externe combine les groupes, tandis que les conditions de chaque groupe utilisent l'op\u00e9rateur oppos\u00e9. Exemple : logic='and' signifie que tous les groupes doivent correspondre, et qu'au sein de chaque groupe n'importe quelle condition peut correspondre (OR).",
        "properties": {
          "logic": {
            "type": "string",
            "enum": [
              "and",
              "or"
            ],
            "description": "Op\u00e9rateur logique pour combiner les groupes. 'and' = tous les groupes doivent correspondre, 'or' = n'importe quel groupe peut correspondre."
          },
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ConditionGroup"
            },
            "description": "Tableau de groupes de conditions"
          }
        }
      },
      "ConditionGroup": {
        "type": "object",
        "required": [
          "conditions"
        ],
        "properties": {
          "conditions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Condition"
            },
            "description": "Tableau de conditions au sein de ce groupe. Combin\u00e9es en utilisant l'op\u00e9rateur logique oppos\u00e9 \u00e0 celui du ConditionSet parent."
          }
        }
      },
      "Condition": {
        "type": "object",
        "required": [
          "field_id",
          "operator"
        ],
        "description": "Une condition unique qui \u00e9value la valeur d'un champ.",
        "properties": {
          "field_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID du champ \u00e0 \u00e9valuer"
          },
          "operator": {
            "type": "string",
            "enum": [
              "is_filled",
              "is_empty",
              "equals",
              "not_equals",
              "contains",
              "not_contains",
              "greater_than",
              "less_than",
              "greater_than_or_equal",
              "less_than_or_equal"
            ],
            "description": "Op\u00e9rateur de comparaison. 'is_filled'/'is_empty' ne n\u00e9cessitent pas de valeur. Op\u00e9rateurs de texte : equals, not_equals, contains, not_contains. Op\u00e9rateurs num\u00e9riques/date : greater_than, less_than, greater_than_or_equal, less_than_or_equal."
          },
          "value": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ],
            "nullable": true,
            "description": "Valeur \u00e0 comparer. Non requise pour les op\u00e9rateurs is_filled/is_empty."
          }
        }
      },
      "SigningRequestReminder": {
        "type": "object",
        "required": [
          "hours",
          "subject",
          "message"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique (\u00e0 inclure pour les mises \u00e0 jour, \u00e0 omettre pour les nouveaux rappels)"
          },
          "hours": {
            "type": "integer",
            "minimum": 1,
            "description": "Heures avant l'expiration pour envoyer le rappel"
          },
          "all_users": {
            "type": "boolean",
            "default": false,
            "description": "Envoyer le rappel \u00e0 tous les destinataires"
          },
          "recipient_id": {
            "type": "string",
            "nullable": true,
            "description": "ID de destinataire sp\u00e9cifique (requis si all_users est false). Utilisez un v\u00e9ritable UUID pour les destinataires existants ou un ID temporaire (par exemple, 'temp_1') pour la cr\u00e9ation bas\u00e9e sur un document afin de r\u00e9f\u00e9rencer des destinataires dans la m\u00eame demande."
          },
          "subject": {
            "type": "string",
            "maxLength": 255,
            "description": "Objet de l'email"
          },
          "message": {
            "type": "string",
            "maxLength": 5000,
            "description": "Corps du message de l'email"
          }
        }
      },
      "DeletedRecipient": {
        "type": "object",
        "required": [
          "recipient_id",
          "field_action"
        ],
        "properties": {
          "recipient_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID du destinataire \u00e0 supprimer"
          },
          "field_action": {
            "type": "string",
            "enum": [
              "delete",
              "reassign"
            ],
            "description": "Action \u00e0 effectuer sur les champs assign\u00e9s \u00e0 ce destinataire"
          },
          "reassign_to_recipient_id": {
            "type": "string",
            "format": "uuid",
            "description": "Destinataire vers lequel r\u00e9assigner les champs (requis si field_action est 'reassign')"
          }
        }
      },
      "SigningRequestUser": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique de l'utilisateur de la demande de signature"
          },
          "name": {
            "type": "string",
            "description": "Nom du destinataire (pr\u00e9nom et nom combin\u00e9s)"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Adresse email du destinataire"
          },
          "first_name": {
            "type": "string",
            "nullable": true,
            "description": "Pr\u00e9nom du destinataire"
          },
          "last_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom du destinataire"
          },
          "designation": {
            "type": "string",
            "enum": [
              "Signer",
              "Approver",
              "CC"
            ],
            "description": "R\u00f4le du destinataire. Le Signataire signe le document, l'Approbateur approuve avec des champs d'approbation, le CC re\u00e7oit une copie \u00e0 la fin."
          },
          "order": {
            "type": "integer",
            "minimum": 1,
            "description": "Ordre de signature"
          },
          "finished_on": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage de la fin de toutes les actions de ce destinataire"
          },
          "declined_on": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage du refus de signer de ce destinataire"
          },
          "decline_reason": {
            "type": "string",
            "nullable": true,
            "description": "Raison fournie par le destinataire pour son refus"
          },
          "phone_number": {
            "type": "string",
            "nullable": true,
            "description": "Num\u00e9ro de t\u00e9l\u00e9phone du destinataire"
          },
          "street_address": {
            "type": "string",
            "nullable": true,
            "description": "Adresse postale du destinataire"
          },
          "city": {
            "type": "string",
            "nullable": true,
            "description": "Ville du destinataire"
          },
          "state_province": {
            "type": "string",
            "nullable": true,
            "description": "\u00c9tat ou province du destinataire"
          },
          "postal_code": {
            "type": "string",
            "nullable": true,
            "description": "Code postal du destinataire"
          },
          "country": {
            "type": "string",
            "nullable": true,
            "description": "Pays du destinataire"
          },
          "title": {
            "type": "string",
            "nullable": true,
            "description": "Titre du poste du destinataire"
          },
          "company": {
            "type": "string",
            "nullable": true,
            "description": "Nom de l'entreprise du destinataire"
          },
          "custom_fields": {
            "type": "object",
            "nullable": true,
            "description": "Valeurs des champs personnalis\u00e9s pour ce destinataire"
          },
          "required_fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Liste des champs de donn\u00e9es du destinataire requis pour l'envoi (bas\u00e9e sur les champs avec des correspondances variable_name). Inclut toujours 'email' et 'first_name'."
          },
          "missing_fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Liste des champs requis actuellement vides pour ce destinataire"
          },
          "required_read_only_fields": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "variable_name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Nom de variable du champ en lecture seule"
                },
                "variable_defined_name": {
                  "type": "string",
                  "nullable": true,
                  "description": "Nom de champ lisible provenant de la d\u00e9finition du champ personnalis\u00e9 (par exemple, 'artist_name'). Pr\u00e9sent uniquement pour les champs li\u00e9s \u00e0 une d\u00e9finition de champ personnalis\u00e9, sinon null."
                },
                "field_type": {
                  "type": "string",
                  "description": "Type du champ (text, date, etc.)"
                },
                "has_value": {
                  "type": "boolean",
                  "description": "Indique si ce champ en lecture seule a une valeur d\u00e9finie"
                }
              }
            },
            "description": "Liste des champs en lecture seule requis n\u00e9cessitant des valeurs pr\u00e9remplies avant l'envoi"
          },
          "ready_to_send": {
            "type": "boolean",
            "description": "Indique si ce destinataire dispose de toutes les donn\u00e9es requises remplies pour l'envoi"
          }
        },
        "required": [
          "id",
          "first_name",
          "email",
          "designation",
          "order"
        ]
      },
      "SigningRequestField": {
        "type": "object",
        "description": "Champ associ\u00e9 \u00e0 une demande de signature, contenant des informations de position, de type et de valeur",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique du champ"
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "signature",
              "date",
              "checkbox",
              "initial",
              "dropdown",
              "radio_buttons",
              "text_area",
              "url",
              "file",
              "stamp",
              "approval_signature",
              "approval_checkmark",
              "approval_date"
            ],
            "description": "Type du champ. Alias simplifi\u00e9 de field_type."
          },
          "recipient_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "ID du destinataire assign\u00e9 \u00e0 ce champ. Alias simplifi\u00e9 de companies_workspaces_signing_requests_users_id."
          },
          "value": {
            "type": "string",
            "nullable": true,
            "description": "Valeur finale sign\u00e9e du champ. Alias simplifi\u00e9 de final_value."
          },
          "position": {
            "type": "object",
            "description": "Position et dimensions du champ sur le document. Toutes les valeurs sont des pourcentages (0-100).",
            "properties": {
              "x": {
                "type": "number",
                "nullable": true,
                "description": "Position X (pourcentage, 0-100). Alias simplifi\u00e9 de x_postion."
              },
              "y": {
                "type": "number",
                "nullable": true,
                "description": "Position Y (pourcentage, 0-100). Alias simplifi\u00e9 de y_position."
              },
              "width": {
                "type": "number",
                "nullable": true,
                "description": "Largeur (pourcentage, 0-100)."
              },
              "height": {
                "type": "number",
                "nullable": true,
                "description": "Hauteur (pourcentage, 0-100). Alias simplifi\u00e9 de heigh."
              }
            }
          },
          "companies_workspaces_signing_requests_id": {
            "type": "string",
            "format": "uuid",
            "description": "D\u00e9pr\u00e9ci\u00e9 : redondant avec le param\u00e8tre de chemin. ID de la demande de signature \u00e0 laquelle ce champ appartient."
          },
          "companies_workspaces_signing_requests_users_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "D\u00e9pr\u00e9ci\u00e9 : utilisez 'recipient_id' \u00e0 la place. ID du destinataire assign\u00e9 \u00e0 ce champ."
          },
          "field_type": {
            "type": "string",
            "enum": [
              "text",
              "signature",
              "date",
              "checkbox",
              "initial",
              "dropdown",
              "radio_buttons",
              "text_area",
              "url",
              "file",
              "stamp",
              "approval_signature",
              "approval_checkmark",
              "approval_date"
            ],
            "description": "D\u00e9pr\u00e9ci\u00e9 : utilisez 'type' \u00e0 la place. Type du champ."
          },
          "required": {
            "type": "boolean",
            "description": "Indique si le champ est requis."
          },
          "x_postion": {
            "type": "number",
            "nullable": true,
            "description": "D\u00e9pr\u00e9ci\u00e9 : utilisez 'position.x' \u00e0 la place. Position X (remarque : le nom de la colonne contient une faute de frappe)."
          },
          "y_position": {
            "type": "number",
            "nullable": true,
            "description": "D\u00e9pr\u00e9ci\u00e9 : utilisez 'position.y' \u00e0 la place. Position Y du champ."
          },
          "width": {
            "type": "number",
            "nullable": true,
            "description": "D\u00e9pr\u00e9ci\u00e9 : utilisez 'position.width' \u00e0 la place. Largeur du champ."
          },
          "heigh": {
            "type": "number",
            "nullable": true,
            "description": "D\u00e9pr\u00e9ci\u00e9 : utilise plut\u00f4t 'position.height'. Hauteur (note : le nom de la colonne contient une faute de frappe)."
          },
          "page_number": {
            "type": "integer",
            "nullable": true,
            "description": "Num\u00e9ro de page o\u00f9 se trouve le champ (index\u00e9 \u00e0 partir de 1)"
          },
          "tl_position": {
            "type": "number",
            "nullable": true,
            "description": "Position du coin sup\u00e9rieur gauche"
          },
          "tr_position": {
            "type": "number",
            "nullable": true,
            "description": "Position du coin sup\u00e9rieur droit"
          },
          "bl_position": {
            "type": "number",
            "nullable": true,
            "description": "Position du coin inf\u00e9rieur gauche"
          },
          "br_position": {
            "type": "number",
            "nullable": true,
            "description": "Position du coin inf\u00e9rieur droit"
          },
          "variable_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de variable pour le mapping des donn\u00e9es pr\u00e9-remplies"
          },
          "variable_defined_name": {
            "type": "string",
            "nullable": true,
            "description": "Nom de champ lisible provenant de la d\u00e9finition du champ personnalis\u00e9 (ex. 'artist_name'). Pr\u00e9sent uniquement pour les champs li\u00e9s \u00e0 une d\u00e9finition de champ personnalis\u00e9, sinon null."
          },
          "final_value": {
            "type": "string",
            "nullable": true,
            "description": "D\u00e9pr\u00e9ci\u00e9 : utilise plut\u00f4t 'value'. Valeur finale sign\u00e9e du champ."
          },
          "date_default": {
            "type": "string",
            "nullable": true,
            "description": "Valeur de date par d\u00e9faut"
          },
          "date_signing_default": {
            "type": "boolean",
            "nullable": true,
            "description": "Indique s'il faut utiliser la date de signature comme valeur par d\u00e9faut."
          },
          "format_rules": {
            "type": "object",
            "nullable": true,
            "description": "R\u00e8gles de formatage (ex. format de date)"
          },
          "validation_rules": {
            "type": "object",
            "nullable": true,
            "description": "R\u00e8gles de validation pour le champ"
          },
          "dropdown_options": {
            "nullable": true,
            "description": "Options pour les champs de type liste d\u00e9roulante",
            "oneOf": [
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              {
                "type": "object"
              }
            ]
          },
          "multi_group_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "ID de groupe pour lier plusieurs champs de case \u00e0 cocher ou bouton radio ensemble. Les champs partageant le m\u00eame multi_group_id se comportent comme un groupe mutuellement exclusif (comme des boutons radio) - s\u00e9lectionner l'un d\u00e9s\u00e9lectionne automatiquement les autres du groupe. Utilise le m\u00eame UUID sur plusieurs champs pour cr\u00e9er un groupe o\u00f9 une seule option peut \u00eatre s\u00e9lectionn\u00e9e \u00e0 la fois."
          },
          "read_only": {
            "type": "boolean",
            "description": "Indique si le champ est en lecture seule."
          },
          "read_only_value": {
            "type": "string",
            "nullable": true,
            "description": "Valeur statique pour les champs en lecture seule"
          },
          "background_color": {
            "type": "string",
            "nullable": true,
            "description": "Couleur de fond en hexad\u00e9cimal (ex. '#FFFDE7')"
          },
          "calculated_font_size": {
            "type": "number",
            "nullable": true,
            "description": "Taille de police calcul\u00e9e pour le champ"
          },
          "deleted": {
            "type": "integer",
            "enum": [
              0,
              1
            ],
            "description": "D\u00e9pr\u00e9ci\u00e9 : champ interne, sera supprim\u00e9 en v2. Indicateur de suppression logique (0 = actif, 1 = supprim\u00e9)."
          }
        },
        "required": [
          "id",
          "field_type",
          "page_number"
        ]
      },
      "SendSigningRequestResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Indique si la Demande de Signature a \u00e9t\u00e9 envoy\u00e9e avec succ\u00e8s"
          },
          "message": {
            "type": "string",
            "description": "Message de succ\u00e8s"
          },
          "sentTo": {
            "type": "string",
            "format": "email",
            "description": "Adresse e-mail \u00e0 laquelle la Demande de Signature a \u00e9t\u00e9 envoy\u00e9e"
          },
          "sentAt": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de l'envoi de la demande"
          }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique du Webhook"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "URL du Webhook"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Description du Webhook"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "\u00c9v\u00e9nements qui d\u00e9clenchent ce Webhook"
          },
          "enabled": {
            "type": "boolean",
            "description": "Indique si le Webhook est activ\u00e9"
          },
          "consecutive_failures": {
            "type": "integer",
            "description": "Nombre d'\u00e9checs de livraison cons\u00e9cutifs"
          },
          "auto_disabled_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage de la d\u00e9sactivation automatique du Webhook suite \u00e0 des \u00e9checs"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de cr\u00e9ation du Webhook"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de la derni\u00e8re mise \u00e0 jour du Webhook"
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "enabled",
          "created_at"
        ]
      },
      "PatchSigningRequestBodySchema": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "document"
            ],
            "description": "Cr\u00e9er une Demande de Signature \u00e0 partir d'un document PDF",
            "properties": {
              "document": {
                "type": "string",
                "format": "byte",
                "description": "Document PDF ou DOCX encod\u00e9 en base64. Les fichiers DOCX sont automatiquement convertis en PDF. Le nombre de pages sera extrait automatiquement."
              },
              "name": {
                "type": "string",
                "maxLength": 255,
                "description": "Nom de la Demande de Signature"
              },
              "description": {
                "type": "string",
                "description": "Description de la Demande de Signature"
              },
              "expiration_hours": {
                "type": "integer",
                "minimum": 1,
                "default": 168,
                "description": "Nombre d'heures avant l'expiration de la Demande de Signature (par d\u00e9faut : 168 = 7 jours)"
              },
              "recipients": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Recipient"
                },
                "description": "Destinataires de la Demande de Signature. Utilise des ID temporaires (ex. 'temp_1') dans le champ id pour r\u00e9f\u00e9rencer les destinataires dans fields/reminders."
              },
              "fields": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Field"
                },
                "description": "Champs \u00e0 placer sur le document. Utilise recipient_id pour assigner les champs aux destinataires."
              },
              "anchor_tags": {
                "type": "array",
                "maxItems": 100,
                "items": {
                  "$ref": "#/components/schemas/AnchorTag"
                },
                "description": "Balises d'ancrage pour le placement automatique des champs. Les marqueurs de texte dans le PDF sont localis\u00e9s et convertis en champs positionn\u00e9s. Le texte d'ancrage est supprim\u00e9 du PDF apr\u00e8s traitement. Les champs cr\u00e9\u00e9s \u00e0 partir de balises d'ancrage sont ajout\u00e9s en plus des champs sp\u00e9cifi\u00e9s manuellement. Disponible uniquement pour la cr\u00e9ation bas\u00e9e sur un document (pas bas\u00e9e sur un Mod\u00e8le)."
              },
              "reminders": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/SigningRequestReminder"
                },
                "description": "Rappels \u00e0 envoyer aux destinataires"
              },
              "settings": {
                "$ref": "#/components/schemas/SigningRequestSettings",
                "description": "Param\u00e8tres de la Demande de Signature"
              },
              "language": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "en",
                  "es",
                  "it",
                  "pt",
                  "fr",
                  "de",
                  "el",
                  "ru",
                  "pl",
                  "cs",
                  "sv",
                  "nl",
                  "ro",
                  "nb"
                ],
                "description": "Langue facultative des e-mails pour cette demande de signature. Lorsqu'elle est d\u00e9finie, tous les e-mails destin\u00e9s au signataire (et le format de date) l'utilisent. Omettez-la ou utilisez null pour revenir \u00e0 la langue par d\u00e9faut de l'espace de travail, puis de l'entreprise (comportement inchang\u00e9)."
              }
            }
          },
          {
            "type": "object",
            "required": [
              "template_id"
            ],
            "description": "Cr\u00e9er une Demande de Signature \u00e0 partir d'un Mod\u00e8le. Prend en charge les mises \u00e0 jour partielles pour les destinataires et les champs.",
            "properties": {
              "template_id": {
                "type": "string",
                "format": "uuid",
                "description": "ID du Mod\u00e8le \u00e0 partir duquel cr\u00e9er la Demande de Signature. Le document, les champs et les destinataires par d\u00e9faut seront copi\u00e9s depuis le Mod\u00e8le."
              },
              "name": {
                "type": "string",
                "maxLength": 255,
                "description": "Nom personnalis\u00e9 pour la Demande de Signature (par d\u00e9faut, le nom du Mod\u00e8le si non fourni)"
              },
              "description": {
                "type": "string",
                "description": "Description personnalis\u00e9e (par d\u00e9faut, la description du Mod\u00e8le si non fournie)"
              },
              "expiration_hours": {
                "type": "integer",
                "minimum": 1,
                "description": "Remplace le nombre d'heures d'expiration du Mod\u00e8le"
              },
              "recipients": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Recipient"
                },
                "description": "Remplacements optionnels des destinataires. Utilise template_user_id (pr\u00e9f\u00e9r\u00e9) ou order (en repli) pour faire correspondre les utilisateurs du Mod\u00e8le. Seules les informations utilisateur (first_name, last_name, email, phone_number, les champs d'adresse, title, company) peuvent \u00eatre mises \u00e0 jour - order et designation sont toujours h\u00e9rit\u00e9s du Mod\u00e8le. Les destinataires non fournis utiliseront les valeurs par d\u00e9faut du Mod\u00e8le."
              },
              "fields": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Field"
                },
                "description": "Surcharges de champs optionnelles pour les mises \u00e0 jour partielles. Utilisez template_field_id (pr\u00e9f\u00e9r\u00e9) ou variable_name (solution de repli) pour faire correspondre les champs du mod\u00e8le. Seules les propri\u00e9t\u00e9s fournies remplacent les valeurs par d\u00e9faut du mod\u00e8le. Propri\u00e9t\u00e9s de surcharge prises en charge : type, required, position, read_only, read_only_value, format_rules, validation_rules, dropdown_options, date_default, date_signing_default, multi_group_id. Les champs non trouv\u00e9s sont ignor\u00e9s. Si le tableau fields est omis, tous les champs du mod\u00e8le sont utilis\u00e9s tels quels."
              },
              "settings": {
                "$ref": "#/components/schemas/SigningRequestSettings",
                "description": "Remplacer les param\u00e8tres du mod\u00e8le"
              },
              "language": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "en",
                  "es",
                  "it",
                  "pt",
                  "fr",
                  "de",
                  "el",
                  "ru",
                  "pl",
                  "cs",
                  "sv",
                  "nl",
                  "ro",
                  "nb"
                ],
                "description": "Langue facultative des e-mails pour cette demande de signature. Lorsqu'elle est d\u00e9finie, tous les e-mails destin\u00e9s au signataire (et le format de date) l'utilisent. Omettez-la ou utilisez null pour revenir \u00e0 la langue par d\u00e9faut de l'espace de travail, puis de l'entreprise (comportement inchang\u00e9)."
              }
            },
            "example": {
              "template_id": "21424147-11c0-43d5-ac5f-a1f7001b5607",
              "name": "Contract for Client X",
              "recipients": [
                {
                  "template_user_id": "template-user-uuid-1",
                  "first_name": "Toni",
                  "last_name": "Campins",
                  "email": "acampins@cocodin.com"
                }
              ],
              "fields": [
                {
                  "template_field_id": "field-uuid-1",
                  "read_only": true,
                  "read_only_value": "Contract #12345"
                },
                {
                  "variable_name": "company_name",
                  "read_only_value": "Acme Corporation"
                }
              ]
            }
          }
        ]
      },
      "UpdateSigningRequestBodySchema": {
        "type": "object",
        "properties": {
          "signing_request_properties": {
            "type": "object",
            "description": "Mettre \u00e0 jour les propri\u00e9t\u00e9s de la demande de signature",
            "properties": {
              "name": {
                "type": "string",
                "maxLength": 255
              },
              "description": {
                "type": "string"
              },
              "document": {
                "type": "string",
                "format": "byte",
                "description": "Remplacer le document (PDF encod\u00e9 en base64)"
              },
              "expiration_hours": {
                "type": "integer",
                "minimum": 1
              },
              "settings": {
                "$ref": "#/components/schemas/SigningRequestSettings"
              }
            }
          },
          "recipients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Recipient"
            },
            "description": "Upsert des destinataires - incluez 'id' pour mettre \u00e0 jour des destinataires existants, utilisez '_temp_id' (par ex. 'temp_1') pour les nouveaux destinataires afin de les r\u00e9f\u00e9rencer dans les champs et rappels au sein de la m\u00eame requ\u00eate"
          },
          "deleted_recipients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DeletedRecipient"
            },
            "description": "Destinataires \u00e0 supprimer et comment g\u00e9rer leurs champs"
          },
          "force_remove_conditions": {
            "type": "boolean",
            "default": false,
            "description": "Lors de la suppression de destinataires dont les champs sont r\u00e9f\u00e9renc\u00e9s par des conditions dans d'autres champs : si true, retire automatiquement les r\u00e9f\u00e9rences de condition ; si false (par d\u00e9faut), la requ\u00eate sera rejet\u00e9e avec une erreur listant les champs d\u00e9pendants."
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Field"
            },
            "description": "Upsert des champs - incluez id pour mettre \u00e0 jour, omettez id pour cr\u00e9er un nouveau champ"
          },
          "reminders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SigningRequestReminder"
            },
            "description": "Upsert des rappels - incluez id pour mettre \u00e0 jour, omettez id pour cr\u00e9er un nouveau rappel"
          },
          "language": {
            "type": "string",
            "nullable": true,
            "enum": [
              "en",
              "es",
              "it",
              "pt",
              "fr",
              "de",
              "el",
              "ru",
              "pl",
              "cs",
              "sv",
              "nl",
              "ro",
              "nb"
            ],
            "description": "Langue facultative des e-mails pour cette demande de signature. Lorsqu'elle est d\u00e9finie, tous les e-mails destin\u00e9s au signataire (et le format de date) l'utilisent. Omettez-la ou utilisez null pour revenir \u00e0 la langue par d\u00e9faut de l'espace de travail, puis de l'entreprise (comportement inchang\u00e9)."
          }
        }
      },
      "GenerateJWTRequest": {
        "type": "object",
        "required": [
          "companies_workspaces_templates_id"
        ],
        "properties": {
          "companies_workspaces_templates_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID du mod\u00e8le pour lequel g\u00e9n\u00e9rer un JWT"
          }
        }
      },
      "GenerateJWTResponse": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "Le jeton JWT g\u00e9n\u00e9r\u00e9"
          },
          "jwt_record_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique de cet enregistrement JWT"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage d'expiration du JWT (30 jours apr\u00e8s la cr\u00e9ation)"
          }
        },
        "required": [
          "token",
          "expires_at"
        ]
      },
      "RevokeJWTRequest": {
        "type": "object",
        "required": [
          "jwt_id"
        ],
        "properties": {
          "jwt_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID du jeton JWT \u00e0 r\u00e9voquer"
          }
        }
      },
      "RevokeJWTResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "Message de confirmation"
          },
          "jwt_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID du JWT r\u00e9voqu\u00e9"
          },
          "revoked": {
            "type": "boolean",
            "description": "Indique si le JWT a \u00e9t\u00e9 r\u00e9voqu\u00e9 avec succ\u00e8s"
          }
        },
        "required": [
          "message"
        ]
      },
      "GenerateSigningRequestJWTRequest": {
        "type": "object",
        "required": [
          "companies_workspaces_signing_requests_id"
        ],
        "properties": {
          "companies_workspaces_signing_requests_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de la demande de signature pour laquelle g\u00e9n\u00e9rer un JWT"
          }
        }
      },
      "GenerateSigningRequestJWTResponse": {
        "type": "object",
        "properties": {
          "jwt": {
            "type": "string",
            "description": "Le jeton JWT g\u00e9n\u00e9r\u00e9"
          },
          "jwt_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique de ce JWT"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage d'expiration du JWT (7 jours apr\u00e8s la cr\u00e9ation)"
          },
          "signing_request_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de la demande de signature \u00e0 laquelle ce JWT est associ\u00e9"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de cr\u00e9ation du JWT"
          }
        },
        "required": [
          "jwt",
          "expires_at",
          "signing_request_id"
        ]
      },
      "RevokeSigningRequestJWTRequest": {
        "type": "object",
        "required": [
          "jwt_id"
        ],
        "properties": {
          "jwt_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID du jeton JWT \u00e0 r\u00e9voquer"
          }
        }
      },
      "RevokeSigningRequestJWTResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "Message de confirmation"
          },
          "jwt_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID du JWT r\u00e9voqu\u00e9"
          },
          "revoked": {
            "type": "boolean",
            "description": "Indique si le JWT a \u00e9t\u00e9 r\u00e9voqu\u00e9 avec succ\u00e8s"
          }
        },
        "required": [
          "message"
        ]
      },
      "ColorPalette": {
        "type": "object",
        "description": "Palette de couleurs r\u00e9solue pour l'exp\u00e9rience de signature. Toutes les valeurs sont des cha\u00eenes de couleur hexad\u00e9cimales (#rrggbb).",
        "properties": {
          "primary": {
            "type": "string",
            "description": "Couleur d'action principale (boutons, liens, accents)",
            "example": "#2563eb"
          },
          "primary_fg": {
            "type": "string",
            "description": "Couleur du texte sur les \u00e9l\u00e9ments de couleur principale",
            "example": "#ffffff"
          },
          "background": {
            "type": "string",
            "description": "Couleur de fond de la page/du canevas",
            "example": "#1c1c21"
          },
          "foreground": {
            "type": "string",
            "description": "Couleur principale du texte",
            "example": "#ffffff"
          },
          "card": {
            "type": "string",
            "description": "Couleur de fond des cartes/panneaux",
            "example": "#22222a"
          },
          "border": {
            "type": "string",
            "description": "Couleur des bordures et s\u00e9parateurs",
            "example": "#3b3b3b"
          },
          "accent": {
            "type": "string",
            "description": "Accent de l'interface de l'\u00e9diteur",
            "example": "#34eeff"
          },
          "accent_fg": {
            "type": "string",
            "description": "Premier plan sur l'accent",
            "example": "#000000"
          },
          "canvas": {
            "type": "string",
            "description": "Pourtour du canevas de document de l'\u00e9diteur",
            "example": "#0f1419"
          },
          "muted": {
            "type": "string",
            "description": "Surface att\u00e9nu\u00e9e (par d\u00e9faut la carte r\u00e9solue)",
            "example": "#22222a"
          },
          "muted_fg": {
            "type": "string",
            "description": "Texte att\u00e9nu\u00e9 (d\u00e9riv\u00e9 pour la lisibilit\u00e9 si non d\u00e9fini)",
            "example": "#b8b8b8"
          }
        }
      },
      "CompanySettings": {
        "type": "object",
        "properties": {
          "default_expiration_hours": {
            "type": "integer",
            "minimum": 1
          },
          "require_terms_acceptance": {
            "type": "boolean"
          },
          "show_custom_branding_only": {
            "type": "boolean"
          },
          "require_otp_verification": {
            "type": "boolean"
          },
          "allow_presigning_download": {
            "type": "boolean"
          },
          "disable_guided_navigation": {
            "type": "boolean"
          },
          "show_signature_frame": {
            "type": "boolean"
          },
          "show_partial_watermark": {
            "type": "boolean"
          },
          "email_local_part": {
            "type": "string"
          },
          "color_primary": {
            "type": "string",
            "nullable": true
          },
          "color_primary_fg": {
            "type": "string",
            "nullable": true
          },
          "color_background": {
            "type": "string",
            "nullable": true
          },
          "color_foreground": {
            "type": "string",
            "nullable": true
          },
          "color_card": {
            "type": "string",
            "nullable": true
          },
          "color_border": {
            "type": "string",
            "nullable": true
          },
          "color_accent": {
            "type": "string",
            "nullable": true
          },
          "color_accent_fg": {
            "type": "string",
            "nullable": true
          },
          "color_canvas": {
            "type": "string",
            "nullable": true
          },
          "color_muted": {
            "type": "string",
            "nullable": true
          },
          "color_muted_fg": {
            "type": "string",
            "nullable": true
          },
          "show_qr_code": {
            "type": "boolean",
            "nullable": true,
            "description": "Afficher un QR code sur la page de signature permettant aux signataires de continuer sur leur t\u00e9l\u00e9phone. Il s'agit de la valeur par d\u00e9faut au niveau de l'entreprise ; les espaces de travail, mod\u00e8les et demandes de signature peuvent la remplacer."
          }
        },
        "required": [
          "default_expiration_hours"
        ]
      },
      "WorkspaceSettings": {
        "type": "object",
        "properties": {
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Nom de l'espace de travail"
          },
          "team_email": {
            "type": "string",
            "format": "email",
            "description": "Email de contact de l'espace de travail"
          },
          "timezone": {
            "type": "string",
            "description": "Fuseau horaire de l'espace de travail"
          },
          "language": {
            "type": "string",
            "description": "Langue de l'espace de travail pour les mod\u00e8les d'email",
            "enum": [
              "en",
              "es",
              "it",
              "pt",
              "fr",
              "de",
              "el",
              "ru",
              "pl",
              "cs",
              "sv",
              "nl",
              "ro",
              "nb"
            ],
            "default": "en"
          },
          "signing_request_email_header": {
            "type": "string",
            "description": "Texte d'en-t\u00eate d'email personnalis\u00e9"
          },
          "signing_request_email_body": {
            "type": "string",
            "description": "Corps d'email HTML personnalis\u00e9"
          },
          "show_credit_cost_in_editor": {
            "type": "boolean",
            "description": "Indique s'il faut afficher le co\u00fbt en cr\u00e9dits dans les \u00e9diteurs int\u00e9gr\u00e9s de mod\u00e8les et de demandes de signature",
            "default": true
          },
          "require_otp_verification": {
            "type": "boolean",
            "nullable": true,
            "description": "Indique si les signataires doivent v\u00e9rifier leur email via OTP avant d'acc\u00e9der aux documents. null = h\u00e9riter du param\u00e8tre de l'entreprise, true = exiger l'OTP, false = ne pas exiger l'OTP"
          },
          "require_terms_acceptance": {
            "type": "boolean",
            "nullable": true,
            "description": "Indique si les signataires doivent accepter les conditions avant de signer. null h\u00e9rite du param\u00e8tre au niveau de l'entreprise."
          },
          "disable_guided_navigation": {
            "type": "boolean",
            "nullable": true,
            "description": "D\u00e9sactiver le d\u00e9filement automatique vers le prochain champ obligatoire pendant la signature. H\u00e9rite de l'espace de travail ou de l'entreprise si non d\u00e9fini."
          },
          "show_signature_frame": {
            "type": "boolean",
            "nullable": true,
            "description": "Indique s'il faut afficher un cadre visuel avec l'ID de Signature autour des signatures dans les PDF finalis\u00e9s. null = h\u00e9riter du param\u00e8tre de l'entreprise (activ\u00e9 par d\u00e9faut), true = afficher le cadre, false = masquer le cadre"
          },
          "allow_presigning_download": {
            "type": "boolean",
            "nullable": true,
            "description": "Autoriser les signataires \u00e0 t\u00e9l\u00e9charger le document original avant de signer. null h\u00e9rite du param\u00e8tre au niveau de l'entreprise."
          },
          "show_partial_watermark": {
            "type": "boolean",
            "nullable": true,
            "description": "Afficher un filigrane EN COURS sur les t\u00e9l\u00e9chargements de PDF partiels lorsque tous les signataires n'ont pas termin\u00e9. null h\u00e9rite du param\u00e8tre au niveau de l'entreprise."
          },
          "show_qr_code": {
            "type": "boolean",
            "nullable": true,
            "description": "Afficher un QR code sur la page de signature permettant aux signataires de continuer sur leur t\u00e9l\u00e9phone. null h\u00e9rite du param\u00e8tre au niveau de l'entreprise."
          },
          "color_primary": {
            "type": "string",
            "nullable": true,
            "description": "Couleur primaire personnalis\u00e9e (hex #rrggbb). Null pour h\u00e9riter de l'entreprise.",
            "example": "#2563eb"
          },
          "color_primary_fg": {
            "type": "string",
            "nullable": true,
            "description": "Couleur de premier plan primaire personnalis\u00e9e. Null pour h\u00e9riter.",
            "example": "#ffffff"
          },
          "color_background": {
            "type": "string",
            "nullable": true,
            "description": "Couleur d'arri\u00e8re-plan personnalis\u00e9e. Null pour h\u00e9riter.",
            "example": "#0f172a"
          },
          "color_foreground": {
            "type": "string",
            "nullable": true,
            "description": "Couleur de premier plan/texte personnalis\u00e9e. Null pour h\u00e9riter.",
            "example": "#ffffff"
          },
          "color_card": {
            "type": "string",
            "nullable": true,
            "description": "Couleur d'arri\u00e8re-plan des cartes personnalis\u00e9e. Null pour h\u00e9riter.",
            "example": "#22222a"
          },
          "color_border": {
            "type": "string",
            "nullable": true,
            "description": "Couleur de bordure personnalis\u00e9e. Null pour h\u00e9riter.",
            "example": "#3b3b3b"
          },
          "color_accent": {
            "type": "string",
            "nullable": true,
            "description": "Couleur d'accent de l'interface de l'\u00e9diteur. Null pour h\u00e9riter.",
            "example": "#34eeff"
          },
          "color_accent_fg": {
            "type": "string",
            "nullable": true,
            "description": "Couleur de premier plan sur les surfaces d'accent. Null pour h\u00e9riter.",
            "example": "#000000"
          },
          "color_canvas": {
            "type": "string",
            "nullable": true,
            "description": "Couleur de l'entourage du canevas de document dans l'\u00e9diteur. Null pour h\u00e9riter.",
            "example": "#0f1419"
          },
          "color_muted": {
            "type": "string",
            "nullable": true,
            "description": "Couleur de surface att\u00e9nu\u00e9e. Null pour h\u00e9riter.",
            "example": "#22222a"
          },
          "color_muted_fg": {
            "type": "string",
            "nullable": true,
            "description": "Couleur de texte att\u00e9nu\u00e9e. Null pour h\u00e9riter.",
            "example": "#b8b8b8"
          },
          "email_local_part": {
            "type": "string",
            "nullable": true,
            "description": "La partie locale (avant le @) de l'adresse email de l'exp\u00e9diteur. Null pour h\u00e9riter du param\u00e8tre de l'entreprise. S'applique uniquement quand un domaine personnalis\u00e9 v\u00e9rifi\u00e9 est configur\u00e9.",
            "example": "signatures",
            "pattern": "^[a-z0-9]([a-z0-9._-]*[a-z0-9])?$",
            "minLength": 1,
            "maxLength": 64
          },
          "signing_button_label_overrides": {
            "type": "object",
            "nullable": true,
            "description": "Libell\u00e9s de boutons personnalis\u00e9s par langue pour la vue de signature. Les cl\u00e9s sont des codes de langue (en, de, etc.) ; les valeurs sont des objets associant des cl\u00e9s de traduction \u00e0 un texte personnalis\u00e9. Null pour utiliser les valeurs par d\u00e9faut.",
            "additionalProperties": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            }
          }
        },
        "required": [
          "workspace_id"
        ]
      },
      "WorkspaceCustomField": {
        "type": "object",
        "description": "Une d\u00e9finition de champ personnalis\u00e9 pour un Espace de Travail",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique"
          },
          "field_name": {
            "type": "string",
            "description": "Nom de champ lisible par machine (g\u00e9n\u00e9r\u00e9 automatiquement \u00e0 partir du libell\u00e9)"
          },
          "field_label": {
            "type": "string",
            "description": "Libell\u00e9 d'affichage lisible par un humain"
          },
          "is_preset": {
            "type": "boolean",
            "description": "Si true, ce champ a une valeur pr\u00e9d\u00e9finie pour tous les utilisateurs"
          },
          "preset_value": {
            "type": "string",
            "nullable": true,
            "description": "Valeur pr\u00e9d\u00e9finie (utilis\u00e9e uniquement quand is_preset=true)"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "field_name",
          "field_label"
        ]
      },
      "TemplateCustomField": {
        "type": "object",
        "description": "Une d\u00e9finition de champ personnalis\u00e9 pour un Mod\u00e8le",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique"
          },
          "field_name": {
            "type": "string",
            "description": "Nom de champ lisible par machine"
          },
          "field_label": {
            "type": "string",
            "description": "Libell\u00e9 d'affichage lisible par un humain"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "field_name"
        ]
      },
      "SigningRequestCustomField": {
        "type": "object",
        "description": "Une d\u00e9finition de champ personnalis\u00e9 pour une Demande de Signature",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique"
          },
          "field_name": {
            "type": "string",
            "description": "Nom de champ lisible par machine"
          },
          "field_label": {
            "type": "string",
            "description": "Libell\u00e9 d'affichage lisible par un humain"
          },
          "copied_from_template": {
            "type": "boolean",
            "description": "True si ce champ a \u00e9t\u00e9 copi\u00e9 depuis un Mod\u00e8le"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "field_name"
        ]
      },
      "Domain": {
        "type": "object",
        "description": "Configuration de domaine email pour l'envoi des emails de Demande de Signature",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique du domaine"
          },
          "domain": {
            "type": "string",
            "description": "Le nom de domaine (par exemple, 'example.com')"
          },
          "verification_status": {
            "type": "integer",
            "enum": [
              0,
              1,
              2
            ],
            "description": "Statut de v\u00e9rification de propri\u00e9t\u00e9 du domaine : 0=en attente, 1=propri\u00e9t\u00e9 v\u00e9rifi\u00e9e (enregistrement TXT confirm\u00e9), 2=finalis\u00e9 (enregistr\u00e9 chez le fournisseur email)"
          },
          "domain_status": {
            "type": "integer",
            "enum": [
              0,
              1
            ],
            "description": "Statut d'envoi d'emails : 0=enregistrements DNS en attente de v\u00e9rification, 1=enti\u00e8rement v\u00e9rifi\u00e9 et pr\u00eat \u00e0 envoyer"
          },
          "is_primary": {
            "type": "boolean",
            "description": "Indique si c'est le domaine principal pour l'envoi d'emails depuis cet Espace de Travail"
          },
          "verification_token": {
            "type": "string",
            "description": "Jeton \u00e0 ajouter comme enregistrement TXT pour la v\u00e9rification de propri\u00e9t\u00e9 du domaine. Retourn\u00e9 uniquement quand verification_status=0."
          },
          "resend_domain_id": {
            "type": "string",
            "nullable": true,
            "description": "ID de domaine du fournisseur email externe (usage interne)"
          },
          "dns_records": {
            "type": "array",
            "nullable": true,
            "description": "Enregistrements DNS requis pour l'envoi d'emails. Retourn\u00e9 uniquement apr\u00e8s la finalisation du domaine (verification_status=2).",
            "items": {
              "$ref": "#/components/schemas/DomainDnsRecord"
            }
          },
          "date_created": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de cr\u00e9ation du domaine"
          },
          "date_changed": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de derni\u00e8re mise \u00e0 jour du domaine"
          }
        },
        "required": [
          "id",
          "domain",
          "domain_status",
          "verification_status"
        ]
      },
      "DomainDnsRecord": {
        "type": "object",
        "description": "Enregistrement DNS requis pour la v\u00e9rification du domaine email",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "TXT",
              "CNAME",
              "MX"
            ],
            "description": "Type d'enregistrement DNS"
          },
          "name": {
            "type": "string",
            "description": "Nom/h\u00f4te de l'enregistrement DNS (par exemple, 'resend._domainkey' ou '@')"
          },
          "value": {
            "type": "string",
            "description": "Valeur de l'enregistrement DNS"
          },
          "ttl": {
            "type": "string",
            "description": "Dur\u00e9e de vie (par exemple, 'Auto' ou en secondes)"
          },
          "priority": {
            "type": "integer",
            "nullable": true,
            "description": "Priorit\u00e9 pour les enregistrements MX"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "verified",
              "failed"
            ],
            "description": "Statut de v\u00e9rification de cet enregistrement sp\u00e9cifique"
          }
        }
      },
      "EmailTemplate": {
        "type": "object",
        "description": "Mod\u00e8le d'email personnalis\u00e9 pour les notifications de Demande de Signature",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifiant unique du mod\u00e8le d'email"
          },
          "email_type": {
            "type": "string",
            "enum": [
              "signing_invite",
              "next_signer",
              "signing_expired",
              "signing_cancelled",
              "signing_declined"
            ],
            "description": "Type d'email pour lequel ce mod\u00e8le est destin\u00e9"
          },
          "subject": {
            "type": "string",
            "description": "Ligne d'objet de l'email"
          },
          "body": {
            "type": "string",
            "description": "Corps de l'email (HTML). Prend en charge des placeholders comme {{signing_link}}, {{signer_name}}, etc."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de cr\u00e9ation du mod\u00e8le"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de derni\u00e8re mise \u00e0 jour du mod\u00e8le"
          }
        },
        "required": [
          "email_type",
          "subject",
          "body"
        ]
      },
      "SignerTerms": {
        "type": "object",
        "properties": {
          "language": {
            "type": "string",
            "enum": [
              "en",
              "es",
              "it",
              "pt",
              "fr",
              "de",
              "el",
              "ru",
              "pl",
              "cs",
              "sv",
              "nl",
              "ro",
              "nb"
            ]
          },
          "statement_text": {
            "type": "string",
            "description": "D\u00e9claration de consentement HTML nettoy\u00e9e"
          },
          "terms_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "Lien externe optionnel vers les conditions"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "language",
          "statement_text"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Message d'erreur lisible par un humain"
          },
          "message": {
            "type": "string",
            "description": "Description d\u00e9taill\u00e9e de l'erreur"
          },
          "details": {
            "type": "object",
            "description": "D\u00e9tails d'erreur suppl\u00e9mentaires",
            "additionalProperties": true
          }
        },
        "required": [
          "error"
        ]
      },
      "SigningRequestDownloadResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "finished",
              "in_progress",
              "cancelled",
              "declined",
              "expired"
            ],
            "description": "Statut de la Demande de Signature. `finished` signifie que tous les Signataires ont termin\u00e9. `in_progress` signifie que la signature est encore en cours et qu'il s'agit d'un t\u00e9l\u00e9chargement partiel. `cancelled`, `declined` et `expired` indiquent des \u00e9tats terminaux o\u00f9 le document est un instantan\u00e9 partiel pris au moment o\u00f9 la signature s'est arr\u00eat\u00e9e."
          },
          "is_partial": {
            "type": "boolean",
            "description": "Indique si cette URL de t\u00e9l\u00e9chargement pointe vers un document partiellement sign\u00e9 (tous les Signataires n'ont pas termin\u00e9)."
          },
          "download_url": {
            "type": "string",
            "format": "uri",
            "description": "URL pr\u00e9-sign\u00e9e pour t\u00e9l\u00e9charger le document PDF. Expire au moment indiqu\u00e9 par `expires_at`."
          },
          "generated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Horodatage ISO 8601 de la derni\u00e8re g\u00e9n\u00e9ration du document. Pour les t\u00e9l\u00e9chargements partiels, c'est le moment o\u00f9 le PDF partiel a \u00e9t\u00e9 cr\u00e9\u00e9."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage ISO 8601 d'expiration de `download_url`. Interrogez \u00e0 nouveau cet endpoint pour obtenir une URL fra\u00eeche apr\u00e8s expiration."
          }
        },
        "required": [
          "status",
          "is_partial",
          "download_url",
          "expires_at"
        ]
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "current_page": {
            "type": "integer"
          },
          "page_size": {
            "type": "integer"
          },
          "total_count": {
            "type": "integer"
          },
          "total_pages": {
            "type": "integer"
          }
        },
        "description": "M\u00e9tadonn\u00e9es de pagination pour les r\u00e9ponses de type liste",
        "required": [
          "current_page",
          "page_size",
          "total_count",
          "total_pages"
        ]
      },
      "WorkspaceListResponse": {
        "type": "object",
        "description": "Liste pagin\u00e9e des espaces de travail",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Workspace"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "results",
          "pagination"
        ]
      },
      "TemplateListResponse": {
        "type": "object",
        "description": "Liste pagin\u00e9e des mod\u00e8les",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Template"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "results",
          "pagination"
        ]
      },
      "SigningRequestListResponse": {
        "type": "object",
        "description": "Liste pagin\u00e9e des demandes de signature",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SigningRequestListItem"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "results",
          "pagination"
        ]
      },
      "WebhookListResponse": {
        "type": "object",
        "description": "Liste pagin\u00e9e des webhooks",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Webhook"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "results",
          "pagination"
        ]
      },
      "MessageResponse": {
        "type": "object",
        "description": "R\u00e9ponse de succ\u00e8s simple avec un message",
        "properties": {
          "message": {
            "type": "string",
            "description": "Message de succ\u00e8s"
          }
        },
        "required": [
          "message"
        ]
      },
      "TemplateUserListResponse": {
        "type": "object",
        "description": "Liste des utilisateurs du mod\u00e8le",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateUser"
            }
          }
        },
        "required": [
          "results"
        ]
      },
      "TemplateFieldListResponse": {
        "type": "object",
        "description": "Liste des champs du mod\u00e8le",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateField"
            }
          }
        },
        "required": [
          "results"
        ]
      },
      "SigningRequestUserListResponse": {
        "type": "object",
        "description": "Liste des utilisateurs de la demande de signature",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SigningRequestUser"
            }
          }
        },
        "required": [
          "results"
        ]
      },
      "SigningRequestFieldListResponse": {
        "type": "object",
        "description": "Liste des champs de la demande de signature",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SigningRequestField"
            }
          }
        },
        "required": [
          "results"
        ]
      },
      "AuditTrailListResponse": {
        "type": "object",
        "description": "Liste des entr\u00e9es de la piste d'audit",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "timestamp": {
                  "type": "string",
                  "format": "date-time"
                },
                "source": {
                  "type": "string",
                  "enum": [
                    "admin",
                    "signer"
                  ],
                  "description": "Indique si l'\u00e9v\u00e9nement a \u00e9t\u00e9 d\u00e9clench\u00e9 par un admin/API ou par un signataire"
                },
                "event": {
                  "type": "string",
                  "description": "Identifiant du type d'\u00e9v\u00e9nement"
                },
                "description": {
                  "type": "string",
                  "description": "Description lisible de l'\u00e9v\u00e9nement"
                },
                "actor": {
                  "type": "object",
                  "nullable": true,
                  "description": "Qui a effectu\u00e9 l'action (nom/email du signataire ou admin/cl\u00e9 API)"
                },
                "ip_address": {
                  "type": "string",
                  "nullable": true,
                  "description": "Adresse IP du signataire (\u00e9v\u00e9nements signataire uniquement)"
                },
                "details": {
                  "type": "object",
                  "nullable": true,
                  "description": "M\u00e9tadonn\u00e9es suppl\u00e9mentaires sp\u00e9cifiques \u00e0 l'\u00e9v\u00e9nement"
                }
              }
            }
          }
        },
        "required": [
          "results"
        ]
      },
      "CompanyEmailTemplateListResponse": {
        "type": "object",
        "description": "Liste des mod\u00e8les d'email de l'entreprise",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailTemplate"
            }
          }
        },
        "required": [
          "results"
        ]
      },
      "DomainListResponse": {
        "type": "object",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Domain"
            }
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de l'espace de travail pour les r\u00e9sultats limit\u00e9s"
          }
        },
        "description": "Liste des domaines avec le contexte de l'espace de travail",
        "required": [
          "results"
        ]
      },
      "DomainCreateResponse": {
        "type": "object",
        "properties": {
          "domain": {
            "$ref": "#/components/schemas/Domain"
          },
          "verification_instructions": {
            "type": "object",
            "properties": {
              "record_type": {
                "type": "string",
                "example": "TXT"
              },
              "record_name": {
                "type": "string",
                "example": "_firma-verification.acme.com"
              },
              "record_value": {
                "type": "string",
                "example": "firma-verify=abc123xyz"
              },
              "next_step": {
                "type": "string",
                "example": "Add this TXT record to your DNS, then call POST /company/domains/{id}/verify-ownership"
              }
            }
          }
        },
        "description": "Domaine cr\u00e9\u00e9 avec les instructions de v\u00e9rification",
        "required": [
          "domain",
          "verification_instructions"
        ]
      },
      "DomainDeleteResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "domain_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "description": "Confirmation de suppression du domaine",
        "required": [
          "message",
          "domain_id"
        ]
      },
      "DomainVerifyOwnershipResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "domain": {
            "$ref": "#/components/schemas/Domain"
          },
          "next_step": {
            "type": "string"
          }
        },
        "description": "R\u00e9sultat de la v\u00e9rification de propri\u00e9t\u00e9 du domaine",
        "required": [
          "message",
          "domain",
          "next_step"
        ]
      },
      "DomainFinalizeResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "domain": {
            "$ref": "#/components/schemas/Domain"
          },
          "dns_records": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DomainDnsRecord"
            },
            "description": "Enregistrements DNS \u00e0 ajouter pour l'envoi d'emails"
          },
          "next_step": {
            "type": "string"
          }
        },
        "description": "Finalisation du domaine avec les enregistrements DNS",
        "required": [
          "message",
          "domain",
          "dns_records",
          "next_step"
        ]
      },
      "DomainVerifyDnsResponse": {
        "type": "object",
        "properties": {
          "verified": {
            "type": "boolean",
            "description": "Indique si tous les enregistrements DNS sont v\u00e9rifi\u00e9s"
          },
          "message": {
            "type": "string"
          },
          "domain": {
            "$ref": "#/components/schemas/Domain"
          },
          "dns_records": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DomainDnsRecord"
            },
            "description": "Statut de chaque enregistrement DNS"
          }
        },
        "description": "R\u00e9sultat de la v\u00e9rification DNS",
        "required": [
          "verified",
          "message",
          "domain"
        ]
      },
      "DomainSetPrimaryResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "domain": {
            "$ref": "#/components/schemas/Domain"
          }
        },
        "description": "Confirmation de la mise \u00e0 jour du domaine principal",
        "required": [
          "message",
          "domain"
        ]
      },
      "RotateSecretResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "new_secret": {
            "type": "string",
            "description": "Le nouveau secret de signature du webhook (cha\u00eene hexad\u00e9cimale de 64 caract\u00e8res)"
          },
          "grace_period_hours": {
            "type": "integer",
            "description": "Nombre d'heures pendant lesquelles l'ancien secret reste valide en parall\u00e8le du nouveau"
          },
          "warning": {
            "type": "string",
            "description": "Rappel de mettre \u00e0 jour la v\u00e9rification de signature du webhook"
          }
        },
        "description": "R\u00e9sultat de la rotation du secret avec p\u00e9riode de gr\u00e2ce",
        "required": [
          "message",
          "new_secret",
          "grace_period_hours"
        ]
      },
      "SecretStatusResponse": {
        "type": "object",
        "properties": {
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date de cr\u00e9ation du secret du webhook",
            "nullable": true
          },
          "last_rotated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date de la derni\u00e8re rotation du secret du webhook",
            "nullable": true
          },
          "grace_period_active": {
            "type": "boolean",
            "description": "Indique si l'ancien secret est encore valide en parall\u00e8le du nouveau"
          },
          "grace_period_ends_at": {
            "type": "string",
            "format": "date-time",
            "description": "Date d'expiration de la p\u00e9riode de gr\u00e2ce de l'ancien secret",
            "nullable": true
          }
        },
        "description": "Statut du secret du webhook et informations de rotation",
        "required": [
          "created_at"
        ]
      },
      "EmailTemplateDeleteResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "email_type": {
            "type": "string"
          }
        },
        "description": "Confirmation de suppression du mod\u00e8le d'email",
        "required": [
          "message",
          "email_type"
        ]
      },
      "SignerTermsListResponse": {
        "type": "object",
        "properties": {
          "terms": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SignerTerms"
            }
          }
        },
        "description": "Liste des conditions signataire par langue",
        "required": [
          "terms"
        ]
      },
      "SignerTermsUpdateResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "storedHtml": {
            "type": "string",
            "description": "Le HTML assaini r\u00e9ellement stock\u00e9"
          },
          "changed": {
            "type": "boolean",
            "description": "Indique si l'assainissement a modifi\u00e9 la d\u00e9claration soumise"
          }
        },
        "description": "R\u00e9sultat de la mise \u00e0 jour des conditions signataire",
        "required": [
          "ok"
        ]
      },
      "SignerTermsDeleteResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "language": {
            "type": "string"
          }
        },
        "description": "Confirmation de suppression des conditions signataire",
        "required": [
          "message",
          "language"
        ]
      },
      "CustomFieldListResponse": {
        "type": "object",
        "properties": {
          "custom_fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkspaceCustomField"
            }
          }
        },
        "description": "Liste des champs personnalis\u00e9s",
        "required": [
          "custom_fields"
        ]
      },
      "LogoUploadResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "icon_url": {
            "type": "string",
            "format": "uri",
            "description": "URL publique du logo t\u00e9l\u00e9vers\u00e9"
          }
        },
        "description": "Confirmation de t\u00e9l\u00e9versement du logo avec URL",
        "required": [
          "success",
          "icon_url"
        ]
      },
      "LogoDeleteResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          }
        },
        "description": "Confirmation de suppression du logo",
        "required": [
          "success"
        ]
      },
      "ApiKeyRegenerateResponse": {
        "type": "object",
        "properties": {
          "new_key": {
            "type": "object",
            "description": "La cl\u00e9 API nouvellement g\u00e9n\u00e9r\u00e9e",
            "properties": {
              "api_key": {
                "type": "string",
                "description": "La valeur de la nouvelle cl\u00e9 API"
              },
              "created_at": {
                "type": "string",
                "format": "date-time",
                "description": "Date de cr\u00e9ation de la cl\u00e9"
              }
            }
          },
          "key_type": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ],
            "description": "Le type de cl\u00e9 qui a \u00e9t\u00e9 r\u00e9g\u00e9n\u00e9r\u00e9"
          },
          "expiring_keys": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "api_key": {
                  "type": "string",
                  "description": "La valeur de la cl\u00e9 API arrivant \u00e0 expiration"
                },
                "expires_at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "description": "Liste des cl\u00e9s qui ont \u00e9t\u00e9 configur\u00e9es pour expirer dans 24 heures"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "description": "R\u00e9sultat de la r\u00e9g\u00e9n\u00e9ration de la cl\u00e9 API",
        "required": [
          "new_key",
          "key_type",
          "workspace_id"
        ]
      },
      "ApiKeyExpireResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Indique si l'op\u00e9ration a r\u00e9ussi"
          },
          "expired_keys": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "api_key": {
                  "type": "string",
                  "description": "La valeur de la cl\u00e9 API expir\u00e9e"
                },
                "original_expires_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Date d'expiration initialement pr\u00e9vue pour la cl\u00e9"
                },
                "expired_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Date \u00e0 laquelle la cl\u00e9 a r\u00e9ellement expir\u00e9"
                }
              }
            },
            "description": "Liste des cl\u00e9s expir\u00e9es avec d\u00e9tails"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "message": {
            "type": "string",
            "description": "Message optionnel lorsqu'aucune cl\u00e9 en attente n'existe"
          }
        },
        "description": "R\u00e9sultat de l'expiration de la cl\u00e9 API",
        "required": [
          "success",
          "workspace_id"
        ]
      },
      "TemplatePatchResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "updated_fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Retourn\u00e9 lors de la mise \u00e0 jour des propri\u00e9t\u00e9s"
          },
          "user": {
            "type": "object",
            "description": "Retourn\u00e9 lors de la mise \u00e0 jour/cr\u00e9ation d'un utilisateur"
          }
        },
        "description": "R\u00e9sultat de la mise \u00e0 jour partielle du mod\u00e8le",
        "required": [
          "message",
          "updated_fields"
        ]
      },
      "TemplateDuplicateResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de la nouvelle demande de signature cr\u00e9\u00e9e"
          },
          "name": {
            "type": "string",
            "description": "Nom de la nouvelle demande de signature"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Description de la nouvelle demande de signature"
          },
          "status": {
            "type": "string",
            "description": "Statut de la nouvelle demande de signature",
            "example": "draft"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid",
            "description": "Espace de travail auquel appartient la demande de signature"
          },
          "created_date": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage de cr\u00e9ation"
          }
        },
        "description": "D\u00e9tails du mod\u00e8le dupliqu\u00e9",
        "required": [
          "id",
          "name",
          "status",
          "workspace_id"
        ]
      },
      "CreateAndSendResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de la demande de signature"
          },
          "name": {
            "type": "string",
            "description": "Nom de la demande de signature"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Description de la demande de signature"
          },
          "status": {
            "type": "string",
            "enum": [
              "sent"
            ],
            "description": "Toujours 'sent' pour ce endpoint"
          },
          "document_url": {
            "type": "string",
            "format": "uri",
            "description": "URL sign\u00e9e pour acc\u00e9der au document"
          },
          "page_count": {
            "type": "integer",
            "description": "Nombre de pages du document"
          },
          "expiration_hours": {
            "type": "integer",
            "description": "Nombre d'heures avant expiration"
          },
          "settings": {
            "$ref": "#/components/schemas/SigningRequestSettings"
          },
          "created_date": {
            "type": "string",
            "format": "date-time"
          },
          "sent_date": {
            "type": "string",
            "format": "date-time",
            "description": "Date d'envoi de la demande"
          },
          "template_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "first_signer": {
            "type": "object",
            "description": "D\u00e9tails du premier signataire ayant re\u00e7u l'email",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "name": {
                "type": "string"
              },
              "email": {
                "type": "string",
                "format": "email"
              },
              "signing_link": {
                "type": "string",
                "format": "uri",
                "description": "Lien direct pour que le signataire acc\u00e8de \u00e0 la vue de signature"
              }
            }
          },
          "recipients": {
            "type": "array",
            "description": "Tous les destinataires avec leurs v\u00e9ritables UUID",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "first_name": {
                  "type": "string"
                },
                "last_name": {
                  "type": "string",
                  "nullable": true
                },
                "name": {
                  "type": "string"
                },
                "email": {
                  "type": "string",
                  "format": "email"
                },
                "designation": {
                  "type": "string"
                },
                "order": {
                  "type": "integer"
                }
              }
            }
          },
          "fields": {
            "type": "array",
            "description": "Tous les champs avec les v\u00e9ritables UUID de destinataire",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          },
          "credits_remaining": {
            "type": "integer",
            "description": "Cr\u00e9dits restants pour l'entreprise apr\u00e8s d\u00e9duction"
          }
        },
        "description": "Demande de signature cr\u00e9\u00e9e et envoy\u00e9e",
        "required": [
          "id",
          "name",
          "status"
        ]
      },
      "CreateAndSendValidationError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "description": "Code d'erreur exploitable par une machine",
            "example": "VALIDATION_ERROR"
          },
          "phase": {
            "type": "string",
            "enum": [
              "create_validation",
              "send_validation"
            ],
            "description": "Quelle phase de validation a \u00e9chou\u00e9"
          },
          "validation_errors": {
            "type": "array",
            "description": "Erreurs de validation d\u00e9taill\u00e9es pour la phase d'envoi",
            "items": {
              "type": "object",
              "properties": {
                "recipient_index": {
                  "type": "integer",
                  "description": "Index du destinataire (base 1)"
                },
                "recipient_email": {
                  "type": "string"
                },
                "missing_fields": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Liste des champs requis manquants"
                }
              }
            }
          }
        },
        "description": "Erreur de validation lors du create-and-send",
        "required": [
          "error",
          "code"
        ]
      },
      "InsufficientCreditsError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "example": "Insufficient credits. Please purchase more credits to send signing requests."
          },
          "code": {
            "type": "string",
            "example": "INSUFFICIENT_CREDITS"
          },
          "current_credits": {
            "type": "integer",
            "example": 0
          }
        },
        "description": "Erreur de cr\u00e9dits insuffisants",
        "required": [
          "error",
          "code",
          "current_credits"
        ]
      },
      "UnprocessableEntityError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "example": "A recipient's email address cannot receive messages."
          },
          "code": {
            "type": "string",
            "example": "RECIPIENT_EMAIL_SUPPRESSED"
          }
        },
        "description": "Erreur d'entit\u00e9 non traitable",
        "required": [
          "error",
          "code"
        ]
      },
      "SigningRequestUpdateResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de la demande de signature (pour compatibilit\u00e9 ascendante)"
          },
          "name": {
            "type": "string",
            "description": "Nom de la demande de signature (pour compatibilit\u00e9 ascendante)"
          },
          "signing_request": {
            "type": "object",
            "description": "R\u00e9sum\u00e9 de la demande de signature mise \u00e0 jour (sous-ensemble du sch\u00e9ma complet SigningRequest)",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "ID de la demande de signature"
              },
              "name": {
                "type": "string",
                "description": "Nom de la demande de signature"
              },
              "description": {
                "type": "string",
                "nullable": true,
                "description": "Description de la demande de signature (mapp\u00e9e depuis template_description)"
              },
              "document_url": {
                "type": "string",
                "format": "uri",
                "description": "URL pr\u00e9-sign\u00e9e vers le document PDF"
              },
              "document_url_expires_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Quand l'URL du document expire"
              },
              "document_page_count": {
                "type": "integer",
                "description": "Nombre de pages dans le document"
              },
              "status": {
                "type": "string",
                "description": "Statut actuel de la demande de signature"
              },
              "expiration_hours": {
                "type": "integer",
                "description": "Heures avant l'expiration de la demande de signature"
              },
              "settings": {
                "type": "object",
                "description": "Sous-ensemble des param\u00e8tres de la demande de signature renvoy\u00e9 dans la r\u00e9ponse PUT",
                "properties": {
                  "allow_download": {
                    "type": "boolean",
                    "description": "Indique si les destinataires peuvent t\u00e9l\u00e9charger le document"
                  },
                  "attach_pdf_on_finish": {
                    "type": "boolean",
                    "description": "Indique si le PDF doit \u00eatre joint \u00e0 la fin"
                  },
                  "hand_drawn_only": {
                    "type": "boolean",
                    "description": "Indique si seules les signatures manuscrites sont autoris\u00e9es"
                  }
                }
              },
              "template_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "ID du mod\u00e8le si cr\u00e9\u00e9 \u00e0 partir d'un mod\u00e8le"
              },
              "expires_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Horodatage ISO 8601 de l'expiration de la demande de signature"
              },
              "created_date": {
                "type": "string",
                "format": "date-time",
                "description": "Horodatage de cr\u00e9ation"
              },
              "sent_date": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Quand la demande de signature a \u00e9t\u00e9 envoy\u00e9e"
              },
              "finished_date": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Quand toutes les signatures ont \u00e9t\u00e9 compl\u00e9t\u00e9es"
              },
              "cancelled_date": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Quand la demande de signature a \u00e9t\u00e9 annul\u00e9e"
              }
            }
          },
          "recipients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Recipient"
            },
            "description": "Liste mise \u00e0 jour des destinataires"
          },
          "reminders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Reminder"
            },
            "description": "Liste mise \u00e0 jour des rappels"
          },
          "summary": {
            "type": "object",
            "description": "R\u00e9sum\u00e9 de tous les changements effectu\u00e9s dans cette mise \u00e0 jour",
            "properties": {
              "properties_updated": {
                "type": "boolean",
                "description": "Indique si des propri\u00e9t\u00e9s ont \u00e9t\u00e9 mises \u00e0 jour"
              },
              "recipients_created": {
                "type": "integer",
                "description": "Nombre de nouveaux destinataires cr\u00e9\u00e9s"
              },
              "recipients_updated": {
                "type": "integer",
                "description": "Nombre de destinataires existants mis \u00e0 jour"
              },
              "recipients_deleted": {
                "type": "integer",
                "description": "Nombre de destinataires supprim\u00e9s en soft-delete"
              },
              "fields_created": {
                "type": "integer",
                "description": "Nombre de nouveaux champs cr\u00e9\u00e9s"
              },
              "fields_updated": {
                "type": "integer",
                "description": "Nombre de champs existants mis \u00e0 jour"
              },
              "fields_reassigned": {
                "type": "integer",
                "description": "Nombre de champs r\u00e9assign\u00e9s \u00e0 un autre destinataire"
              },
              "fields_deleted": {
                "type": "integer",
                "description": "Nombre de champs supprim\u00e9s en soft-delete"
              },
              "reminders_created": {
                "type": "integer",
                "description": "Nombre de nouveaux rappels cr\u00e9\u00e9s"
              },
              "reminders_updated": {
                "type": "integer",
                "description": "Nombre de rappels existants mis \u00e0 jour"
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Avertissements de format d'email pour les destinataires (non bloquants)"
              }
            }
          }
        },
        "description": "R\u00e9sultat de la mise \u00e0 jour de la demande de signature",
        "required": [
          "id",
          "name"
        ]
      },
      "SigningRequestUpdateError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "details": {
            "type": "object",
            "properties": {
              "signing_request_properties": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "recipients": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "deleted_recipients": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "fields": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "reminders": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Erreur de validation lors de la mise \u00e0 jour de la demande de signature",
        "required": [
          "error"
        ]
      },
      "SigningRequestDeleteResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "signing_request_id": {
            "type": "string",
            "format": "uuid"
          },
          "deleted_on": {
            "type": "string",
            "format": "date-time"
          }
        },
        "description": "Confirmation de suppression de la demande de signature",
        "required": [
          "message",
          "signing_request_id"
        ]
      },
      "CancelSigningRequestResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "signing_request_id": {
            "type": "string",
            "format": "uuid"
          },
          "cancelled_on": {
            "type": "string",
            "format": "date-time"
          },
          "notify_signers": {
            "type": "boolean"
          },
          "emails_sent": {
            "type": "integer",
            "description": "Nombre d'emails de notification d'annulation envoy\u00e9s aux signataires"
          }
        },
        "description": "R\u00e9sultat de l'annulation de la demande de signature",
        "required": [
          "message",
          "signing_request_id",
          "cancelled_on"
        ]
      },
      "ResendSigningRequestResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "signing_request_id": {
            "type": "string",
            "format": "uuid"
          },
          "recipients_notified": {
            "type": "integer"
          },
          "recipients_failed": {
            "type": "integer",
            "description": "Nombre de destinataires dont la notification de renvoi a \u00e9chou\u00e9"
          },
          "recipients": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "email": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "R\u00e9sultat du renvoi de la demande de signature",
        "required": [
          "message",
          "signing_request_id"
        ]
      },
      "ResendConflictError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "details": {
            "type": "object",
            "properties": {
              "current_order": {
                "type": "integer"
              },
              "invalid_recipients": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "email": {
                      "type": "string"
                    },
                    "order": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        },
        "description": "Erreur de conflit de renvoi",
        "required": [
          "error",
          "code"
        ]
      },
      "TestWebhookResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Indique si le webhook de test a \u00e9t\u00e9 livr\u00e9 avec succ\u00e8s"
          },
          "status_code": {
            "type": "integer",
            "description": "Code de statut HTTP renvoy\u00e9 par le endpoint du webhook"
          },
          "webhook_event_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de l'enregistrement de l'\u00e9v\u00e9nement webhook"
          },
          "message": {
            "type": "string"
          },
          "headers_sent": {
            "type": "object",
            "description": "En-t\u00eates envoy\u00e9s avec la requ\u00eate de webhook de test",
            "properties": {
              "X-Firma-Event": {
                "type": "string"
              },
              "X-Firma-Signature": {
                "type": "string"
              },
              "X-Firma-Delivery": {
                "type": "string"
              },
              "X-Firma-Signature-Old": {
                "type": "string",
                "description": "Pr\u00e9sent uniquement pendant la p\u00e9riode de gr\u00e2ce apr\u00e8s la rotation du secret"
              }
            }
          }
        },
        "description": "R\u00e9sultat de l'ex\u00e9cution du test webhook",
        "required": [
          "success",
          "status_code"
        ]
      },
      "GenerateTemplateTokenResponse": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "Le token JWT"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Horodatage d'expiration du token"
          },
          "jwt_record_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de l'enregistrement en base de donn\u00e9es pour le JWT"
          }
        },
        "description": "Token JWT g\u00e9n\u00e9r\u00e9 pour le mod\u00e8le",
        "required": [
          "token",
          "expires_at"
        ]
      },
      "EmailTemplateDefaultsResponse": {
        "type": "object",
        "properties": {
          "language": {
            "type": "string"
          },
          "templates": {
            "type": "object",
            "description": "Correspondance entre email_type et le mod\u00e8le par d\u00e9faut {subject, body}",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "subject": {
                  "type": "string"
                },
                "body": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Mod\u00e8les d'email par d\u00e9faut pour une langue",
        "required": [
          "language",
          "templates"
        ]
      },
      "EmailTemplatePlaceholdersResponse": {
        "type": "object",
        "properties": {
          "placeholders": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string",
                  "description": "Cl\u00e9 du placeholder (par ex. 'signing_link')"
                },
                "description": {
                  "type": "string",
                  "description": "Ce vers quoi ce placeholder se r\u00e9sout"
                }
              }
            }
          }
        },
        "description": "Placeholders de mod\u00e8les d'email disponibles",
        "required": [
          "placeholders"
        ]
      },
      "WorkspaceEmailTemplateListResponse": {
        "type": "object",
        "description": "Liste des mod\u00e8les d'email de l'espace de travail",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailTemplate"
            }
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID de l'espace de travail"
          }
        },
        "required": [
          "results",
          "workspace_id"
        ]
      },
      "TemplateCopyResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the newly created template copy"
          },
          "name": {
            "type": "string",
            "description": "Name of the copied template"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid",
            "description": "Target workspace the template was copied to"
          },
          "created_date": {
            "type": "string",
            "format": "date-time",
            "description": "Creation timestamp"
          }
        },
        "description": "Template copy response",
        "required": [
          "id",
          "name",
          "workspace_id",
          "created_date"
        ]
      }
    }
  },
  "paths": {
    "/company": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer les informations de l'entreprise",
        "description": "R\u00e9cup\u00e8re les informations sur l'entreprise authentifi\u00e9e",
        "tags": [
          "Company"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Informations de l'entreprise r\u00e9cup\u00e9r\u00e9es avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Horodatage Unix de la r\u00e9initialisation de la limite de d\u00e9bit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Company"
                },
                "example": {
                  "id": "123e4567-e89b-12d3-a456-426614174000",
                  "name": "Acme Corporation",
                  "language": "en",
                  "account_owner": "John Doe",
                  "account_owner_email": "john@acme.com",
                  "website": "https://acme.com",
                  "icon_url": "https://acme.com/logo.png",
                  "credits": 1000,
                  "created_date": "2024-01-15T10:30:00Z",
                  "updated_date": "2024-03-20T14:25:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "getCompany",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.company.getCompany();\nconsole.log(response);"
          }
        ]
      },
      "put": {
        "summary": "Mettre \u00e0 jour les informations de l'entreprise",
        "description": "Met \u00e0 jour tous les d\u00e9tails de l'entreprise. Il s'agit d'un remplacement complet n\u00e9cessitant tous les champs sauf icon_url.",
        "tags": [
          "Company"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "account_owner",
                  "account_owner_email",
                  "website"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom de l'entreprise"
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "es",
                      "it",
                      "pt",
                      "fr",
                      "de",
                      "el",
                      "ru",
                      "pl",
                      "cs",
                      "sv",
                      "nl",
                      "ro",
                      "nb"
                    ],
                    "description": "Langue par d\u00e9faut de l'entreprise"
                  },
                  "account_owner": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom du titulaire du compte"
                  },
                  "account_owner_email": {
                    "type": "string",
                    "format": "email",
                    "description": "Adresse email du titulaire du compte"
                  },
                  "website": {
                    "type": "string",
                    "format": "uri",
                    "description": "URL du site web de l'entreprise"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "name": "Acme Corporation Ltd",
                "account_owner": "Jane Smith",
                "account_owner_email": "jane@acme.com",
                "website": "https://www.acme.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Entreprise mise \u00e0 jour avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Horodatage Unix de la r\u00e9initialisation de la limite de d\u00e9bit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Company"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "protectedFields": {
                    "summary": "Tentative de modification de champs prot\u00e9g\u00e9s",
                    "value": {
                      "error": "The following fields cannot be modified: credits",
                      "code": "VALIDATION_ERROR"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "updateCompany",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.company.updateCompany({\n    name: \"Acme Corporation Ltd\",\n    account_owner: \"Jane Smith\",\n    account_owner_email: \"jane@acme.com\",\n    website: \"https://www.acme.com\"\n});\nconsole.log(response);"
          }
        ]
      },
      "patch": {
        "summary": "Mettre \u00e0 jour partiellement les informations de l'entreprise",
        "description": "Met \u00e0 jour des champs sp\u00e9cifiques de l'entreprise. Seuls les champs fournis seront mis \u00e0 jour. Au moins un champ doit \u00eatre fourni.",
        "tags": [
          "Company"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom de l'entreprise"
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "es",
                      "it",
                      "pt",
                      "fr",
                      "de",
                      "el",
                      "ru",
                      "pl",
                      "cs",
                      "sv",
                      "nl",
                      "ro",
                      "nb"
                    ],
                    "description": "Langue par d\u00e9faut de l'entreprise"
                  },
                  "account_owner": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom du titulaire du compte"
                  },
                  "account_owner_email": {
                    "type": "string",
                    "format": "email",
                    "description": "Adresse email du titulaire du compte"
                  },
                  "website": {
                    "type": "string",
                    "format": "uri",
                    "description": "URL du site web de l'entreprise"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "name": "Acme Corporation Ltd",
                "website": "https://www.acme.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Entreprise mise \u00e0 jour avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Horodatage Unix de la r\u00e9initialisation de la limite de d\u00e9bit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Company"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "protectedFields": {
                    "summary": "Tentative de modification de champs prot\u00e9g\u00e9s",
                    "value": {
                      "error": "The following fields cannot be modified: credits",
                      "code": "VALIDATION_ERROR"
                    }
                  },
                  "noFields": {
                    "summary": "Aucun champ fourni",
                    "value": {
                      "error": "Validation failed",
                      "details": [
                        {
                          "path": [
                            "body"
                          ],
                          "message": "No fields provided to update"
                        }
                      ]
                    }
                  },
                  "invalidEmail": {
                    "summary": "Email invalide",
                    "value": {
                      "error": "Validation failed",
                      "details": [
                        {
                          "path": [
                            "account_owner_email"
                          ],
                          "message": "Invalid email address"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "patchCompany",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.company.patchCompany({\n    name: \"Acme Corporation Ltd\",\n    website: \"https://www.acme.com\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/company/settings": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer les param\u00e8tres de l'entreprise",
        "description": "R\u00e9cup\u00e8re les param\u00e8tres de l'entreprise authentifi\u00e9e",
        "tags": [
          "Company"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Param\u00e8tres de l'entreprise r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanySettings"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "getCompanySettings",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.company.getCompanySettings();\nconsole.log(response);"
          }
        ]
      },
      "put": {
        "summary": "Mettre \u00e0 jour les param\u00e8tres de l'entreprise",
        "description": "Met \u00e0 jour les param\u00e8tres de l'entreprise. Seuls les champs fournis seront mis \u00e0 jour.",
        "tags": [
          "Company"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "default_expiration_hours": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Expiration par d\u00e9faut de la demande de signature en heures"
                  },
                  "require_terms_acceptance": {
                    "type": "boolean",
                    "description": "Indique si les signataires doivent accepter les conditions avant de signer"
                  },
                  "show_custom_branding_only": {
                    "type": "boolean"
                  },
                  "require_otp_verification": {
                    "type": "boolean"
                  },
                  "allow_presigning_download": {
                    "type": "boolean"
                  },
                  "disable_guided_navigation": {
                    "type": "boolean"
                  },
                  "show_signature_frame": {
                    "type": "boolean"
                  },
                  "show_partial_watermark": {
                    "type": "boolean"
                  },
                  "email_local_part": {
                    "type": "string"
                  },
                  "color_primary": {
                    "type": "string",
                    "nullable": true,
                    "pattern": "^#[0-9A-Fa-f]{6}$"
                  },
                  "color_primary_fg": {
                    "type": "string",
                    "nullable": true,
                    "pattern": "^#[0-9A-Fa-f]{6}$"
                  },
                  "color_background": {
                    "type": "string",
                    "nullable": true,
                    "pattern": "^#[0-9A-Fa-f]{6}$"
                  },
                  "color_foreground": {
                    "type": "string",
                    "nullable": true,
                    "pattern": "^#[0-9A-Fa-f]{6}$"
                  },
                  "color_card": {
                    "type": "string",
                    "nullable": true,
                    "pattern": "^#[0-9A-Fa-f]{6}$"
                  },
                  "color_border": {
                    "type": "string",
                    "nullable": true,
                    "pattern": "^#[0-9A-Fa-f]{6}$"
                  },
                  "color_accent": {
                    "type": "string",
                    "nullable": true,
                    "pattern": "^#[0-9A-Fa-f]{6}$"
                  },
                  "color_accent_fg": {
                    "type": "string",
                    "nullable": true,
                    "pattern": "^#[0-9A-Fa-f]{6}$"
                  },
                  "color_canvas": {
                    "type": "string",
                    "nullable": true,
                    "pattern": "^#[0-9A-Fa-f]{6}$"
                  },
                  "color_muted": {
                    "type": "string",
                    "nullable": true,
                    "pattern": "^#[0-9A-Fa-f]{6}$"
                  },
                  "color_muted_fg": {
                    "type": "string",
                    "nullable": true,
                    "pattern": "^#[0-9A-Fa-f]{6}$"
                  },
                  "show_qr_code": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Afficher un QR code sur la page de signature qui permet aux signataires de continuer sur leur t\u00e9l\u00e9phone. C'est le param\u00e8tre par d\u00e9faut au niveau de l'entreprise ; les espaces de travail, mod\u00e8les et demandes de signature peuvent le remplacer."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Param\u00e8tres de l'entreprise mis \u00e0 jour avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanySettings"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "updateCompanySettings",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.company.updateCompanySettings();\nconsole.log(response);"
          }
        ]
      }
    },
    "/company/domains": {
      "get": {
        "summary": "Lister les domaines de l'entreprise",
        "description": "Lister tous les domaines email configur\u00e9s pour l'entreprise (domaines sur l'espace de travail prot\u00e9g\u00e9/par d\u00e9faut). Ces domaines sont utilis\u00e9s comme domaine d'envoi par d\u00e9faut pour tous les espaces de travail.",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Domaines de l'entreprise r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainListResponse"
                },
                "example": {
                  "results": [
                    {
                      "id": "123e4567-e89b-12d3-a456-426614174000",
                      "domain": "acme.com",
                      "verification_status": 2,
                      "domain_status": 1,
                      "is_primary": true,
                      "date_created": "2024-01-15T10:30:00Z",
                      "date_changed": "2024-01-16T14:00:00Z"
                    }
                  ],
                  "workspace_id": "456e4567-e89b-12d3-a456-426614174000"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listCompanyDomains",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.listCompanyDomains();\nconsole.log(response);"
          }
        ]
      },
      "post": {
        "summary": "Ajouter un domaine d'entreprise",
        "description": "Ajouter un nouveau domaine email pour l'entreprise. Ceci initie le processus de v\u00e9rification du domaine. Apr\u00e8s la cr\u00e9ation, vous devez :\n1. Ajouter un enregistrement TXT \u00e0 votre DNS avec le jeton de v\u00e9rification\n2. Appeler POST /company/domains/{id}/verify-ownership pour v\u00e9rifier la propri\u00e9t\u00e9 du domaine\n3. Appeler POST /company/domains/{id}/finalize pour vous enregistrer aupr\u00e8s du fournisseur d'email\n4. Ajouter les enregistrements DNS retourn\u00e9s (SPF, DKIM, etc.)\n5. Appeler POST /company/domains/{id}/verify-dns pour terminer la v\u00e9rification",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "domain"
                ],
                "properties": {
                  "domain": {
                    "type": "string",
                    "description": "Nom de domaine \u00e0 ajouter (par ex., 'example.com'). Doit \u00eatre un format de domaine valide.",
                    "example": "acme.com"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Domaine cr\u00e9\u00e9 avec succ\u00e8s. Ajoutez l'enregistrement TXT de v\u00e9rification \u00e0 votre DNS.",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainCreateResponse"
                },
                "example": {
                  "domain": {
                    "id": "123e4567-e89b-12d3-a456-426614174000",
                    "domain": "acme.com",
                    "verification_status": 0,
                    "domain_status": 0,
                    "is_primary": false,
                    "verification_token": "firma-verify=abc123xyz",
                    "date_created": "2024-01-15T10:30:00Z",
                    "date_changed": "2024-01-15T10:30:00Z"
                  },
                  "verification_instructions": {
                    "record_type": "TXT",
                    "record_name": "_firma-verification.acme.com",
                    "record_value": "firma-verify=abc123xyz",
                    "next_step": "Add this TXT record to your DNS, then call POST /company/domains/{id}/verify-ownership"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Format de domaine invalide ou le domaine existe d\u00e9j\u00e0",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalidDomain": {
                    "value": {
                      "error": "Invalid domain format",
                      "message": "Please provide a valid domain name (e.g., example.com)"
                    }
                  },
                  "domainExists": {
                    "value": {
                      "error": "Domain already exists",
                      "message": "This domain is already configured for your company"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "createCompanyDomain",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.createCompanyDomain({\n    domain: \"acme.com\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/company/domains/{id}": {
      "get": {
        "summary": "Obtenir un domaine d'entreprise",
        "description": "R\u00e9cup\u00e9rer les d\u00e9tails d'un domaine d'entreprise sp\u00e9cifique, y compris le statut de v\u00e9rification et les enregistrements DNS",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du domaine"
          }
        ],
        "responses": {
          "200": {
            "description": "Domaine r\u00e9cup\u00e9r\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Domain"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "getCompanyDomain",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.getCompanyDomain({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer un domaine d'entreprise",
        "description": "Retirer un domaine de l'entreprise. Si le domaine est le domaine principal ou le seul domaine, l'envoi revient \u00e0 l'entreprise ou \u00e0 l'exp\u00e9diteur par d\u00e9faut.",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du domaine"
          }
        ],
        "responses": {
          "200": {
            "description": "Domaine supprim\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainDeleteResponse"
                },
                "example": {
                  "message": "Domain deleted successfully",
                  "domain_id": "123e4567-e89b-12d3-a456-426614174000"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "deleteCompanyDomain",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.deleteCompanyDomain({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/company/domains/{id}/verify-ownership": {
      "post": {
        "summary": "V\u00e9rifier la propri\u00e9t\u00e9 du domaine",
        "description": "V\u00e9rifier la propri\u00e9t\u00e9 du domaine en contr\u00f4lant l'enregistrement TXT. Appelez ceci apr\u00e8s avoir ajout\u00e9 l'enregistrement TXT de v\u00e9rification \u00e0 votre DNS. La propagation DNS peut prendre jusqu'\u00e0 48 heures, mais se termine g\u00e9n\u00e9ralement en quelques minutes.",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du domaine"
          }
        ],
        "responses": {
          "200": {
            "description": "Propri\u00e9t\u00e9 du domaine v\u00e9rifi\u00e9e avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainVerifyOwnershipResponse"
                },
                "example": {
                  "message": "Domain ownership verified",
                  "domain": {
                    "id": "123e4567-e89b-12d3-a456-426614174000",
                    "domain": "acme.com",
                    "verification_status": 1,
                    "domain_status": 0
                  },
                  "next_step": "Call POST /company/domains/{id}/finalize to complete domain setup and receive DNS records for email sending"
                }
              }
            }
          },
          "400": {
            "description": "\u00c9chec de la v\u00e9rification",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "recordNotFound": {
                    "value": {
                      "error": "Verification failed",
                      "message": "TXT record not found. Please ensure the record is added correctly and DNS has propagated.",
                      "details": {
                        "expected_record": "_firma-verification.acme.com",
                        "expected_value": "firma-verify=abc123xyz"
                      }
                    }
                  },
                  "alreadyVerified": {
                    "value": {
                      "error": "Already verified",
                      "message": "Domain ownership has already been verified"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "verifyCompanyDomainOwnership",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.verifyCompanyDomainOwnership({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/company/domains/{id}/finalize": {
      "post": {
        "summary": "Finaliser la configuration du domaine",
        "description": "Finaliser la configuration du domaine en l'enregistrant aupr\u00e8s du fournisseur d'email. Ceci retourne les enregistrements DNS (SPF, DKIM, DMARC) qui doivent \u00eatre ajout\u00e9s pour activer l'envoi d'emails. Ne peut \u00eatre appel\u00e9 qu'apr\u00e8s v\u00e9rification de la propri\u00e9t\u00e9 du domaine.",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du domaine"
          }
        ],
        "responses": {
          "200": {
            "description": "Domaine finalis\u00e9 avec succ\u00e8s. Ajoutez les enregistrements DNS retourn\u00e9s.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainFinalizeResponse"
                },
                "example": {
                  "message": "Domain finalized. Add the following DNS records to enable email sending.",
                  "domain": {
                    "id": "123e4567-e89b-12d3-a456-426614174000",
                    "domain": "acme.com",
                    "verification_status": 2,
                    "domain_status": 0
                  },
                  "dns_records": [
                    {
                      "type": "TXT",
                      "name": "@",
                      "value": "v=spf1 include:amazonses.com ~all",
                      "ttl": "Auto",
                      "status": "pending"
                    },
                    {
                      "type": "CNAME",
                      "name": "resend._domainkey",
                      "value": "resend._domainkey.amazonses.com",
                      "ttl": "Auto",
                      "status": "pending"
                    },
                    {
                      "type": "TXT",
                      "name": "_dmarc",
                      "value": "v=DMARC1; p=none;",
                      "ttl": "Auto",
                      "status": "pending"
                    }
                  ],
                  "next_step": "Add these DNS records, then call POST /company/domains/{id}/verify-dns to complete verification"
                }
              }
            }
          },
          "400": {
            "description": "Impossible de finaliser",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "notVerified": {
                    "value": {
                      "error": "Ownership not verified",
                      "message": "Please verify domain ownership first by calling POST /company/domains/{id}/verify-ownership"
                    }
                  },
                  "alreadyFinalized": {
                    "value": {
                      "error": "Already finalized",
                      "message": "Domain has already been finalized"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "finalizeCompanyDomain",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.finalizeCompanyDomain({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/company/domains/{id}/verify-dns": {
      "post": {
        "summary": "V\u00e9rifier les enregistrements DNS",
        "description": "V\u00e9rifier que tous les enregistrements DNS requis (SPF, DKIM, DMARC) sont correctement configur\u00e9s. Appelez ceci apr\u00e8s avoir ajout\u00e9 tous les enregistrements DNS de l'\u00e9tape de finalisation. Une fois v\u00e9rifi\u00e9, le domaine est pr\u00eat \u00e0 envoyer des emails.",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du domaine"
          }
        ],
        "responses": {
          "200": {
            "description": "R\u00e9sultat de la v\u00e9rification DNS",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainVerifyDnsResponse"
                },
                "examples": {
                  "verified": {
                    "summary": "Tous les enregistrements v\u00e9rifi\u00e9s",
                    "value": {
                      "verified": true,
                      "message": "Domain is fully verified and ready to send emails",
                      "domain": {
                        "id": "123e4567-e89b-12d3-a456-426614174000",
                        "domain": "acme.com",
                        "verification_status": 2,
                        "domain_status": 1,
                        "is_primary": true
                      },
                      "dns_records": [
                        {
                          "type": "TXT",
                          "name": "@",
                          "value": "v=spf1 include:amazonses.com ~all",
                          "status": "verified"
                        },
                        {
                          "type": "CNAME",
                          "name": "resend._domainkey",
                          "value": "resend._domainkey.amazonses.com",
                          "status": "verified"
                        },
                        {
                          "type": "TXT",
                          "name": "_dmarc",
                          "value": "v=DMARC1; p=none;",
                          "status": "verified"
                        }
                      ]
                    }
                  },
                  "pending": {
                    "summary": "Certains enregistrements en attente",
                    "value": {
                      "verified": false,
                      "message": "Some DNS records are not yet verified. Please check your DNS configuration.",
                      "domain": {
                        "id": "123e4567-e89b-12d3-a456-426614174000",
                        "domain": "acme.com",
                        "verification_status": 2,
                        "domain_status": 0
                      },
                      "dns_records": [
                        {
                          "type": "TXT",
                          "name": "@",
                          "value": "v=spf1 include:amazonses.com ~all",
                          "status": "verified"
                        },
                        {
                          "type": "CNAME",
                          "name": "resend._domainkey",
                          "value": "resend._domainkey.amazonses.com",
                          "status": "pending"
                        },
                        {
                          "type": "TXT",
                          "name": "_dmarc",
                          "value": "v=DMARC1; p=none;",
                          "status": "pending"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Domaine non finalis\u00e9",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Domain not finalized",
                  "message": "Please finalize domain setup first by calling POST /company/domains/{id}/finalize"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "verifyCompanyDomainDns",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.verifyCompanyDomainDns({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/company/domains/{id}/set-primary": {
      "post": {
        "summary": "D\u00e9finir le domaine principal",
        "description": "D\u00e9finir un domaine comme domaine d'envoi principal pour l'entreprise. Seuls les domaines enti\u00e8rement v\u00e9rifi\u00e9s (domain_status=1) peuvent \u00eatre d\u00e9finis comme principaux.",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du domaine"
          }
        ],
        "responses": {
          "200": {
            "description": "Domaine principal mis \u00e0 jour avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainSetPrimaryResponse"
                },
                "example": {
                  "message": "Primary domain updated",
                  "domain": {
                    "id": "123e4567-e89b-12d3-a456-426614174000",
                    "domain": "acme.com",
                    "verification_status": 2,
                    "domain_status": 1,
                    "is_primary": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "Domaine non v\u00e9rifi\u00e9",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Domain not verified",
                  "message": "Only fully verified domains can be set as primary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "setCompanyPrimaryDomain",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.setCompanyPrimaryDomain({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspaces": {
      "get": {
        "summary": "Lister les espaces de travail",
        "description": "R\u00e9cup\u00e9rer une liste pagin\u00e9e des espaces de travail pour l'entreprise authentifi\u00e9e",
        "tags": [
          "Workspaces"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Num\u00e9ro de page pour la pagination",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "description": "Nombre d'\u00e9l\u00e9ments par page",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrer par nom d'espace de travail (correspondance partielle, insensible \u00e0 la casse)"
          },
          {
            "name": "protected",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1",
                "true",
                "false"
              ]
            },
            "description": "Filtrer par statut prot\u00e9g\u00e9"
          },
          {
            "name": "created_after",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Filtrer les espaces de travail cr\u00e9\u00e9s apr\u00e8s cette date (format ISO 8601)"
          },
          {
            "name": "created_before",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Filtrer les espaces de travail cr\u00e9\u00e9s avant cette date (format ISO 8601)"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "name",
                "protected",
                "created_on"
              ],
              "default": "created_on"
            },
            "description": "Champ \u00e0 utiliser pour le tri"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Ordre de tri"
          }
        ],
        "responses": {
          "200": {
            "description": "Espaces de travail r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Horodatage Unix de la r\u00e9initialisation de la limite de d\u00e9bit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceListResponse"
                },
                "example": {
                  "results": [
                    {
                      "id": "789e4567-e89b-12d3-a456-426614174000",
                      "name": "Sales Workspace",
                      "protected": false,
                      "api_key": "fk_a1b2c3d4e5f6g7h8i9j0",
                      "created_date": "2024-01-20T09:00:00Z",
                      "updated_date": "2024-01-20T09:00:00Z"
                    },
                    {
                      "id": "456e4567-e89b-12d3-a456-426614174000",
                      "name": "Default Workspace",
                      "protected": true,
                      "api_key": "fk_z9y8x7w6v5u4t3s2r1q0",
                      "created_date": "2024-01-15T10:30:00Z",
                      "updated_date": "2024-01-15T10:30:00Z"
                    }
                  ],
                  "pagination": {
                    "current_page": 1,
                    "page_size": 20,
                    "total_count": 2,
                    "total_pages": 1
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation - format de date ou param\u00e8tres de tri invalides",
            "content": {
              "application/json": {
                "examples": {
                  "invalidDate": {
                    "summary": "Format de date invalide",
                    "value": {
                      "error": "Validation failed",
                      "code": "VALIDATION_ERROR",
                      "details": [
                        {
                          "path": [
                            "created_after"
                          ],
                          "message": "created_after must be a valid ISO 8601 date"
                        }
                      ]
                    }
                  },
                  "invalidSort": {
                    "summary": "Param\u00e8tre de tri invalide",
                    "value": {
                      "error": "Validation failed",
                      "code": "VALIDATION_ERROR",
                      "details": [
                        {
                          "path": [
                            "sort_order"
                          ],
                          "message": "sort_order must be either 'asc' or 'desc'"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listWorkspaces",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.workspaces.listWorkspaces();\nconsole.log(response);"
          }
        ]
      },
      "post": {
        "summary": "Cr\u00e9er un nouvel espace de travail",
        "description": "Cr\u00e9er un nouvel espace de travail pour l'entreprise authentifi\u00e9e. Tous les espaces de travail sont cr\u00e9\u00e9s comme non prot\u00e9g\u00e9s par d\u00e9faut. Le statut prot\u00e9g\u00e9 ne peut \u00eatre d\u00e9fini que lors de la cr\u00e9ation du compte d'entreprise.",
        "tags": [
          "Workspaces"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom de l'espace de travail"
                  }
                }
              },
              "example": {
                "name": "Marketing Workspace"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Espace de travail cr\u00e9\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Nombre de requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de r\u00e9initialisation de la limite de requ\u00eates"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                },
                "example": {
                  "id": "abc12345-e89b-12d3-a456-426614174000",
                  "name": "Marketing Workspace",
                  "protected": false,
                  "api_key": "fk_m1n2o3p4q5r6s7t8u9v0",
                  "created_date": "2024-01-25T14:00:00Z",
                  "updated_date": "2024-01-25T14:00:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "createWorkspace",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.workspaces.createWorkspace({\n    name: \"Marketing Workspace\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspaces/{id}": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer un espace de travail",
        "description": "R\u00e9cup\u00e8re un espace de travail sp\u00e9cifique par ID, y compris sa cl\u00e9 API",
        "tags": [
          "Workspaces"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de l'espace de travail",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Espace de travail r\u00e9cup\u00e9r\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Nombre de requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de r\u00e9initialisation de la limite de requ\u00eates"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                },
                "example": {
                  "id": "789e4567-e89b-12d3-a456-426614174000",
                  "name": "Sales Workspace",
                  "protected": false,
                  "api_key": "fk_a1b2c3d4e5f6g7h8i9j0",
                  "created_date": "2024-01-20T09:00:00Z",
                  "updated_date": "2024-01-20T09:00:00Z",
                  "webhook_enabled": false,
                  "webhook_secret": null,
                  "webhook_secret_rotated_at": null,
                  "webhook_secret_created_at": null,
                  "ignore_company_webhooks": false
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "getWorkspace",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.workspaces.getWorkspace({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "put": {
        "summary": "Mettre \u00e0 jour un espace de travail",
        "description": "Met \u00e0 jour les informations d'un espace de travail existant. Il s'agit d'une op\u00e9ration de remplacement complet n\u00e9cessitant le champ name.",
        "tags": [
          "Workspaces"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de l'espace de travail",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom de l'espace de travail"
                  }
                }
              },
              "example": {
                "name": "Enterprise Sales Workspace"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Espace de travail mis \u00e0 jour avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Nombre de requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de r\u00e9initialisation de la limite de requ\u00eates"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "updateWorkspace",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.workspaces.updateWorkspace({\n    id: \"id\",\n    name: \"Enterprise Sales Workspace\"\n});\nconsole.log(response);"
          }
        ]
      },
      "patch": {
        "summary": "Mettre \u00e0 jour partiellement un espace de travail",
        "description": "Met \u00e0 jour des champs sp\u00e9cifiques de l'espace de travail. Seul le champ name peut \u00eatre mis \u00e0 jour via l'API. Le champ protected est en lecture seule et ne peut \u00eatre d\u00e9fini que lors de la cr\u00e9ation du compte de l'entreprise.",
        "tags": [
          "Workspaces"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de l'espace de travail",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom de l'espace de travail"
                  }
                }
              },
              "example": {
                "name": "Updated Workspace Name"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Espace de travail mis \u00e0 jour avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Nombre de requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de r\u00e9initialisation de la limite de requ\u00eates"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation",
            "content": {
              "application/json": {
                "examples": {
                  "protectedField": {
                    "summary": "Tentative de mise \u00e0 jour d'un champ prot\u00e9g\u00e9",
                    "value": {
                      "error": "Validation failed",
                      "details": [
                        {
                          "path": [
                            "protected"
                          ],
                          "message": "The 'protected' field cannot be updated via API"
                        }
                      ]
                    }
                  },
                  "noFields": {
                    "summary": "Aucun champ fourni",
                    "value": {
                      "error": "Validation failed",
                      "details": [
                        {
                          "path": [
                            "body"
                          ],
                          "message": "No fields provided to update"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "patchWorkspace",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.workspaces.patchWorkspace({\n    id: \"id\",\n    name: \"Updated Workspace Name\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspaces/{id}/api-key/regenerate": {
      "post": {
        "summary": "R\u00e9g\u00e9n\u00e9rer la cl\u00e9 API de l'espace de travail",
        "description": "R\u00e9g\u00e9n\u00e8re la cl\u00e9 API d'un espace de travail. Applique une expiration de 24 heures aux cl\u00e9s actives existantes et cr\u00e9e une nouvelle cl\u00e9. Ne peut pas \u00eatre utilis\u00e9 sur des espaces de travail prot\u00e9g\u00e9s. Limit\u00e9 \u00e0 1 requ\u00eate par minute.",
        "tags": [
          "Workspaces"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de l'espace de travail",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "key_type": {
                    "type": "string",
                    "enum": [
                      "live",
                      "test"
                    ],
                    "default": "live",
                    "description": "Quel type de cl\u00e9 r\u00e9g\u00e9n\u00e9rer ('live' ou 'test'). Par d\u00e9faut, 'live'. La r\u00e9g\u00e9n\u00e9ration d'un type n'expire pas et n'affecte pas l'autre."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cl\u00e9 API r\u00e9g\u00e9n\u00e9r\u00e9e avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 1 requ\u00eate par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Nombre de requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de r\u00e9initialisation de la limite de requ\u00eates"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyRegenerateResponse"
                },
                "example": {
                  "new_key": {
                    "api_key": "firma_live_abc123xyz...",
                    "created_at": "2024-12-17T10:30:00Z"
                  },
                  "key_type": "live",
                  "expiring_keys": [
                    {
                      "id": "old-key-uuid",
                      "api_key": "firma_old456...",
                      "expires_at": "2024-12-18T10:30:00Z"
                    }
                  ],
                  "workspace_id": "123e4567-e89b-12d3-a456-426614174000"
                }
              }
            }
          },
          "400": {
            "description": "Impossible de r\u00e9g\u00e9n\u00e9rer la cl\u00e9 pour un espace de travail prot\u00e9g\u00e9",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Cannot regenerate API key for protected workspace"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "regenerateWorkspaceApiKey",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.workspaces.regenerateWorkspaceApiKey({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspaces/{id}/api-key/expire": {
      "post": {
        "summary": "Expirer les cl\u00e9s API en attente",
        "description": "Expire imm\u00e9diatement toutes les cl\u00e9s API en attente (celles avec expires_at d\u00e9fini) pour un espace de travail. Utile apr\u00e8s avoir v\u00e9rifi\u00e9 que la nouvelle cl\u00e9 fonctionne correctement. Ne peut pas \u00eatre utilis\u00e9 sur des espaces de travail prot\u00e9g\u00e9s. Limit\u00e9 \u00e0 1 requ\u00eate par minute.",
        "tags": [
          "Workspaces"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de l'espace de travail",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "key_type": {
                    "type": "string",
                    "enum": [
                      "live",
                      "test"
                    ],
                    "description": "Restreindre \u00e9ventuellement l'expiration \u00e0 un seul type de cl\u00e9 ('live' ou 'test'). Si omis, toutes les cl\u00e9s en attente sont expir\u00e9es (comportement actuel)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cl\u00e9s en attente expir\u00e9es avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 1 requ\u00eate par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Nombre de requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de r\u00e9initialisation de la limite de requ\u00eates"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyExpireResponse"
                },
                "example": {
                  "success": true,
                  "expired_keys": [
                    {
                      "id": "old-key-uuid",
                      "api_key": "firma_old456...",
                      "original_expires_at": "2024-12-18T10:30:00Z",
                      "expired_at": "2024-12-17T10:30:00Z"
                    }
                  ],
                  "workspace_id": "123e4567-e89b-12d3-a456-426614174000"
                }
              }
            }
          },
          "400": {
            "description": "Impossible d'expirer les cl\u00e9s pour un espace de travail prot\u00e9g\u00e9",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Cannot expire API keys for protected workspace"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "expireWorkspaceApiKey",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.workspaces.expireWorkspaceApiKey({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/templates": {
      "get": {
        "summary": "Lister les Mod\u00e8les",
        "description": "R\u00e9cup\u00e8re une liste pagin\u00e9e de mod\u00e8les",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "description": "Num\u00e9ro de page"
          },
          {
            "name": "page_size",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "description": "\u00c9l\u00e9ments par page"
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrer par nom de mod\u00e8le (correspondance partielle, insensible \u00e0 la casse)"
          },
          {
            "name": "created_after",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Filtrer les mod\u00e8les cr\u00e9\u00e9s apr\u00e8s cette date (format ISO 8601)"
          },
          {
            "name": "created_before",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Filtrer les mod\u00e8les cr\u00e9\u00e9s avant cette date (format ISO 8601)"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "name",
                "created_on",
                "last_changed_on"
              ],
              "default": "created_on"
            },
            "description": "Champ de tri"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Ordre de tri"
          }
        ],
        "responses": {
          "200": {
            "description": "Mod\u00e8les r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listTemplates",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.templates.listTemplates();\nconsole.log(response);"
          }
        ]
      },
      "post": {
        "summary": "Cr\u00e9er un Mod\u00e8le",
        "description": "Cr\u00e9e un nouveau mod\u00e8le avec un document PDF encod\u00e9 en base64. L'API extrait automatiquement le nombre de pages du document.",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "document"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom du mod\u00e8le",
                    "example": "Employment Contract Template"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description du mod\u00e8le",
                    "example": "Standard employment contract for new hires"
                  },
                  "document": {
                    "type": "string",
                    "format": "byte",
                    "description": "Document PDF ou DOCX encod\u00e9 en base64. Les fichiers DOCX sont automatiquement convertis en PDF. Taille maximale : 20 Mo. L'API extrait automatiquement le nombre de pages du document. (mutuellement exclusif avec document_id)",
                    "example": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c..."
                  },
                  "expiration_hours": {
                    "type": "integer",
                    "description": "Heures avant l'expiration de la demande de signature",
                    "default": 168,
                    "example": 168
                  },
                  "settings": {
                    "type": "object",
                    "properties": {
                      "allow_editing_before_sending": {
                        "type": "boolean",
                        "default": false,
                        "description": "Autoriser la modification des champs avant l'envoi"
                      },
                      "attach_pdf_on_finish": {
                        "type": "boolean",
                        "default": true,
                        "description": "Joindre le PDF termin\u00e9 \u00e0 l'email de finalisation"
                      },
                      "allow_download": {
                        "type": "boolean",
                        "default": true,
                        "description": "Autoriser les destinataires \u00e0 t\u00e9l\u00e9charger le document"
                      },
                      "hand_drawn_only": {
                        "type": "boolean",
                        "default": false,
                        "description": "Exiger des signataires qu'ils dessinent leur signature \u00e0 la main plut\u00f4t que d'utiliser des signatures saisies"
                      },
                      "require_otp_verification": {
                        "type": "boolean",
                        "nullable": true,
                        "default": null,
                        "description": "Exiger des signataires qu'ils v\u00e9rifient leur email avec un code \u00e0 usage unique. null = h\u00e9rite de l'espace de travail/l'entreprise."
                      },
                      "disable_guided_navigation": {
                        "type": "boolean",
                        "nullable": true,
                        "description": "D\u00e9sactiver le d\u00e9filement automatique vers le prochain champ requis pendant la signature. H\u00e9rite de l'espace de travail ou de l'entreprise si non d\u00e9fini."
                      },
                      "allow_presigning_download": {
                        "type": "boolean",
                        "nullable": true,
                        "description": "Autoriser les signataires \u00e0 t\u00e9l\u00e9charger le document original avant de signer. H\u00e9rite du param\u00e8tre de l'espace de travail ou de l'entreprise si null."
                      },
                      "show_qr_code": {
                        "type": "boolean",
                        "nullable": true,
                        "description": "Affiche un QR code sur la page de signature qui permet aux signataires de continuer sur leur t\u00e9l\u00e9phone. H\u00e9rite du param\u00e8tre de l'espace de travail ou de l'entreprise si null."
                      }
                    }
                  },
                  "document_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "ID d'un document pr\u00e9c\u00e9demment t\u00e9l\u00e9vers\u00e9 (mutuellement exclusif avec document). \u00c0 obtenir en appelant d'abord POST /documents.",
                    "example": "123e4567-e89b-12d3-a456-426614174000"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Mod\u00e8le cr\u00e9\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de taux : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "createTemplate",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.templates.createTemplate({\n    name: \"Employment Contract Template\",\n    document: \"JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c...\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/templates/{id}": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer un Mod\u00e8le",
        "description": "R\u00e9cup\u00e8re un mod\u00e8le sp\u00e9cifique par ID",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Mod\u00e8le r\u00e9cup\u00e9r\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de taux : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "getTemplate",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.templates.getTemplate({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "patch": {
        "summary": "Mettre \u00e0 Jour Partiellement un Mod\u00e8le",
        "description": "Met \u00e0 jour les propri\u00e9t\u00e9s du mod\u00e8le, un seul utilisateur, OU un seul champ. Impossible de m\u00e9langer plusieurs types d'entit\u00e9s dans une seule requ\u00eate. Utilisez PUT pour des mises \u00e0 jour compl\u00e8tes incluant les utilisateurs, les champs et les rappels.",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "description": "Mettre \u00e0 jour les propri\u00e9t\u00e9s du mod\u00e8le",
                    "properties": {
                      "name": {
                        "type": "string",
                        "maxLength": 255,
                        "description": "Nom du mod\u00e8le"
                      },
                      "description": {
                        "type": "string",
                        "description": "Description du mod\u00e8le"
                      },
                      "document": {
                        "type": "string",
                        "format": "byte",
                        "description": "PDF ou DOCX encod\u00e9 en base64 pour remplacer le document. Les fichiers DOCX sont automatiquement convertis en PDF. Taille maximale : 20 Mo"
                      },
                      "expiration_hours": {
                        "type": "integer",
                        "minimum": 1,
                        "description": "Heures avant expiration"
                      },
                      "settings": {
                        "type": "object",
                        "properties": {
                          "allow_editing_before_sending": {
                            "type": "boolean"
                          },
                          "attach_pdf_on_finish": {
                            "type": "boolean"
                          },
                          "allow_download": {
                            "type": "boolean"
                          },
                          "hand_drawn_only": {
                            "type": "boolean"
                          },
                          "require_otp_verification": {
                            "type": "boolean",
                            "nullable": true
                          },
                          "disable_guided_navigation": {
                            "type": "boolean",
                            "nullable": true
                          },
                          "allow_presigning_download": {
                            "type": "boolean",
                            "nullable": true,
                            "description": "Autorise les signataires \u00e0 t\u00e9l\u00e9charger le document original avant de signer. H\u00e9rite du param\u00e8tre de l'espace de travail ou de l'entreprise si null."
                          },
                          "show_qr_code": {
                            "type": "boolean",
                            "nullable": true,
                            "description": "Affiche un QR code sur la page de signature qui permet aux signataires de continuer sur leur t\u00e9l\u00e9phone. H\u00e9rite du param\u00e8tre de l'espace de travail ou de l'entreprise si null."
                          }
                        }
                      }
                    }
                  },
                  {
                    "type": "object",
                    "description": "Mettre \u00e0 jour ou cr\u00e9er un seul utilisateur",
                    "required": [
                      "user"
                    ],
                    "properties": {
                      "user": {
                        "type": "object",
                        "required": [
                          "first_name",
                          "email",
                          "designation",
                          "order"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "\u00c0 inclure pour mettre \u00e0 jour un utilisateur existant, \u00e0 omettre pour en cr\u00e9er un nouveau"
                          },
                          "first_name": {
                            "type": "string",
                            "maxLength": 255
                          },
                          "last_name": {
                            "type": "string",
                            "maxLength": 255,
                            "description": "Optionnel, mais requis si vous utilisez les variables pr\u00e9remplies full_name ou last_name"
                          },
                          "email": {
                            "type": "string",
                            "format": "email"
                          },
                          "designation": {
                            "type": "string",
                            "enum": [
                              "Signer",
                              "Approver",
                              "CC"
                            ]
                          },
                          "order": {
                            "type": "integer",
                            "minimum": 1
                          },
                          "phone_number": {
                            "type": "string"
                          },
                          "street_address": {
                            "type": "string"
                          },
                          "city": {
                            "type": "string"
                          },
                          "state_province": {
                            "type": "string"
                          },
                          "postal_code": {
                            "type": "string"
                          },
                          "country": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "company": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  },
                  {
                    "type": "object",
                    "description": "Mettre \u00e0 jour ou cr\u00e9er un seul champ",
                    "required": [
                      "field"
                    ],
                    "properties": {
                      "field": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "\u00c0 inclure pour mettre \u00e0 jour un champ existant, \u00e0 omettre pour en cr\u00e9er un nouveau"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "text",
                              "signature",
                              "date",
                              "checkbox",
                              "initial",
                              "initials",
                              "dropdown",
                              "radio_buttons",
                              "textarea",
                              "text_area",
                              "url",
                              "file",
                              "stamp",
                              "approval_signature",
                              "approval_checkmark",
                              "approval_date"
                            ],
                            "description": "Type de champ. Accepte 'initial' ou 'initials', 'textarea' ou 'text_area'. Requis pour les nouveaux champs. Les champs url sont automatiquement en lecture seule. Les champs file permettent aux signataires de t\u00e9l\u00e9verser des pi\u00e8ces jointes (images/PDF). Les champs stamp affichent une image pr\u00e9configur\u00e9e."
                          },
                          "x": {
                            "type": "number",
                            "description": "Position X sur le document. Requis pour les nouveaux champs."
                          },
                          "y": {
                            "type": "number",
                            "description": "Position Y sur le document. Requis pour les nouveaux champs."
                          },
                          "width": {
                            "type": "number",
                            "description": "Largeur du champ. Requis pour les nouveaux champs."
                          },
                          "height": {
                            "type": "number",
                            "description": "Hauteur du champ. Requis pour les nouveaux champs."
                          },
                          "page": {
                            "type": "integer",
                            "minimum": 1,
                            "description": "Num\u00e9ro de page (index\u00e9 \u00e0 partir de 1). Requis pour les nouveaux champs."
                          },
                          "required": {
                            "type": "boolean",
                            "description": "Si le champ est obligatoire"
                          },
                          "assigned_to_user_id": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true,
                            "description": "ID de l'utilisateur du mod\u00e8le auquel assigner le champ"
                          },
                          "variable_name": {
                            "type": "string",
                            "description": "Nom de variable pour le mapping des donn\u00e9es pr\u00e9remplies"
                          },
                          "variable_defined_name": {
                            "type": "string",
                            "maxLength": 100,
                            "nullable": true,
                            "description": "Nom de d\u00e9finition de champ personnalis\u00e9, lisible par un humain. Peut \u00eatre utilis\u00e9 comme alternative \u00e0 variable_name pour cibler des champs lors de la cr\u00e9ation bas\u00e9e sur un mod\u00e8le."
                          },
                          "options": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Options pour les champs de type liste d\u00e9roulante"
                          },
                          "format_rules": {
                            "type": "object",
                            "description": "R\u00e8gles de format (par ex. format de date, urlDisplayText pour les champs url, acceptedFileTypes pour les champs file)"
                          },
                          "multi_group_id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "ID de groupe pour les groupes de boutons radio"
                          },
                          "default_to_signing_date": {
                            "type": "boolean",
                            "description": "Pour les champs de type date, utilise la date de signature par d\u00e9faut"
                          },
                          "read_only": {
                            "type": "boolean",
                            "description": "Si le champ est en lecture seule (automatiquement vrai pour les champs url)"
                          },
                          "read_only_value": {
                            "type": "string",
                            "description": "Valeur statique pour les champs en lecture seule. Pour les champs url, il s'agit de l'URL vers laquelle pointer."
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "examples": {
                "update-properties": {
                  "summary": "Mettre \u00e0 jour les propri\u00e9t\u00e9s",
                  "value": {
                    "name": "Updated Template Name",
                    "expiration_hours": 72
                  }
                },
                "create-url-field": {
                  "summary": "Cr\u00e9er un champ URL",
                  "value": {
                    "field": {
                      "type": "url",
                      "x": 100,
                      "y": 200,
                      "width": 150,
                      "height": 30,
                      "page": 1,
                      "read_only_value": "https://example.com/terms",
                      "format_rules": {
                        "urlDisplayText": "View Terms & Conditions"
                      }
                    }
                  }
                },
                "create-file-field": {
                  "summary": "Cr\u00e9er un champ de t\u00e9l\u00e9versement de fichier",
                  "value": {
                    "field": {
                      "type": "file",
                      "x": 100,
                      "y": 300,
                      "width": 200,
                      "height": 40,
                      "page": 1,
                      "required": true,
                      "format_rules": {
                        "acceptedFileTypes": "image_and_pdf"
                      }
                    }
                  }
                },
                "update-field": {
                  "summary": "Mettre \u00e0 jour un champ existant",
                  "value": {
                    "field": {
                      "id": "field123-e89b-12d3-a456-426614174000",
                      "x": 120,
                      "y": 220
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mod\u00e8le partiellement mis \u00e0 jour avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de taux : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplatePatchResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "patchTemplate",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.templates.patchTemplate({\n    id: \"id\",\n    body: {\n        name: \"Updated Template Name\",\n        expiration_hours: 72\n    }\n});\nconsole.log(response);"
          }
        ]
      },
      "put": {
        "summary": "Mise \u00e0 Jour Compl\u00e8te du Mod\u00e8le",
        "description": "Mise \u00e0 jour compl\u00e8te du mod\u00e8le incluant les propri\u00e9t\u00e9s, les utilisateurs, les champs et les rappels. Prend en charge la suppression d'utilisateurs avec r\u00e9assignation ou suppression des champs. Toutes les sections sont optionnelles mais au moins une doit \u00eatre fournie.",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "template_properties": {
                    "type": "object",
                    "description": "Mettre \u00e0 jour les m\u00e9tadonn\u00e9es et les param\u00e8tres du mod\u00e8le",
                    "properties": {
                      "name": {
                        "type": "string",
                        "maxLength": 255
                      },
                      "description": {
                        "type": "string"
                      },
                      "document": {
                        "type": "string",
                        "format": "byte",
                        "description": "PDF ou DOCX encod\u00e9 en base64 pour remplacer le document. Les fichiers DOCX sont automatiquement convertis en PDF. Taille maximale : 20 Mo"
                      },
                      "expiration_hours": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "settings": {
                        "type": "object",
                        "properties": {
                          "allow_editing_before_sending": {
                            "type": "boolean"
                          },
                          "attach_pdf_on_finish": {
                            "type": "boolean"
                          },
                          "allow_download": {
                            "type": "boolean"
                          },
                          "hand_drawn_only": {
                            "type": "boolean"
                          },
                          "require_otp_verification": {
                            "type": "boolean",
                            "nullable": true
                          },
                          "disable_guided_navigation": {
                            "type": "boolean",
                            "nullable": true
                          },
                          "allow_presigning_download": {
                            "type": "boolean",
                            "nullable": true,
                            "description": "Autorise les signataires \u00e0 t\u00e9l\u00e9charger le document original avant de signer. H\u00e9rite du param\u00e8tre de l'espace de travail ou de l'entreprise si null."
                          },
                          "show_qr_code": {
                            "type": "boolean",
                            "nullable": true,
                            "description": "Affiche un QR code sur la page de signature qui permet aux signataires de continuer sur leur t\u00e9l\u00e9phone. H\u00e9rite du param\u00e8tre de l'espace de travail ou de l'entreprise si null."
                          }
                        }
                      }
                    }
                  },
                  "users": {
                    "type": "array",
                    "description": "Cr\u00e9e ou met \u00e0 jour des utilisateurs (inclure id pour mettre \u00e0 jour, omettre pour cr\u00e9er)",
                    "items": {
                      "type": "object",
                      "required": [
                        "first_name",
                        "email",
                        "designation",
                        "order"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "\u00c0 omettre pour les nouveaux utilisateurs"
                        },
                        "first_name": {
                          "type": "string"
                        },
                        "last_name": {
                          "type": "string",
                          "description": "Optionnel, mais requis si vous utilisez les variables pr\u00e9remplies full_name ou last_name"
                        },
                        "email": {
                          "type": "string",
                          "format": "email"
                        },
                        "designation": {
                          "type": "string",
                          "enum": [
                            "Signer",
                            "Approver",
                            "CC"
                          ]
                        },
                        "order": {
                          "type": "integer",
                          "minimum": 1
                        },
                        "phone_number": {
                          "type": "string"
                        },
                        "street_address": {
                          "type": "string"
                        },
                        "city": {
                          "type": "string"
                        },
                        "state_province": {
                          "type": "string"
                        },
                        "postal_code": {
                          "type": "string"
                        },
                        "country": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "company": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "force_remove_conditions": {
                    "type": "boolean",
                    "default": false,
                    "description": "Lors de la suppression d'utilisateurs dont les champs sont r\u00e9f\u00e9renc\u00e9s par des conditions dans d'autres champs : si true, supprime automatiquement les r\u00e9f\u00e9rences de condition ; si false (par d\u00e9faut), la requ\u00eate sera rejet\u00e9e avec une erreur."
                  },
                  "deleted_users": {
                    "type": "array",
                    "description": "Utilisateurs \u00e0 supprimer avec strat\u00e9gie de gestion des champs",
                    "items": {
                      "type": "object",
                      "required": [
                        "user_id",
                        "field_action"
                      ],
                      "properties": {
                        "user_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "field_action": {
                          "type": "string",
                          "enum": [
                            "delete",
                            "reassign"
                          ],
                          "description": "Que faire des champs assign\u00e9s \u00e0 cet utilisateur"
                        },
                        "reassign_to_user_id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Requis quand field_action vaut 'reassign'. L'utilisateur cible doit avoir la m\u00eame d\u00e9signation."
                        }
                      }
                    }
                  },
                  "fields": {
                    "type": "array",
                    "description": "Upsert des champs (inclure id pour mettre \u00e0 jour, omettre pour cr\u00e9er)",
                    "items": {
                      "type": "object",
                      "required": [
                        "type",
                        "x",
                        "y",
                        "width",
                        "height",
                        "page"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Omettre pour les nouveaux champs"
                        },
                        "type": {
                          "type": "string",
                          "enum": [
                            "signature",
                            "text",
                            "date",
                            "checkbox",
                            "dropdown",
                            "approval_signature",
                            "approval_checkmark",
                            "approval_date"
                          ]
                        },
                        "x": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 100,
                          "description": "Position X en pourcentage"
                        },
                        "y": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 100,
                          "description": "Position Y en pourcentage"
                        },
                        "width": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 100
                        },
                        "height": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 100
                        },
                        "page": {
                          "type": "integer",
                          "minimum": 1
                        },
                        "required": {
                          "type": "boolean",
                          "default": false
                        },
                        "assigned_to_user_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "options": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Pour les champs de type liste d\u00e9roulante"
                        },
                        "default_to_signing_date": {
                          "type": "boolean",
                          "description": "Pour les champs de type date"
                        },
                        "multi_group_id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "ID de groupe pour les groupes de cases \u00e0 cocher/boutons radio mutuellement exclusifs"
                        },
                        "variable_name": {
                          "type": "string"
                        },
                        "variable_defined_name": {
                          "type": "string",
                          "maxLength": 100,
                          "nullable": true,
                          "description": "Nom de d\u00e9finition de champ personnalis\u00e9 lisible par un humain. Peut \u00eatre utilis\u00e9 comme alternative \u00e0 variable_name pour cibler des champs lors de la cr\u00e9ation bas\u00e9e sur un mod\u00e8le."
                        },
                        "required_conditions": {
                          "$ref": "#/components/schemas/ConditionSet",
                          "nullable": true
                        },
                        "visibility_conditions": {
                          "$ref": "#/components/schemas/ConditionSet",
                          "nullable": true
                        }
                      }
                    }
                  },
                  "reminders": {
                    "type": "array",
                    "description": "Upsert des rappels (inclure id pour mettre \u00e0 jour, omettre pour cr\u00e9er)",
                    "items": {
                      "type": "object",
                      "required": [
                        "hours",
                        "subject",
                        "message"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Omettre pour les nouveaux rappels"
                        },
                        "hours": {
                          "type": "integer",
                          "minimum": 1,
                          "description": "Heures apr\u00e8s l'envoi avant le rappel"
                        },
                        "all_users": {
                          "type": "boolean",
                          "default": false
                        },
                        "user_id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Requis si all_users vaut false"
                        },
                        "subject": {
                          "type": "string",
                          "maxLength": 255
                        },
                        "message": {
                          "type": "string",
                          "maxLength": 5000
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mod\u00e8le mis \u00e0 jour avec succ\u00e8s. Retourne le mod\u00e8le complet avec toutes ses relations.",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de taux : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "updateTemplate",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.templates.updateTemplate({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer un mod\u00e8le",
        "description": "Suppression douce d'un mod\u00e8le par ID. Cela marque le mod\u00e8le comme supprim\u00e9 mais conserve les donn\u00e9es.",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID du mod\u00e8le",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Mod\u00e8le supprim\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de taux : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Horodatage Unix de la r\u00e9initialisation de la limite de taux"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                },
                "example": {
                  "message": "Template deleted successfully"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "deleteTemplate",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.templates.deleteTemplate({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/templates/{id}/users": {
      "get": {
        "summary": "Obtenir les utilisateurs du mod\u00e8le",
        "description": "R\u00e9cup\u00e9rer tous les destinataires/utilisateurs associ\u00e9s \u00e0 un mod\u00e8le sp\u00e9cifique",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID du mod\u00e8le",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Utilisateurs du mod\u00e8le r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de taux : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Horodatage Unix de la r\u00e9initialisation de la limite de taux"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateUserListResponse"
                },
                "example": {
                  "results": [
                    {
                      "id": "abc12345-e89b-12d3-a456-426614174000",
                      "name": "John Doe",
                      "email": "john@example.com",
                      "first_name": "John",
                      "last_name": "Doe",
                      "designation": "Signer",
                      "order": 1,
                      "phone_number": null,
                      "street_address": null,
                      "city": null,
                      "state_province": null,
                      "postal_code": null,
                      "country": null,
                      "title": null,
                      "company": null,
                      "required_fields": [
                        "email",
                        "first_name"
                      ],
                      "missing_fields": [],
                      "required_read_only_fields": [],
                      "ready_to_send": true
                    },
                    {
                      "id": "def67890-e89b-12d3-a456-426614174000",
                      "name": null,
                      "email": null,
                      "first_name": null,
                      "last_name": null,
                      "designation": "Signer",
                      "order": 2,
                      "phone_number": null,
                      "street_address": null,
                      "city": null,
                      "state_province": null,
                      "postal_code": null,
                      "country": null,
                      "title": null,
                      "company": null,
                      "required_fields": [
                        "email",
                        "first_name",
                        "phone_number"
                      ],
                      "missing_fields": [
                        "email",
                        "first_name",
                        "phone_number"
                      ],
                      "required_read_only_fields": [
                        {
                          "variable_name": "contract_date",
                          "field_type": "date"
                        }
                      ],
                      "ready_to_send": false
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listTemplateUsers",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.templates.listTemplateUsers({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/templates/{id}/fields": {
      "get": {
        "summary": "Obtenir les champs du mod\u00e8le",
        "description": "R\u00e9cup\u00e9rer tous les champs configur\u00e9s pour un mod\u00e8le sp\u00e9cifique",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID du mod\u00e8le",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Champs du mod\u00e8le r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de taux : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Horodatage Unix de la r\u00e9initialisation de la limite de taux"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateFieldListResponse"
                },
                "example": {
                  "results": [
                    {
                      "id": "field123-e89b-12d3-a456-426614174000",
                      "type": "signature",
                      "required": true,
                      "recipient_id": "user123-uuid",
                      "variable_name": null,
                      "position": {
                        "x": 100,
                        "y": 200,
                        "width": 200,
                        "height": 50
                      },
                      "page_number": 1,
                      "dropdown_options": null,
                      "multi_group_id": null,
                      "date_signing_default": false,
                      "format_rules": null,
                      "validation_rules": null,
                      "read_only": false,
                      "read_only_value": null
                    },
                    {
                      "id": "field456-e89b-12d3-a456-426614174000",
                      "type": "date",
                      "required": true,
                      "recipient_id": "user123-uuid",
                      "variable_name": null,
                      "position": {
                        "x": 100,
                        "y": 250,
                        "width": 150,
                        "height": 30
                      },
                      "page_number": 1,
                      "dropdown_options": null,
                      "multi_group_id": null,
                      "date_signing_default": true,
                      "format_rules": {
                        "date_format": "MM/DD/YYYY"
                      },
                      "validation_rules": null,
                      "read_only": false,
                      "read_only_value": null
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listTemplateFields",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.templates.listTemplateFields({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/templates/{id}/reminders": {
      "get": {
        "summary": "Obtenir les rappels du mod\u00e8le",
        "description": "R\u00e9cup\u00e9rer tous les rappels configur\u00e9s pour un mod\u00e8le sp\u00e9cifique",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID du mod\u00e8le",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rappels du mod\u00e8le r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de taux : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Horodatage Unix de la r\u00e9initialisation de la limite de taux"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Reminder"
                  }
                },
                "example": [
                  {
                    "id": "remind123-e89b-12d3-a456-426614174000",
                    "hours": 24,
                    "subject": "Reminder: Please sign the document",
                    "message": "This is a friendly reminder to complete your signature.",
                    "all_users": true,
                    "template_user_id": null,
                    "created_date": "2024-01-15T10:30:00Z",
                    "updated_date": "2024-01-15T10:30:00Z"
                  }
                ]
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listTemplateReminders",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.templates.listTemplateReminders({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/templates/{id}/replace-document": {
      "post": {
        "summary": "Remplacer le document du mod\u00e8le",
        "description": "Remplace le document PDF d'un mod\u00e8le existant tout en pr\u00e9servant tous les placements de champs. Le document de remplacement doit avoir le m\u00eame nombre de pages et des dimensions de page correspondantes (avec une tol\u00e9rance de 1pt) que l'original.",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du mod\u00e8le"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "document"
                ],
                "properties": {
                  "document": {
                    "type": "string",
                    "description": "Document PDF ou DOCX encod\u00e9 en base64. Les fichiers DOCX sont automatiquement convertis en PDF."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document remplac\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de taux : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation (nombre de pages incompatible, dimensions incompatibles, document invalide)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "replaceTemplateDocument",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.templates.replaceTemplateDocument({\n    id: \"id\",\n    document: \"document\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/templates/{id}/duplicate": {
      "post": {
        "summary": "Dupliquer le mod\u00e8le en une demande de signature",
        "description": "Cr\u00e9e une nouvelle demande de signature en dupliquant un mod\u00e8le existant, y compris tous les champs, utilisateurs, rappels et param\u00e8tres.",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du mod\u00e8le \u00e0 dupliquer"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom personnalis\u00e9 pour la nouvelle demande de signature (par d\u00e9faut, le nom du mod\u00e8le)"
                  }
                }
              },
              "example": {
                "name": "Q4 2025 Contract"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Mod\u00e8le dupliqu\u00e9 avec succ\u00e8s en une nouvelle demande de signature",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de taux : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateDuplicateResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "description": "Le mod\u00e8le appartient \u00e0 un espace de travail diff\u00e9rent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "duplicateTemplate",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.templates.duplicateTemplate({\n    id: \"id\",\n    name: \"Q4 2025 Contract\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests": {
      "get": {
        "summary": "Lister les Demandes de Signature",
        "description": "R\u00e9cup\u00e9rer une liste pagin\u00e9e des demandes de signature",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "description": "Num\u00e9ro de page"
          },
          {
            "name": "page_size",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "description": "\u00c9l\u00e9ments par page"
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrer par nom de demande de signature (correspondance partielle, insensible \u00e0 la casse)"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "not_sent",
                "in_progress",
                "finished",
                "cancelled",
                "declined",
                "deleted",
                "expired"
              ]
            },
            "description": "Filtrer par statut de demande de signature. Prend en charge plusieurs valeurs s\u00e9par\u00e9es par des virgules.\n\n**Statuts disponibles :**\n- `not_sent` : Demande cr\u00e9\u00e9e mais pas encore envoy\u00e9e aux signataires\n- `in_progress` : Envoy\u00e9e aux signataires mais pas termin\u00e9e, annul\u00e9e, refus\u00e9e ou expir\u00e9e\n- `finished` : Tous les signataires ont termin\u00e9\n- `cancelled` : La demande a \u00e9t\u00e9 annul\u00e9e par l'exp\u00e9diteur\n- `declined` : Un signataire a refus\u00e9 de signer (la demande est arr\u00eat\u00e9e)\n- `deleted` : Enregistrements supprim\u00e9s en douceur (normalement masqu\u00e9s)\n- `expired` : Envoy\u00e9e mais au-del\u00e0 du d\u00e9lai d'expiration (sent_on + expiration_hours < maintenant)\n\n**Exemple :** `?status=in_progress,expired`\n\n**Remarque :** Le statut `expired` utilise un post-filtrage qui peut avoir des implications sur les performances avec de grands ensembles de donn\u00e9es."
          },
          {
            "name": "created_after",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Filtrer les demandes de signature cr\u00e9\u00e9es apr\u00e8s cette date (format ISO 8601)"
          },
          {
            "name": "created_before",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Filtre les demandes de signature cr\u00e9\u00e9es avant cette date (format ISO 8601)"
          },
          {
            "name": "signer_email",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtre par adresse email du signataire (correspondance exacte)"
          },
          {
            "name": "signer_name",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtre par nom du signataire (correspondance partielle, insensible \u00e0 la casse)"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "name",
                "created_on",
                "expiration_hours",
                "sent_on",
                "finished_on"
              ],
              "default": "created_on"
            },
            "description": "Champ utilis\u00e9 pour le tri"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Ordre de tri"
          }
        ],
        "responses": {
          "200": {
            "description": "Demandes de signature r\u00e9cup\u00e9r\u00e9es avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningRequestListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listSigningRequests",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.listSigningRequests();\nconsole.log(response);"
          }
        ]
      },
      "post": {
        "summary": "Cr\u00e9er une Demande de Signature",
        "description": "Cr\u00e9e une nouvelle demande de signature soit \u00e0 partir d'un document PDF (bas\u00e9 sur un document), soit \u00e0 partir d'un mod\u00e8le existant (bas\u00e9 sur un mod\u00e8le). Pour une cr\u00e9ation bas\u00e9e sur un document, allow_editing_before_sending est automatiquement d\u00e9fini sur true. Pour une cr\u00e9ation bas\u00e9e sur un mod\u00e8le, les propri\u00e9t\u00e9s sont h\u00e9rit\u00e9es du mod\u00e8le et peuvent \u00eatre surcharg\u00e9es.\n\n**Motif d'ID Temporaire** : Pour une cr\u00e9ation bas\u00e9e sur un document, tu peux r\u00e9f\u00e9rencer des destinataires avant qu'ils soient cr\u00e9\u00e9s en utilisant des ID temporaires (format : 'temp_X' o\u00f9 X est un identifiant quelconque, par exemple 'temp_1', 'temp_alice'). Utilise ces ID temporaires dans recipient.id, field.recipient_id et reminder.recipient_id. L'API valide toutes les r\u00e9f\u00e9rences et fait automatiquement correspondre les ID temporaires aux vrais UUID une fois les destinataires cr\u00e9\u00e9s. La r\u00e9ponse ne contient que de vrais UUID.\n\n**Validation des ID Temporaires** : Les ID temporaires doivent commencer par 'temp_', \u00eatre uniques parmi tous les destinataires de la requ\u00eate, et toutes les r\u00e9f\u00e9rences de champ/rappel doivent pointer vers des destinataires d\u00e9finis dans la m\u00eame requ\u00eate. Un format invalide, des ID en double ou des r\u00e9f\u00e9rences de destinataires manquantes renvoient une erreur 400 avec des messages de validation d\u00e9taill\u00e9s.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/PatchSigningRequestBody"
        },
        "responses": {
          "201": {
            "description": "Demande de signature cr\u00e9\u00e9e avec succ\u00e8s. La r\u00e9ponse peut inclure un tableau 'warnings' pour les avertissements de validation de format d'email (non bloquants).",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningRequestCreateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError",
            "description": "Entr\u00e9e invalide - tu dois fournir soit 'document' soit 'template_id', pas les deux. Le document doit \u00eatre un PDF valide encod\u00e9 en base64 de moins de 20 Mo. Le mod\u00e8le doit exister et appartenir \u00e0 l'espace de travail."
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "description": "Mod\u00e8le introuvable ou n'appartenant pas \u00e0 l'espace de travail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "createSigningRequest",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.createSigningRequest({\n    template_id: \"template_id\",\n    name: \"Updated Contract Name\",\n    expiration_hours: 72\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/create-and-send": {
      "post": {
        "summary": "Cr\u00e9er et Envoyer une Demande de Signature (Atomique)",
        "description": "Cr\u00e9e et envoie imm\u00e9diatement une demande de signature en une seule op\u00e9ration atomique. Ce endpoint combine les fonctionnalit\u00e9s de POST /signing-requests et POST /signing-requests/{id}/send.\n\n**Avantages Cl\u00e9s :**\n- Un seul appel API au lieu de deux requ\u00eates s\u00e9par\u00e9es\n- Valide toutes les exigences d'envoi AVANT de cr\u00e9er la demande de signature\n- D\u00e9duction de cr\u00e9dit atomique - facture uniquement si tout r\u00e9ussit\n- Renvoie status: 'sent' imm\u00e9diatement avec les d\u00e9tails du premier signataire\n- Plus efficace (\u00e9conomise 1 appel API + le temps d'aller-retour)\n\n**Validation :**\n- Toutes les validations de cr\u00e9ation standard (document/mod\u00e8le, destinataires, champs)\n- Validations d'envoi suppl\u00e9mentaires :\n  - Tous les signataires doivent avoir un first_name et un email valide\n  - Les champs en lecture seule requis doivent avoir un final_value renseign\u00e9\n  - Les champs de donn\u00e9es pr\u00e9rempli\u00e9es (variable_name) doivent avoir les donn\u00e9es utilisateur correspondantes\n  - L'entreprise doit disposer de cr\u00e9dits suffisants (\u22651)\n\n**Atomicit\u00e9 :**\n- Si une validation \u00e9choue, rien n'est cr\u00e9\u00e9\n- Le cr\u00e9dit n'est d\u00e9duit qu'apr\u00e8s la cr\u00e9ation r\u00e9ussie et avant l'envoi de l'email\n- Si l'envoi de l'email \u00e9choue apr\u00e8s la cr\u00e9ation, la demande de signature reste au statut 'draft' et le cr\u00e9dit N'est PAS d\u00e9duit\n\n**Motif d'ID Temporaire :** Pour une cr\u00e9ation bas\u00e9e sur un document, utilise des ID temporaires (format : 'temp_X') pour r\u00e9f\u00e9rencer les destinataires avant leur cr\u00e9ation. L'API valide toutes les r\u00e9f\u00e9rences et fait automatiquement correspondre les ID temporaires aux vrais UUID.\n\n**Limite de D\u00e9bit :** 120 requ\u00eates/minute (identique aux op\u00e9rations d'\u00e9criture)",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom de la demande de signature",
                    "example": "Employment Contract - John Doe"
                  },
                  "description": {
                    "type": "string",
                    "description": "Description de la demande de signature",
                    "example": "Full-time employment contract for Software Engineer position"
                  },
                  "document": {
                    "type": "string",
                    "format": "byte",
                    "description": "Document PDF ou DOCX encod\u00e9 en base64 (mutuellement exclusif avec template_id et document_id). Les fichiers DOCX sont automatiquement convertis en PDF. Taille maximale : 50 Mo.",
                    "example": "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQgMSAwIFIKL1Jlc291c..."
                  },
                  "template_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "ID du mod\u00e8le \u00e0 utiliser (mutuellement exclusif avec document et document_id)",
                    "example": "123e4567-e89b-12d3-a456-426614174000"
                  },
                  "expiration_hours": {
                    "type": "integer",
                    "minimum": 1,
                    "default": 168,
                    "description": "Nombre d'heures avant l'expiration de la demande de signature (par d\u00e9faut : 168 = 7 jours)",
                    "example": 168
                  },
                  "recipients": {
                    "type": "array",
                    "description": "Tableau de destinataires. Au moins un doit \u00eatre un Signataire. Pour une cr\u00e9ation bas\u00e9e sur un document : obligatoire. Pour une cr\u00e9ation bas\u00e9e sur un mod\u00e8le : optionnel (utilise les destinataires du mod\u00e8le si omis). Utilisez template_user_id (pr\u00e9f\u00e9r\u00e9) ou order (solution de repli) pour faire correspondre les utilisateurs du mod\u00e8le.",
                    "minItems": 1,
                    "items": {
                      "$ref": "#/components/schemas/Recipient"
                    }
                  },
                  "fields": {
                    "type": "array",
                    "description": "Tableau de champs \u00e0 remplir (bas\u00e9 sur un document uniquement)",
                    "items": {
                      "type": "object",
                      "required": [
                        "type",
                        "page",
                        "x",
                        "y"
                      ],
                      "properties": {
                        "recipient_id": {
                          "type": "string",
                          "description": "ID temporaire ou UUID du destinataire assign\u00e9 \u00e0 ce champ",
                          "example": "temp_signer_1"
                        },
                        "type": {
                          "type": "string",
                          "enum": [
                            "signature",
                            "initial",
                            "text",
                            "date",
                            "checkbox",
                            "dropdown",
                            "radio_buttons",
                            "text_area",
                            "url",
                            "file",
                            "stamp",
                            "approval_signature",
                            "approval_checkmark",
                            "approval_date"
                          ],
                          "description": "Type de champ. Accepte les alias : \"initials\" (normalis\u00e9 en \"initial\"), \"textarea\" (normalis\u00e9 en \"text_area\"), \"radio\" (normalis\u00e9 en \"radio_buttons\").",
                          "example": "signature"
                        },
                        "page": {
                          "type": "integer",
                          "minimum": 1,
                          "description": "Num\u00e9ro de page du PDF (index\u00e9 \u00e0 partir de 1)",
                          "example": 1
                        },
                        "x": {
                          "type": "number",
                          "description": "Coordonn\u00e9e X sur la page",
                          "example": 100
                        },
                        "y": {
                          "type": "number",
                          "description": "Coordonn\u00e9e Y sur la page",
                          "example": 200
                        },
                        "width": {
                          "type": "number",
                          "default": 200,
                          "example": 200
                        },
                        "height": {
                          "type": "number",
                          "default": 50,
                          "example": 50
                        },
                        "variable_name": {
                          "type": "string",
                          "description": "Nom de variable pour les donn\u00e9es pr\u00e9remplies (par ex. 'phone_number', 'company'). Si d\u00e9fini, le champ correspondant du destinataire doit \u00eatre renseign\u00e9.",
                          "enum": [
                            "first_name",
                            "last_name",
                            "full_name",
                            "email",
                            "phone_number",
                            "street_address",
                            "city",
                            "state_province",
                            "postal_code",
                            "country",
                            "title",
                            "company"
                          ],
                          "example": "phone_number"
                        },
                        "variable_defined_name": {
                          "type": "string",
                          "maxLength": 100,
                          "nullable": true,
                          "description": "Nom lisible et personnalis\u00e9 de la d\u00e9finition du champ. Peut \u00eatre utilis\u00e9 comme alternative \u00e0 variable_name pour cibler des champs lors d'une cr\u00e9ation bas\u00e9e sur un mod\u00e8le."
                        },
                        "required": {
                          "type": "boolean",
                          "default": false,
                          "description": "Indique si le champ est obligatoire"
                        },
                        "read_only": {
                          "type": "boolean",
                          "default": false,
                          "description": "Indique si le champ est en lecture seule (pr\u00e9rempli)"
                        },
                        "final_value": {
                          "type": "string",
                          "description": "Valeur pr\u00e9remplie pour les champs en lecture seule (obligatoire si read_only=true et required=true)",
                          "example": "Software Engineer"
                        },
                        "background_color": {
                          "type": "string",
                          "nullable": true,
                          "pattern": "^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$",
                          "description": "Couleur d'arri\u00e8re-plan en hexad\u00e9cimal (par ex. '#FFFDE7')",
                          "example": "#FFFDE7"
                        },
                        "dropdown_options": {
                          "description": "Options pour les champs de type liste d\u00e9roulante. Obligatoire quand type vaut \"dropdown\".",
                          "example": [
                            "Option A",
                            "Option B",
                            "Option C"
                          ],
                          "oneOf": [
                            {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            {
                              "type": "object"
                            }
                          ]
                        }
                      }
                    }
                  },
                  "anchor_tags": {
                    "type": "array",
                    "maxItems": 100,
                    "items": {
                      "$ref": "#/components/schemas/AnchorTag"
                    },
                    "description": "Balises d'ancrage pour le placement automatique des champs. Les marqueurs de texte dans le PDF sont localis\u00e9s puis convertis en champs positionn\u00e9s. Le texte d'ancrage est supprim\u00e9 du PDF apr\u00e8s traitement. Les champs cr\u00e9\u00e9s \u00e0 partir des balises d'ancrage s'ajoutent aux champs sp\u00e9cifi\u00e9s manuellement. Disponible uniquement pour la cr\u00e9ation bas\u00e9e sur un document (pas pour celle bas\u00e9e sur un mod\u00e8le)."
                  },
                  "reminders": {
                    "type": "array",
                    "description": "Tableau de configurations de rappels",
                    "items": {
                      "type": "object",
                      "required": [
                        "hours_before_expiration"
                      ],
                      "properties": {
                        "hours_before_expiration": {
                          "type": "integer",
                          "minimum": 1,
                          "description": "Heures avant expiration pour l'envoi du rappel",
                          "example": 24
                        }
                      }
                    }
                  },
                  "settings": {
                    "type": "object",
                    "description": "Param\u00e8tres de la demande de signature",
                    "properties": {
                      "use_signing_order": {
                        "type": "boolean",
                        "default": true,
                        "description": "Impose l'ordre de signature bas\u00e9 sur recipient.order. Si false, tous les signataires re\u00e7oivent le document simultan\u00e9ment."
                      },
                      "allow_download": {
                        "type": "boolean",
                        "default": true,
                        "description": "Autoriser les destinataires \u00e0 t\u00e9l\u00e9charger le document"
                      },
                      "attach_pdf_on_finish": {
                        "type": "boolean",
                        "default": true,
                        "description": "Joindre le PDF finalis\u00e9 \u00e0 l'e-mail de fin de signature"
                      },
                      "send_signing_email": {
                        "type": "boolean",
                        "default": true,
                        "description": "Envoyer une notification par e-mail aux signataires"
                      },
                      "send_finish_email": {
                        "type": "boolean",
                        "default": true,
                        "description": "Envoyer un e-mail quand toutes les signatures sont termin\u00e9es"
                      },
                      "send_expiration_email": {
                        "type": "boolean",
                        "default": true,
                        "description": "Envoyer un e-mail quand la demande expire"
                      },
                      "send_cancellation_email": {
                        "type": "boolean",
                        "default": true,
                        "description": "Envoyer un e-mail quand la demande est annul\u00e9e"
                      },
                      "hand_drawn_only": {
                        "type": "boolean",
                        "default": false,
                        "description": "Exiger que les signataires dessinent leur signature \u00e0 la main plut\u00f4t que d'utiliser une signature saisie"
                      },
                      "identity_editable_fields": {
                        "type": "array",
                        "nullable": true,
                        "items": {
                          "type": "string",
                          "enum": [
                            "name",
                            "company",
                            "title",
                            "phone",
                            "address"
                          ]
                        },
                        "description": "Champs d'identit\u00e9 que les signataires peuvent modifier avant de signer. null = d\u00e9sactiv\u00e9. Si d\u00e9fini, une bo\u00eete de dialogue de confirmation appara\u00eet pour permettre aux signataires de modifier les champs sp\u00e9cifi\u00e9s.",
                        "example": [
                          "name",
                          "company"
                        ]
                      },
                      "notify_identity_change_webhook": {
                        "type": "boolean",
                        "default": false,
                        "description": "Envoyer un \u00e9v\u00e9nement webhook quand un signataire modifie son identit\u00e9"
                      },
                      "notify_identity_change_email": {
                        "type": "boolean",
                        "default": false,
                        "description": "Envoyer une notification par e-mail quand un signataire modifie son identit\u00e9"
                      }
                    }
                  },
                  "document_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "ID d'un document pr\u00e9c\u00e9demment t\u00e9l\u00e9vers\u00e9 (mutuellement exclusif avec document et template_id). \u00c0 obtenir en appelant d'abord POST /documents.",
                    "example": "123e4567-e89b-12d3-a456-426614174000"
                  },
                  "language": {
                    "type": "string",
                    "nullable": true,
                    "enum": [
                      "en",
                      "es",
                      "it",
                      "pt",
                      "fr",
                      "de",
                      "el",
                      "ru",
                      "pl",
                      "cs",
                      "sv",
                      "nl",
                      "ro",
                      "nb"
                    ],
                    "description": "Langue facultative des e-mails pour cette demande de signature. Lorsqu'elle est d\u00e9finie, tous les e-mails destin\u00e9s au signataire (et le format de date) l'utilisent. Omettez-la ou utilisez null pour revenir \u00e0 la langue par d\u00e9faut de l'espace de travail, puis de l'entreprise (comportement inchang\u00e9)."
                  }
                },
                "oneOf": [
                  {
                    "required": [
                      "document"
                    ]
                  },
                  {
                    "required": [
                      "template_id"
                    ]
                  }
                ]
              },
              "examples": {
                "document-based": {
                  "summary": "Cr\u00e9er et envoyer avec un document",
                  "value": {
                    "name": "Employment Contract - John Doe",
                    "description": "Contrat de travail \u00e0 temps plein",
                    "document": "JVBERi0xLjQKJeLjz9MK...",
                    "expiration_hours": 168,
                    "recipients": [
                      {
                        "id": "temp_signer_1",
                        "first_name": "John",
                        "last_name": "Doe",
                        "email": "john.doe@example.com",
                        "designation": "Signer",
                        "order": 1,
                        "phone_number": "+1-555-0123",
                        "company": "Acme Corp",
                        "title": "Ing\u00e9nieur logiciel"
                      }
                    ],
                    "fields": [
                      {
                        "recipient_id": "temp_signer_1",
                        "type": "signature",
                        "page": 1,
                        "x": 100,
                        "y": 500,
                        "width": 200,
                        "height": 50
                      },
                      {
                        "recipient_id": "temp_signer_1",
                        "type": "text",
                        "page": 1,
                        "x": 100,
                        "y": 400,
                        "width": 150,
                        "height": 30,
                        "variable_name": "phone_number",
                        "required": true,
                        "read_only": true
                      }
                    ],
                    "settings": {
                      "use_signing_order": true,
                      "send_signing_email": true
                    }
                  }
                },
                "template-based": {
                  "summary": "Cr\u00e9er et envoyer \u00e0 partir d'un mod\u00e8le",
                  "value": {
                    "name": "NDA - Jane Smith",
                    "template_id": "123e4567-e89b-12d3-a456-426614174000",
                    "recipients": [
                      {
                        "first_name": "Jane",
                        "last_name": "Smith",
                        "email": "jane.smith@example.com",
                        "designation": "Signer",
                        "order": 1,
                        "company": "Tech Startup Inc"
                      }
                    ],
                    "expiration_hours": 72
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Demande de signature cr\u00e9\u00e9e et envoy\u00e9e avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateAndSendResponse"
                },
                "example": {
                  "id": "550e8400-e29b-41d4-a716-446655440000",
                  "name": "Employment Contract - John Doe",
                  "description": "Contrat de travail \u00e0 temps plein",
                  "status": "sent",
                  "document_url": "https://storage.supabase.co/...",
                  "page_count": 3,
                  "expiration_hours": 168,
                  "settings": {
                    "use_signing_order": true,
                    "allow_download": true,
                    "attach_pdf_on_finish": true,
                    "send_signing_email": true,
                    "send_finish_email": true,
                    "send_expiration_email": true,
                    "send_cancellation_email": true,
                    "hand_drawn_only": false
                  },
                  "created_date": "2026-01-12T10:30:00Z",
                  "sent_date": "2026-01-12T10:30:00Z",
                  "template_id": null,
                  "first_signer": {
                    "id": "rec456-e89b-12d3-a456-426614174000",
                    "name": "John Doe",
                    "email": "john.doe@example.com",
                    "signing_link": "https://app.firma.dev/signing/rec456-e89b-12d3-a456-426614174000"
                  },
                  "recipients": [
                    {
                      "id": "rec456-e89b-12d3-a456-426614174000",
                      "first_name": "John",
                      "last_name": "Doe",
                      "name": "John Doe",
                      "email": "john.doe@example.com",
                      "designation": "Signer",
                      "order": 1
                    }
                  ],
                  "fields": [
                    {
                      "id": "field123-e89b-12d3-a456-426614174000",
                      "type": "signature",
                      "page": 1,
                      "x": 100,
                      "y": 500,
                      "width": 200,
                      "height": 50,
                      "required": true,
                      "recipient_id": "rec456-e89b-12d3-a456-426614174000"
                    }
                  ],
                  "credits_remaining": 99
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation - entr\u00e9e invalide ou donn\u00e9es de signataire obligatoires manquantes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateAndSendValidationError"
                },
                "examples": {
                  "missing-recipient-data": {
                    "value": {
                      "error": "One or more signers are missing required information for sending",
                      "phase": "send_validation",
                      "validation_errors": [
                        {
                          "recipient_index": 1,
                          "recipient_email": "john@example.com",
                          "missing_fields": [
                            "phone_number",
                            "company"
                          ]
                        }
                      ]
                    }
                  },
                  "invalid-document": {
                    "value": {
                      "error": "Document must be valid base64-encoded PDF",
                      "phase": "create_validation"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "402": {
            "description": "Cr\u00e9dits insuffisants",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InsufficientCreditsError"
                }
              }
            }
          },
          "404": {
            "description": "Mod\u00e8le introuvable ou n'appartenant pas \u00e0 l'espace de travail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "L'adresse e-mail du destinataire est suspendue (rejet pr\u00e9c\u00e9dent ou signal\u00e9e comme spam) et l'envoi est impossible",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnprocessableEntityError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "description": "Erreur serveur inattendue. Toute demande de signature partiellement cr\u00e9\u00e9e est annul\u00e9e, donc aucun brouillon n'est laiss\u00e9 derri\u00e8re. Les \u00e9checs actionnables c\u00f4t\u00e9 client lors de l'\u00e9tape d'envoi renvoient plut\u00f4t 400, 402 ou 422.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "operationId": "createAndSendSigningRequest",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.createAndSendSigningRequest({\n    \"name\": \"Employment Contract - John Doe\",\n    \"description\": \"Full-time employment contract\",\n    \"document\": \"JVBERi0xLjQKJeLjz9MK...\",\n    \"expiration_hours\": 168,\n    \"recipients\": [\n        {\n            \"id\": \"temp_signer_1\",\n            \"first_name\": \"John\",\n            \"last_name\": \"Doe\",\n            \"email\": \"john.doe@example.com\",\n            \"designation\": \"Signer\",\n            \"order\": 1,\n            \"phone_number\": \"+1-555-0123\",\n            \"company\": \"Acme Corp\",\n            \"title\": \"Software Engineer\"\n        }\n    ],\n    \"fields\": [\n        {\n            \"recipient_id\": \"temp_signer_1\",\n            \"type\": \"signature\",\n            \"page\": 1,\n            \"x\": 100,\n            \"y\": 500,\n            \"width\": 200,\n            \"height\": 50\n        },\n        {\n            \"recipient_id\": \"temp_signer_1\",\n            \"type\": \"text\",\n            \"page\": 1,\n            \"x\": 100,\n            \"y\": 400,\n            \"width\": 150,\n            \"height\": 30,\n            \"variable_name\": \"phone_number\",\n            \"required\": true,\n            \"read_only\": true\n        }\n    ],\n    \"settings\": {\n        \"use_signing_order\": true,\n        \"send_signing_email\": true\n    }\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{id}": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer une Demande de Signature",
        "description": "R\u00e9cup\u00e9rer une demande de signature sp\u00e9cifique par ID",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Demande de signature r\u00e9cup\u00e9r\u00e9e avec succ\u00e8s. Renvoie une structure imbriqu\u00e9e d\u00e9taill\u00e9e avec le statut sous forme d'objet et les horodatages regroup\u00e9s ensemble.",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningRequestDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "getSigningRequest",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.getSigningRequest({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "patch": {
        "summary": "Mettre \u00e0 Jour Partiellement une Demande de Signature",
        "description": "Mettre \u00e0 jour les propri\u00e9t\u00e9s de la demande de signature, un seul destinataire, OU un seul champ. Impossible de mettre \u00e0 jour plusieurs types d'entit\u00e9s dans une m\u00eame requ\u00eate. Impossible de mettre \u00e0 jour apr\u00e8s que la demande de signature a \u00e9t\u00e9 envoy\u00e9e, termin\u00e9e ou annul\u00e9e.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de la demande de signature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "description": "Mettre \u00e0 jour uniquement les propri\u00e9t\u00e9s de la demande de signature",
                    "properties": {
                      "name": {
                        "type": "string",
                        "maxLength": 255,
                        "description": "Nouveau nom pour la demande de signature"
                      },
                      "description": {
                        "type": "string",
                        "description": "Nouvelle description"
                      },
                      "document": {
                        "type": "string",
                        "format": "byte",
                        "description": "Remplace le document par un nouveau PDF encod\u00e9 en base64. Le nombre de pages est extrait automatiquement."
                      },
                      "expiration_hours": {
                        "type": "integer",
                        "minimum": 1,
                        "description": "Nouvelles heures d'expiration"
                      },
                      "settings": {
                        "$ref": "#/components/schemas/SigningRequestSettings",
                        "description": "Mettre \u00e0 jour les param\u00e8tres"
                      },
                      "language": {
                        "type": "string",
                        "nullable": true,
                        "enum": [
                          "en",
                          "es",
                          "it",
                          "pt",
                          "fr",
                          "de",
                          "el",
                          "ru",
                          "pl",
                          "cs",
                          "sv",
                          "nl",
                          "ro",
                          "nb"
                        ],
                        "description": "Langue facultative des e-mails pour cette demande de signature. Lorsqu'elle est d\u00e9finie, tous les e-mails destin\u00e9s au signataire (et le format de date) l'utilisent. Omettez-la ou utilisez null pour revenir \u00e0 la langue par d\u00e9faut de l'espace de travail, puis de l'entreprise (comportement inchang\u00e9)."
                      }
                    }
                  },
                  {
                    "type": "object",
                    "required": [
                      "recipient"
                    ],
                    "description": "Cr\u00e9er ou mettre \u00e0 jour un seul destinataire",
                    "properties": {
                      "recipient": {
                        "$ref": "#/components/schemas/Recipient",
                        "description": "Destinataire \u00e0 cr\u00e9er (omettre id) ou \u00e0 mettre \u00e0 jour (inclure id). Lors de la mise \u00e0 jour de first_name ou last_name, le champ name est automatiquement reconstruit \u00e0 partir des valeurs existantes en base de donn\u00e9es pour tout champ non fourni. R\u00e9sultat : 'First Last' si les deux existent, 'First' si seul first_name est pr\u00e9sent."
                      }
                    }
                  },
                  {
                    "type": "object",
                    "required": [
                      "field"
                    ],
                    "description": "Cr\u00e9er ou mettre \u00e0 jour un seul champ",
                    "properties": {
                      "field": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "Inclure pour mettre \u00e0 jour un champ existant, omettre pour en cr\u00e9er un nouveau"
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "text",
                              "signature",
                              "date",
                              "checkbox",
                              "initial",
                              "initials",
                              "dropdown",
                              "radio_buttons",
                              "textarea",
                              "text_area",
                              "url",
                              "file",
                              "stamp",
                              "approval_signature",
                              "approval_checkmark",
                              "approval_date"
                            ],
                            "description": "Type de champ. Accepte 'initial' ou 'initials', 'textarea' ou 'text_area'. Requis pour les nouveaux champs. Les champs url sont automatiquement en lecture seule. Les champs file permettent aux signataires de t\u00e9l\u00e9verser des pi\u00e8ces jointes (images/PDF). Les champs stamp affichent une image pr\u00e9configur\u00e9e."
                          },
                          "position": {
                            "type": "object",
                            "properties": {
                              "x": {
                                "type": "number",
                                "description": "Position X sur le document"
                              },
                              "y": {
                                "type": "number",
                                "description": "Position Y sur le document"
                              },
                              "width": {
                                "type": "number",
                                "description": "Largeur du champ"
                              },
                              "height": {
                                "type": "number",
                                "description": "Hauteur du champ"
                              }
                            },
                            "description": "Objet position. Toutes les propri\u00e9t\u00e9s sont requises pour les nouveaux champs."
                          },
                          "page_number": {
                            "type": "integer",
                            "minimum": 1,
                            "description": "Num\u00e9ro de page (index\u00e9 \u00e0 partir de 1). Requis pour les nouveaux champs."
                          },
                          "required": {
                            "type": "boolean",
                            "description": "Indique si le champ est requis"
                          },
                          "recipient_id": {
                            "type": "string",
                            "format": "uuid",
                            "nullable": true,
                            "description": "ID du destinataire auquel assigner le champ"
                          },
                          "variable_name": {
                            "type": "string",
                            "description": "Nom de variable pour le mappage des donn\u00e9es pr\u00e9remplies"
                          },
                          "variable_defined_name": {
                            "type": "string",
                            "maxLength": 100,
                            "nullable": true,
                            "description": "Nom lisible et personnalis\u00e9 de la d\u00e9finition du champ. Peut \u00eatre utilis\u00e9 comme alternative \u00e0 variable_name pour cibler des champs lors de la cr\u00e9ation \u00e0 partir d'un mod\u00e8le."
                          },
                          "dropdown_options": {
                            "description": "Options pour les champs de type liste d\u00e9roulante",
                            "oneOf": [
                              {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              {
                                "type": "object"
                              }
                            ]
                          },
                          "format_rules": {
                            "type": "object",
                            "description": "R\u00e8gles de format (ex. format de date, urlDisplayText pour les champs url, acceptedFileTypes pour les champs file)"
                          },
                          "validation_rules": {
                            "type": "object",
                            "description": "R\u00e8gles de validation pour le champ"
                          },
                          "multi_group_id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "ID de groupe pour les groupes de boutons radio"
                          },
                          "date_default": {
                            "type": "string",
                            "description": "Valeur de date par d\u00e9faut"
                          },
                          "date_signing_default": {
                            "type": "boolean",
                            "description": "Pour les champs de type date, utiliser la date de signature comme valeur par d\u00e9faut"
                          },
                          "read_only": {
                            "type": "boolean",
                            "description": "Indique si le champ est en lecture seule (automatiquement vrai pour les champs url)"
                          },
                          "read_only_value": {
                            "type": "string",
                            "description": "Valeur statique pour les champs en lecture seule. Pour les champs url, il s'agit de l'URL vers laquelle pointer le lien."
                          },
                          "final_value": {
                            "type": "string",
                            "description": "Valeur finale du champ (pour les champs pr\u00e9remplis en lecture seule)"
                          }
                        }
                      }
                    }
                  }
                ]
              },
              "examples": {
                "update-properties": {
                  "summary": "Mettre \u00e0 jour les propri\u00e9t\u00e9s",
                  "value": {
                    "name": "Updated Contract Name",
                    "expiration_hours": 72
                  }
                },
                "update-recipient": {
                  "summary": "Mettre \u00e0 jour un seul destinataire",
                  "value": {
                    "recipient": {
                      "id": "rec123-e89b-12d3-a456-426614174000",
                      "first_name": "John",
                      "last_name": "Smith",
                      "email": "john.smith@example.com",
                      "designation": "Signer",
                      "order": 1
                    }
                  }
                },
                "add-recipient": {
                  "summary": "Ajouter un nouveau destinataire",
                  "value": {
                    "recipient": {
                      "first_name": "Jane",
                      "last_name": "Doe",
                      "email": "jane@example.com",
                      "designation": "Signer",
                      "order": 2
                    }
                  }
                },
                "create-url-field": {
                  "summary": "Cr\u00e9er un champ URL",
                  "value": {
                    "field": {
                      "type": "url",
                      "position": {
                        "x": 100,
                        "y": 200,
                        "width": 150,
                        "height": 30
                      },
                      "page_number": 1,
                      "read_only_value": "https://example.com/terms",
                      "format_rules": {
                        "urlDisplayText": "View Terms & Conditions"
                      }
                    }
                  }
                },
                "create-file-field": {
                  "summary": "Cr\u00e9er un champ de t\u00e9l\u00e9versement de fichier",
                  "value": {
                    "field": {
                      "type": "file",
                      "position": {
                        "x": 100,
                        "y": 300,
                        "width": 200,
                        "height": 40
                      },
                      "page_number": 1,
                      "required": true,
                      "format_rules": {
                        "acceptedFileTypes": "image_and_pdf"
                      }
                    }
                  }
                },
                "update-field": {
                  "summary": "Mettre \u00e0 jour la position d'un champ existant",
                  "value": {
                    "field": {
                      "id": "field123-e89b-12d3-a456-426614174000",
                      "position": {
                        "x": 120,
                        "y": 220
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Demande de signature mise \u00e0 jour avec succ\u00e8s. La forme de la r\u00e9ponse d\u00e9pend de ce qui a \u00e9t\u00e9 mis \u00e0 jour : une mise \u00e0 jour des propri\u00e9t\u00e9s renvoie {id, name, template_description, document_url, expiration_hours} ; une mise \u00e0 jour de destinataire renvoie l'objet destinataire complet ; une mise \u00e0 jour de champ renvoie l'objet champ complet. La r\u00e9ponse peut inclure un champ 'warning' pour les avertissements de validation de format d'email (non bloquant).",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "description": "R\u00e9ponse lors de la mise \u00e0 jour des propri\u00e9t\u00e9s",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        },
                        "template_description": {
                          "type": "string",
                          "nullable": true
                        },
                        "document_url": {
                          "type": "string",
                          "format": "uri"
                        },
                        "expiration_hours": {
                          "type": "integer"
                        }
                      }
                    },
                    {
                      "type": "object",
                      "description": "R\u00e9ponse lors de la mise \u00e0 jour/cr\u00e9ation d'un destinataire"
                    },
                    {
                      "type": "object",
                      "description": "R\u00e9ponse lors de la mise \u00e0 jour/cr\u00e9ation d'un champ"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Requ\u00eate invalide - Impossible de mettre \u00e0 jour \u00e0 la fois les propri\u00e9t\u00e9s et le destinataire dans la m\u00eame requ\u00eate, ou la demande de signature a d\u00e9j\u00e0 \u00e9t\u00e9 envoy\u00e9e/compl\u00e9t\u00e9e/annul\u00e9e",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "cannot-update-sent": {
                    "value": {
                      "error": "Cannot update signing request",
                      "message": "Signing request has already been sent and cannot be modified"
                    }
                  },
                  "mixed-update": {
                    "value": {
                      "error": "Invalid request",
                      "message": "Cannot update both properties and recipient in the same request"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "patchSigningRequest",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.patchSigningRequest({\n    id: \"id\",\n    body: {\n        name: \"Updated Contract Name\",\n        expiration_hours: 72\n    }\n});\nconsole.log(response);"
          }
        ]
      },
      "put": {
        "summary": "Mise \u00e0 jour compl\u00e8te de la demande de signature",
        "description": "Effectue des mises \u00e0 jour compl\u00e8tes d'une demande de signature, y compris les propri\u00e9t\u00e9s, les destinataires, les champs et les rappels. Impossible de mettre \u00e0 jour apr\u00e8s que la demande de signature a \u00e9t\u00e9 envoy\u00e9e, compl\u00e9t\u00e9e ou annul\u00e9e. Toutes les sections sont optionnelles, mais au moins une doit \u00eatre fournie.\n\n**Mod\u00e8le d'ID temporaire pour les nouveaux destinataires** : lors de l'ajout de nouveaux destinataires dans une mise \u00e0 jour compl\u00e8te, utilisez le champ '_temp_id' (format : 'temp_X') au lieu de 'id' pour \u00e9tablir des relations avec les champs et les rappels. Cela permet de cr\u00e9er de nouveaux destinataires et de les r\u00e9f\u00e9rencer dans les champs/rappels en une seule requ\u00eate. Utilisez le champ 'id' pour mettre \u00e0 jour des destinataires existants. R\u00e8gles de validation : (1) les ID temporaires doivent commencer par 'temp_' ; (2) chaque ID temporaire doit \u00eatre unique au sein de la requ\u00eate ; (3) les champs et rappels peuvent r\u00e9f\u00e9rencer des ID temporaires dans leur propri\u00e9t\u00e9 recipient_id ; (4) l'API r\u00e9sout automatiquement les ID temporaires en v\u00e9ritables UUID apr\u00e8s la cr\u00e9ation du destinataire.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de la demande de signature"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/UpdateSigningRequestBody"
        },
        "responses": {
          "200": {
            "description": "Demande de signature mise \u00e0 jour avec succ\u00e8s. Renvoie la demande de signature mise \u00e0 jour et un r\u00e9sum\u00e9 des modifications effectu\u00e9es.",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningRequestUpdateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Erreurs de validation. Toutes les erreurs de section sont renvoy\u00e9es ensemble.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningRequestUpdateError"
                },
                "example": {
                  "error": "Validation failed",
                  "message": "Multiple validation errors occurred",
                  "details": {
                    "recipients": [
                      "Recipient 1: email is invalid"
                    ],
                    "deleted_recipients": [
                      "Cannot reassign: designations must match"
                    ],
                    "fields": [
                      "Field 2: x coordinate must be between 0 and 100"
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "updateSigningRequest",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.updateSigningRequest({\n    id: \"id\",\n    signing_request_properties: {\n        name: \"Updated Contract Name\",\n        expiration_hours: 72\n    },\n    recipients: [{\n            id: \"rec1-e89b-12d3-a456-426614174000\",\n            first_name: \"John\",\n            last_name: \"Smith\",\n            email: \"john.smith@example.com\",\n            designation: \"Signer\",\n            order: 1\n        }, {\n            first_name: \"Jane\",\n            last_name: \"Doe\",\n            email: \"jane@example.com\",\n            designation: \"Signer\",\n            order: 2\n        }],\n    deleted_recipients: [{\n            recipient_id: \"rec2-e89b-12d3-a456-426614174000\",\n            field_action: \"reassign\",\n            reassign_to_recipient_id: \"rec1-e89b-12d3-a456-426614174000\"\n        }],\n    fields: [{\n            id: \"field1-e89b-12d3-a456-426614174000\",\n            type: \"signature\",\n            position: {\n                x: 15,\n                y: 85,\n                width: 30,\n                height: 10\n            },\n            page_number: 1,\n            required: true,\n            recipient_id: \"rec1-e89b-12d3-a456-426614174000\"\n        }],\n    reminders: [{\n            hours: 48,\n            all_users: true,\n            subject: \"Reminder: Please sign the document\",\n            message: \"This is a reminder to complete your signature.\"\n        }]\n});\nconsole.log(response);"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer une demande de signature",
        "description": "Supprime une demande de signature non envoy\u00e9e (brouillon). Seules les demandes de signature qui n'ont pas \u00e9t\u00e9 envoy\u00e9es peuvent \u00eatre supprim\u00e9es. Pour les demandes de signature envoy\u00e9es, utilise plut\u00f4t le endpoint d'annulation.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de la demande de signature"
          }
        ],
        "responses": {
          "200": {
            "description": "Demande de signature supprim\u00e9e avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningRequestDeleteResponse"
                },
                "example": {
                  "message": "Signing request deleted successfully",
                  "signing_request_id": "550e8400-e29b-41d4-a716-446655440000",
                  "deleted_on": "2026-05-30T10:00:00.000Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "409": {
            "description": "Impossible de supprimer une demande de signature qui a \u00e9t\u00e9 envoy\u00e9e",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Cannot delete a signing request that has been sent. Use cancel instead.",
                  "code": "ALREADY_SENT"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "deleteSigningRequest",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.deleteSigningRequest({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{id}/users": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer les utilisateurs d'une demande de signature",
        "description": "R\u00e9cup\u00e8re tous les destinataires/utilisateurs d'une demande de signature sp\u00e9cifique",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de la demande de signature",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Utilisateurs de la demande de signature r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de r\u00e9initialisation de la limite de d\u00e9bit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningRequestUserListResponse"
                },
                "example": {
                  "results": [
                    {
                      "id": "user123-e89b-12d3-a456-426614174000",
                      "name": "Alice Johnson",
                      "email": "alice@example.com",
                      "first_name": "Alice",
                      "last_name": "Johnson",
                      "designation": "Signer",
                      "order": 1,
                      "finished_on": "2024-03-15T14:30:00Z",
                      "declined_on": null,
                      "decline_reason": null,
                      "phone_number": "+1-555-0101",
                      "street_address": null,
                      "city": null,
                      "state_province": null,
                      "postal_code": null,
                      "country": null,
                      "title": "PDG",
                      "company": "Acme Corp",
                      "custom_fields": null,
                      "required_fields": [
                        "email",
                        "first_name"
                      ],
                      "missing_fields": [],
                      "required_read_only_fields": [],
                      "ready_to_send": true
                    },
                    {
                      "id": "user456-e89b-12d3-a456-426614174000",
                      "name": "Bob Williams",
                      "email": "bob@example.com",
                      "first_name": "Bob",
                      "last_name": "Williams",
                      "designation": "Signer",
                      "order": 2,
                      "finished_on": null,
                      "declined_on": null,
                      "decline_reason": null,
                      "phone_number": null,
                      "street_address": null,
                      "city": null,
                      "state_province": null,
                      "postal_code": null,
                      "country": null,
                      "title": null,
                      "company": null,
                      "custom_fields": null,
                      "required_fields": [
                        "email",
                        "first_name",
                        "phone_number"
                      ],
                      "missing_fields": [
                        "phone_number"
                      ],
                      "required_read_only_fields": [
                        {
                          "variable_name": "contract_amount",
                          "field_type": "number",
                          "has_value": false
                        }
                      ],
                      "ready_to_send": false
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listSigningRequestUsers",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.listSigningRequestUsers({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{id}/fields": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer les champs d'une demande de signature",
        "description": "R\u00e9cup\u00e8re tous les champs d'une demande de signature sp\u00e9cifique avec leurs valeurs",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de la demande de signature",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Champs de la demande de signature r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de r\u00e9initialisation de la limite de d\u00e9bit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningRequestFieldListResponse"
                },
                "example": {
                  "results": [
                    {
                      "id": "field789-e89b-12d3-a456-426614174000",
                      "type": "signature",
                      "recipient_id": "user456-e89b-12d3-a456-426614174000",
                      "required": true,
                      "read_only": false,
                      "value": "data:image/png;base64,iVBOR...",
                      "position": {
                        "x": 100.5,
                        "y": 200.75,
                        "width": 200,
                        "height": 50
                      },
                      "page_number": 1,
                      "variable_name": null,
                      "variable_defined_name": null,
                      "companies_workspaces_signing_requests_id": "sr123-e89b-12d3-a456-426614174000",
                      "companies_workspaces_signing_requests_users_id": "user456-e89b-12d3-a456-426614174000",
                      "field_type": "signature",
                      "x_postion": 100.5,
                      "y_position": 200.75,
                      "width": 200,
                      "heigh": 50,
                      "final_value": "data:image/png;base64,iVBOR...",
                      "deleted": 0
                    },
                    {
                      "id": "field012-e89b-12d3-a456-426614174000",
                      "type": "text",
                      "recipient_id": "user456-e89b-12d3-a456-426614174000",
                      "required": true,
                      "read_only": false,
                      "value": "Alice Johnson",
                      "position": {
                        "x": 150,
                        "y": 300,
                        "width": 250,
                        "height": 30
                      },
                      "page_number": 1,
                      "variable_name": "full_name",
                      "variable_defined_name": null,
                      "companies_workspaces_signing_requests_id": "sr123-e89b-12d3-a456-426614174000",
                      "companies_workspaces_signing_requests_users_id": "user456-e89b-12d3-a456-426614174000",
                      "field_type": "text",
                      "x_postion": 150,
                      "y_position": 300,
                      "width": 250,
                      "heigh": 30,
                      "final_value": "Alice Johnson",
                      "deleted": 0
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listSigningRequestFields",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.listSigningRequestFields({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{id}/reminders": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer les rappels d'une demande de signature",
        "description": "R\u00e9cup\u00e8re tous les rappels programm\u00e9s pour une demande de signature sp\u00e9cifique",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de la demande de signature",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rappels de la demande de signature r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de r\u00e9initialisation de la limite de d\u00e9bit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Reminder"
                  }
                },
                "example": [
                  {
                    "id": "remind789-e89b-12d3-a456-426614174000",
                    "hours": 48,
                    "subject": "Urgent: Document signature required",
                    "message": "Please complete your signature at your earliest convenience.",
                    "all_users": false,
                    "template_user_id": "user456-e89b-12d3-a456-426614174000",
                    "date_created": "2024-03-10T09:00:00Z",
                    "date_changed": "2024-03-10T09:00:00Z"
                  }
                ]
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listSigningRequestReminders",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.listSigningRequestReminders({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{id}/audit": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer la piste d'audit d'une demande de signature",
        "description": "R\u00e9cup\u00e8re la piste d'audit compl\u00e8te d'une demande de signature, combinant les actions admin (cr\u00e9\u00e9e, modifi\u00e9e, envoy\u00e9e, annul\u00e9e) et les actions du signataire (consult\u00e9e, sign\u00e9e, refus\u00e9e, t\u00e9l\u00e9charg\u00e9e). Les \u00e9v\u00e9nements sont tri\u00e9s chronologiquement.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de la demande de signature"
          }
        ],
        "responses": {
          "200": {
            "description": "Piste d'audit r\u00e9cup\u00e9r\u00e9e avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditTrailListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listSigningRequestAuditTrail",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.listSigningRequestAuditTrail({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{id}/send": {
      "post": {
        "summary": "Envoyer une demande de signature",
        "description": "Envoie une demande de signature \u00e0 tous les destinataires par email. Ceci d\u00e9clenche l'envoi de l'email et d\u00e9finit le timestamp sent_on.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de la demande de signature",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Demande de signature envoy\u00e9e avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 60 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de r\u00e9initialisation de la limite de d\u00e9bit"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendSigningRequestResponse"
                },
                "example": {
                  "message": "Signing request sent successfully",
                  "signing_request_id": "123e4567-e89b-12d3-a456-426614174000",
                  "recipients_notified": 3,
                  "sent_date": "2024-03-20T10:15:00Z",
                  "expires_at": "2024-04-20T10:15:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Requ\u00eate invalide - La demande de signature a d\u00e9j\u00e0 \u00e9t\u00e9 envoy\u00e9e ou a expir\u00e9",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "alreadySent": {
                    "value": {
                      "error": "Bad Request",
                      "message": "Signing request has already been sent"
                    }
                  },
                  "expired": {
                    "value": {
                      "error": "Bad Request",
                      "message": "Signing request has expired"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "sendSigningRequest",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.sendSigningRequest({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{id}/cancel": {
      "post": {
        "summary": "Annuler une demande de signature",
        "description": "Annule une demande de signature qui n'a pas encore \u00e9t\u00e9 compl\u00e9t\u00e9e. Ne peut annuler que les demandes qui ont \u00e9t\u00e9 envoy\u00e9es et qui ne sont pas d\u00e9j\u00e0 termin\u00e9es ou annul\u00e9es.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de la demande de signature"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Raison d'annulation optionnelle"
                  },
                  "notify_signers": {
                    "type": "boolean",
                    "default": true,
                    "description": "Si les signataires doivent \u00eatre notifi\u00e9s de l'annulation"
                  }
                }
              },
              "example": {
                "reason": "No longer needed",
                "notify_signers": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Demande de signature annul\u00e9e avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelSigningRequestResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "409": {
            "description": "Impossible d'annuler (d\u00e9j\u00e0 annul\u00e9e, termin\u00e9e, ou pas encore envoy\u00e9e)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "cancelSigningRequest",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.cancelSigningRequest({\n    id: \"id\",\n    reason: \"No longer needed\",\n    notify_signers: true\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{id}/resend": {
      "post": {
        "summary": "Renvoyer une demande de signature \u00e0 des destinataires sp\u00e9cifiques",
        "description": "Renvoie les notifications de la demande de signature \u00e0 un ou plusieurs destinataires actuellement \u00e9ligibles pour signer. Pour les demandes avec l'ordre de signature activ\u00e9, ne peut renvoyer qu'aux destinataires \u00e0 l'ordre actif actuel. Impossible de renvoyer aux destinataires ayant d\u00e9j\u00e0 sign\u00e9.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de la demande de signature"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "recipient_ids"
                ],
                "properties": {
                  "recipient_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "Tableau des ID utilisateur des destinataires \u00e0 qui renvoyer",
                    "minItems": 1
                  },
                  "custom_message": {
                    "type": "string",
                    "maxLength": 1000,
                    "description": "Message personnalis\u00e9 optionnel \u00e0 inclure dans la notification de renvoi"
                  }
                }
              },
              "example": {
                "recipient_ids": [
                  "123e4567-e89b-12d3-a456-426614174000"
                ],
                "custom_message": "Gentle reminder to complete your signature"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Demande de signature renvoy\u00e9e avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResendSigningRequestResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "409": {
            "description": "Impossible de renvoyer (destinataires ayant d\u00e9j\u00e0 sign\u00e9, ordre de signature invalide, ou demande pas envoy\u00e9e/annul\u00e9e/termin\u00e9e)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResendConflictError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "resendSigningRequest",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.resendSigningRequest({\n    id: \"id\",\n    recipient_ids: [\"123e4567-e89b-12d3-a456-426614174000\"],\n    custom_message: \"Gentle reminder to complete your signature\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/webhooks": {
      "get": {
        "summary": "Lister les Webhooks",
        "description": "R\u00e9cup\u00e8re une liste pagin\u00e9e des webhooks",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "description": "Num\u00e9ro de page"
          },
          {
            "name": "page_size",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "description": "\u00c9l\u00e9ments par page"
          },
          {
            "name": "enabled",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ]
            },
            "description": "Filtrer par statut activ\u00e9 (0=d\u00e9sactiv\u00e9, 1=activ\u00e9)"
          },
          {
            "name": "url",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrer par URL du webhook (correspondance partielle, insensible \u00e0 la casse)"
          },
          {
            "name": "event",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtrer par type d'\u00e9v\u00e9nement (par ex., 'signing_request.completed')"
          },
          {
            "name": "created_after",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Filtrer les webhooks cr\u00e9\u00e9s apr\u00e8s cette date (format ISO 8601)"
          },
          {
            "name": "created_before",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Filtrer les webhooks cr\u00e9\u00e9s avant cette date (format ISO 8601)"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "url",
                "enabled",
                "created_on",
                "last_changed_on",
                "consecutive_failures"
              ],
              "default": "created_on"
            },
            "description": "Champ selon lequel trier"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Ordre de tri"
          },
          {
            "name": "workspace_id",
            "in": "query",
            "description": "Filtrer les webhooks par espace de travail. Si fourni, ne renvoie que les webhooks limit\u00e9s \u00e0 cet espace de travail. Si omis, ne renvoie que les webhooks au niveau de l'entreprise.",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhooks r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation - format de date ou param\u00e8tres de tri invalides",
            "content": {
              "application/json": {
                "examples": {
                  "invalidDate": {
                    "summary": "Format de date invalide",
                    "value": {
                      "error": "Validation failed",
                      "code": "VALIDATION_ERROR",
                      "details": [
                        {
                          "path": [
                            "created_before"
                          ],
                          "message": "created_before must be a valid ISO 8601 date"
                        }
                      ]
                    }
                  },
                  "invalidSort": {
                    "summary": "Param\u00e8tre de tri invalide",
                    "value": {
                      "error": "Validation failed",
                      "code": "VALIDATION_ERROR",
                      "details": [
                        {
                          "path": [
                            "sort_by"
                          ],
                          "message": "Invalid sort field"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listWebhooks",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.webhooks.listWebhooks();\nconsole.log(response);"
          }
        ]
      },
      "post": {
        "summary": "Cr\u00e9er un webhook",
        "description": "Cr\u00e9er un nouveau webhook",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "events"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "workspace_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "ID d'espace de travail optionnel. Si fourni, cr\u00e9e un webhook au niveau de l'espace de travail. Si omis, cr\u00e9e un webhook au niveau de l'entreprise."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook cr\u00e9\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 60 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "createWebhook",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.webhooks.createWebhook({\n    url: \"url\",\n    events: [\"events\"]\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/webhooks/{id}": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer un webhook",
        "description": "R\u00e9cup\u00e9rer un webhook sp\u00e9cifique par ID",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook r\u00e9cup\u00e9r\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "getWebhook",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.webhooks.getWebhook({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "put": {
        "summary": "Mettre \u00e0 jour un webhook",
        "description": "Mettre \u00e0 jour un webhook existant",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook mis \u00e0 jour avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 60 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "updateWebhook",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.webhooks.updateWebhook({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer un webhook",
        "description": "Supprimer (soft delete) un webhook par ID. \u00c7a marque le webhook comme supprim\u00e9 mais conserve les donn\u00e9es.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID du webhook",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook supprim\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 60 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de la r\u00e9initialisation de la limite de requ\u00eates"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                },
                "example": {
                  "message": "Webhook deleted successfully"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "deleteWebhook",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.webhooks.deleteWebhook({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "summary": "Tester un webhook",
        "description": "Envoyer un payload de test \u00e0 l'URL du webhook pour v\u00e9rifier qu'il fonctionne correctement",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID du webhook",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook de test envoy\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 10 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de la r\u00e9initialisation de la limite de requ\u00eates"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestWebhookResponse"
                },
                "example": {
                  "success": true,
                  "status_code": 200,
                  "webhook_event_id": "123e4567-e89b-12d3-a456-426614174000",
                  "message": "Test webhook delivered successfully",
                  "headers_sent": {
                    "X-Firma-Event": "webhook.test",
                    "X-Firma-Signature": "Generated HMAC-SHA256 signature",
                    "X-Firma-Delivery": "123e4567-e89b-12d3-a456-426614174000"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "testWebhook",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.webhooks.testWebhook({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/webhooks/rotate-secret": {
      "post": {
        "summary": "Faire tourner le secret de signature du webhook",
        "description": "G\u00e9n\u00e8re un nouveau secret de signature de webhook pour l'entreprise. L'ancien secret reste valide pendant 7 jours pour permettre une migration en douceur. Limit\u00e9 \u00e0 1 requ\u00eate par minute.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Secret chang\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 1 requ\u00eate par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RotateSecretResponse"
                },
                "example": {
                  "message": "Webhook secret rotated successfully",
                  "new_secret": "a1b2c3d4e5f6...",
                  "grace_period_hours": 168,
                  "warning": "Update your webhook signature verification to use the new secret. The old secret will remain valid for 7 days."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "description": "Limite de requ\u00eates d\u00e9pass\u00e9e (1 rotation par minute)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "operationId": "rotateWebhookSecret",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.webhooks.rotateWebhookSecret();\nconsole.log(response);"
          }
        ]
      }
    },
    "/webhooks/secret-status": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer le statut de rotation du secret du webhook",
        "description": "Renvoie des infos sur le secret de webhook actuel, incluant le statut de rotation et l'expiration de l'ancien secret le cas \u00e9ch\u00e9ant.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Statut du secret r\u00e9cup\u00e9r\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretStatusResponse"
                },
                "example": {
                  "created_at": "2025-09-01T10:00:00Z",
                  "last_rotated_at": "2025-10-16T12:00:00Z",
                  "grace_period_active": true,
                  "grace_period_ends_at": "2025-10-23T12:00:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "description": "Aucune configuration de webhook trouv\u00e9e",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "getWebhookSecretStatus",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.webhooks.getWebhookSecretStatus();\nconsole.log(response);"
          }
        ]
      }
    },
    "/generate-template-token": {
      "post": {
        "summary": "G\u00e9n\u00e9rer un token JWT pour int\u00e9grer des mod\u00e8les",
        "description": "Cr\u00e9e un token JWT pour int\u00e9grer un mod\u00e8le, avec une expiration de 24 heures. C'est l'endpoint standard pour la g\u00e9n\u00e9ration de JWT.\n\n**Remarque** : la fonction autonome `generate-embedded-template-token` est d\u00e9pr\u00e9ci\u00e9e au profit de cet endpoint bas\u00e9 sur le routeur.",
        "tags": [
          "JWT Management"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateJWTRequest"
              },
              "example": {
                "companies_workspaces_templates_id": "123e4567-e89b-12d3-a456-426614174000"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "JWT g\u00e9n\u00e9r\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de la r\u00e9initialisation de la limite de requ\u00eates"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateTemplateTokenResponse"
                },
                "example": {
                  "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
                  "expires_at": "2024-04-20T10:00:00Z",
                  "jwt_record_id": "jwt123-e89b-12d3-a456-426614174000"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "generateTemplateToken",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.jwtManagement.generateTemplateToken({\n    companies_workspaces_templates_id: \"123e4567-e89b-12d3-a456-426614174000\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/revoke-template-token": {
      "post": {
        "summary": "R\u00e9voquer un token JWT de mod\u00e8le",
        "description": "R\u00e9voquer un token JWT g\u00e9n\u00e9r\u00e9 pr\u00e9c\u00e9demment, pour l'emp\u00eacher d'\u00eatre utilis\u00e9 pour l'int\u00e9gration de mod\u00e8les. C'est l'endpoint standard pour r\u00e9voquer les JWT de mod\u00e8les.",
        "tags": [
          "JWT Management"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevokeJWTRequest"
              },
              "example": {
                "jwt_id": "123e4567-e89b-12d3-a456-426614174000"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JWT r\u00e9voqu\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de la r\u00e9initialisation de la limite de requ\u00eates"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevokeJWTResponse"
                },
                "example": {
                  "message": "JWT revoked successfully",
                  "jwt_id": "123e4567-e89b-12d3-a456-426614174000",
                  "revoked_at": "2024-03-20T16:45:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Requ\u00eate invalide - JWT d\u00e9j\u00e0 r\u00e9voqu\u00e9 ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "alreadyRevoked": {
                    "value": {
                      "error": "Bad Request",
                      "message": "JWT has already been revoked"
                    }
                  },
                  "invalidJwt": {
                    "value": {
                      "error": "Bad Request",
                      "message": "Invalid JWT ID"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "revokeTemplateToken",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.jwtManagement.revokeTemplateToken({\n    jwt_id: \"123e4567-e89b-12d3-a456-426614174000\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/jwt/generate-signing-request": {
      "post": {
        "summary": "G\u00e9n\u00e9rer un token JWT pour une demande de signature",
        "description": "G\u00e9n\u00e8re un token JWT pour int\u00e9grer un \u00e9diteur de demande de signature. Le JWT expire apr\u00e8s 7 jours.",
        "tags": [
          "JWT Management"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateSigningRequestJWTRequest"
              },
              "example": {
                "companies_workspaces_signing_requests_id": "123e4567-e89b-12d3-a456-426614174000"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JWT g\u00e9n\u00e9r\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de la r\u00e9initialisation de la limite de requ\u00eates"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateSigningRequestJWTResponse"
                },
                "example": {
                  "jwt": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
                  "jwt_id": "jwt123-e89b-12d3-a456-426614174000",
                  "expires_at": "2024-03-27T10:00:00Z",
                  "signing_request_id": "123e4567-e89b-12d3-a456-426614174000"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "generateSigningRequestToken",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.jwtManagement.generateSigningRequestToken({\n    companies_workspaces_signing_requests_id: \"123e4567-e89b-12d3-a456-426614174000\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/jwt/revoke-signing-request": {
      "post": {
        "summary": "R\u00e9voquer un token JWT de demande de signature",
        "description": "R\u00e9voquer un token JWT g\u00e9n\u00e9r\u00e9 pr\u00e9c\u00e9demment pour une demande de signature, pour l'emp\u00eacher d'\u00eatre utilis\u00e9 pour l'\u00e9dition int\u00e9gr\u00e9e",
        "tags": [
          "JWT Management"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevokeSigningRequestJWTRequest"
              },
              "example": {
                "jwt_id": "123e4567-e89b-12d3-a456-426614174000"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JWT r\u00e9voqu\u00e9 avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de requ\u00eates : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                },
                "description": "Requ\u00eates restantes dans la fen\u00eatre actuelle"
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                },
                "description": "Timestamp Unix de la r\u00e9initialisation de la limite de requ\u00eates"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevokeSigningRequestJWTResponse"
                },
                "example": {
                  "message": "JWT revoked successfully",
                  "jwt_id": "123e4567-e89b-12d3-a456-426614174000",
                  "revoked_at": "2024-03-20T16:45:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Requ\u00eate invalide - JWT d\u00e9j\u00e0 r\u00e9voqu\u00e9 ou invalide",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "alreadyRevoked": {
                    "value": {
                      "error": "Bad Request",
                      "message": "JWT has already been revoked"
                    }
                  },
                  "invalidJwt": {
                    "value": {
                      "error": "Bad Request",
                      "message": "Invalid JWT ID"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "revokeSigningRequestToken",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.jwtManagement.revokeSigningRequestToken({\n    jwt_id: \"123e4567-e89b-12d3-a456-426614174000\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspace/{workspace_id}/email-templates": {
      "get": {
        "summary": "Lister les mod\u00e8les d'e-mail de l'espace de travail",
        "description": "R\u00e9cup\u00e9rer tous les mod\u00e8les d'e-mail personnalis\u00e9s d'un espace de travail",
        "tags": [
          "Email Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          }
        ],
        "responses": {
          "200": {
            "description": "Mod\u00e8les d'e-mail r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceEmailTemplateListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listWorkspaceEmailTemplates",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailTemplates.listWorkspaceEmailTemplates({\n    workspace_id: \"workspace_id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspace/{workspace_id}/email-templates/{email_type}": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer un mod\u00e8le d'e-mail de l'espace de travail",
        "description": "R\u00e9cup\u00e9rer un mod\u00e8le d'e-mail sp\u00e9cifique par type pour un espace de travail",
        "tags": [
          "Email Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          },
          {
            "name": "email_type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "signing_invite",
                "next_signer",
                "signing_expired",
                "signing_cancelled",
                "signing_declined"
              ]
            },
            "description": "Type de mod\u00e8le d'e-mail"
          }
        ],
        "responses": {
          "200": {
            "description": "Mod\u00e8le d'e-mail r\u00e9cup\u00e9r\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailTemplate"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "getWorkspaceEmailTemplate",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailTemplates.getWorkspaceEmailTemplate({\n    workspace_id: \"workspace_id\",\n    email_type: \"signing_invite\"\n});\nconsole.log(response);"
          }
        ]
      },
      "put": {
        "summary": "Cr\u00e9er ou mettre \u00e0 jour un mod\u00e8le d'e-mail de l'espace de travail",
        "description": "Cr\u00e9er ou mettre \u00e0 jour un mod\u00e8le d'e-mail personnalis\u00e9 pour un type sp\u00e9cifique. Si un mod\u00e8le existe d\u00e9j\u00e0 pour ce type, il sera mis \u00e0 jour. Un avertissement est renvoy\u00e9 si le corps du mod\u00e8le ne contient pas {{signing_link}}.",
        "tags": [
          "Email Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          },
          {
            "name": "email_type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "signing_invite",
                "next_signer",
                "signing_expired",
                "signing_cancelled",
                "signing_declined"
              ]
            },
            "description": "Type de mod\u00e8le d'e-mail"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "subject",
                  "body"
                ],
                "properties": {
                  "subject": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Ligne d'objet de l'e-mail"
                  },
                  "body": {
                    "type": "string",
                    "maxLength": 50000,
                    "description": "Corps de l'e-mail (HTML). Utilisez le placeholder {{signing_link}} pour l'URL de signature."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mod\u00e8le d'e-mail mis \u00e0 jour avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/EmailTemplate"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Mod\u00e8le d'email cr\u00e9\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/EmailTemplate"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "updateWorkspaceEmailTemplate",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailTemplates.updateWorkspaceEmailTemplate({\n    workspace_id: \"workspace_id\",\n    email_type: \"signing_invite\",\n    subject: \"subject\",\n    body: \"body\"\n});\nconsole.log(response);"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer le mod\u00e8le d'email de l'espace de travail",
        "description": "Supprime un mod\u00e8le d'email personnalis\u00e9. L'espace de travail reviendra \u00e0 l'utilisation du mod\u00e8le au niveau de l'entreprise ou du mod\u00e8le par d\u00e9faut pour ce type.",
        "tags": [
          "Email Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          },
          {
            "name": "email_type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "signing_invite",
                "next_signer",
                "signing_expired",
                "signing_cancelled",
                "signing_declined"
              ]
            },
            "description": "Type de mod\u00e8le d'email"
          }
        ],
        "responses": {
          "200": {
            "description": "Mod\u00e8le d'email supprim\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailTemplateDeleteResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "deleteWorkspaceEmailTemplate",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailTemplates.deleteWorkspaceEmailTemplate({\n    workspace_id: \"workspace_id\",\n    email_type: \"signing_invite\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/company/email-templates": {
      "get": {
        "summary": "Lister les mod\u00e8les d'email de l'entreprise",
        "description": "R\u00e9cup\u00e8re tous les mod\u00e8les d'email personnalis\u00e9s au niveau de l'entreprise. Les mod\u00e8les d'entreprise servent de valeurs par d\u00e9faut pour tous les espaces de travail qui n'ont pas de mod\u00e8les sp\u00e9cifiques.",
        "tags": [
          "Email Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Mod\u00e8les d'email de l'entreprise r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyEmailTemplateListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listCompanyEmailTemplates",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailTemplates.listCompanyEmailTemplates();\nconsole.log(response);"
          }
        ]
      }
    },
    "/company/email-templates/{email_type}": {
      "put": {
        "summary": "Cr\u00e9er ou mettre \u00e0 jour le mod\u00e8le d'email de l'entreprise",
        "description": "Cr\u00e9e ou met \u00e0 jour un mod\u00e8le d'email au niveau de l'entreprise pour un type sp\u00e9cifique. Les mod\u00e8les d'entreprise sont utilis\u00e9s comme valeurs par d\u00e9faut pour les espaces de travail sans mod\u00e8les sp\u00e9cifiques.",
        "tags": [
          "Email Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "email_type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "signing_invite",
                "next_signer",
                "signing_expired",
                "signing_cancelled",
                "signing_declined"
              ]
            },
            "description": "Type de mod\u00e8le d'email"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "subject",
                  "body"
                ],
                "properties": {
                  "subject": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Ligne d'objet de l'email"
                  },
                  "body": {
                    "type": "string",
                    "maxLength": 50000,
                    "description": "Corps de l'email (HTML). Utilisez le placeholder {{signing_link}} pour l'URL de signature."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mod\u00e8le d'email de l'entreprise mis \u00e0 jour avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/EmailTemplate"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Mod\u00e8le d'email de l'entreprise cr\u00e9\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/EmailTemplate"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "updateCompanyEmailTemplate",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailTemplates.updateCompanyEmailTemplate({\n    email_type: \"signing_invite\",\n    subject: \"subject\",\n    body: \"body\"\n});\nconsole.log(response);"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer le mod\u00e8le d'email de l'entreprise",
        "description": "Supprime un mod\u00e8le d'email au niveau de l'entreprise. Les espaces de travail reviendront au mod\u00e8le par d\u00e9faut int\u00e9gr\u00e9 pour ce type.",
        "tags": [
          "Email Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "email_type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "signing_invite",
                "next_signer",
                "signing_expired",
                "signing_cancelled",
                "signing_declined"
              ]
            },
            "description": "Type de mod\u00e8le d'email"
          }
        ],
        "responses": {
          "200": {
            "description": "Mod\u00e8le d'email de l'entreprise supprim\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailTemplateDeleteResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "deleteCompanyEmailTemplate",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailTemplates.deleteCompanyEmailTemplate({\n    email_type: \"signing_invite\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/company/signer-terms": {
      "get": {
        "summary": "Lister les conditions signataire de l'entreprise",
        "description": "R\u00e9cup\u00e8re toutes les conditions signataire au niveau de l'entreprise. Les conditions signataire de l'entreprise servent de valeurs par d\u00e9faut pour les espaces de travail sans conditions sp\u00e9cifiques.",
        "tags": [
          "Signer Terms"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Conditions signataire de l'entreprise r\u00e9cup\u00e9r\u00e9es avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignerTermsListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listCompanySignerTerms",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signerTerms.listCompanySignerTerms();\nconsole.log(response);"
          }
        ]
      }
    },
    "/company/signer-terms/{language}": {
      "put": {
        "summary": "Cr\u00e9er ou mettre \u00e0 jour les conditions signataire de l'entreprise",
        "description": "Cr\u00e9e ou met \u00e0 jour les conditions signataire au niveau de l'entreprise pour une langue sp\u00e9cifique. La d\u00e9claration soumise est nettoy\u00e9e avant stockage.",
        "tags": [
          "Signer Terms"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "language",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es",
                "it",
                "pt",
                "fr",
                "de",
                "el",
                "ru",
                "pl",
                "cs",
                "sv",
                "nl",
                "ro",
                "nb"
              ]
            },
            "description": "Code de langue"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "statement_text"
                ],
                "properties": {
                  "statement_text": {
                    "type": "string",
                    "description": "D\u00e9claration de consentement du signataire au format HTML. Nettoy\u00e9e avant stockage."
                  },
                  "terms_url": {
                    "type": "string",
                    "format": "uri",
                    "nullable": true,
                    "description": "Lien externe optionnel vers les conditions"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conditions signataire de l'entreprise mises \u00e0 jour avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignerTermsUpdateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "updateCompanySignerTerms",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signerTerms.updateCompanySignerTerms({\n    language: \"en\",\n    statement_text: \"statement_text\"\n});\nconsole.log(response);"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer les conditions signataire de l'entreprise",
        "description": "Supprime les conditions signataire au niveau de l'entreprise pour une langue sp\u00e9cifique.",
        "tags": [
          "Signer Terms"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "language",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es",
                "it",
                "pt",
                "fr",
                "de",
                "el",
                "ru",
                "pl",
                "cs",
                "sv",
                "nl",
                "ro",
                "nb"
              ]
            },
            "description": "Code de langue"
          }
        ],
        "responses": {
          "200": {
            "description": "Conditions signataire de l'entreprise supprim\u00e9es avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignerTermsDeleteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "deleteCompanySignerTerms",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signerTerms.deleteCompanySignerTerms({\n    language: \"en\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspace/{workspace_id}/signer-terms": {
      "get": {
        "summary": "Lister les conditions signataire de l'espace de travail",
        "description": "R\u00e9cup\u00e8re toutes les conditions signataire personnalis\u00e9es d'un espace de travail",
        "tags": [
          "Signer Terms"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          }
        ],
        "responses": {
          "200": {
            "description": "Conditions signataire de l'espace de travail r\u00e9cup\u00e9r\u00e9es avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignerTermsListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listWorkspaceSignerTerms",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signerTerms.listWorkspaceSignerTerms({\n    workspace_id: \"workspace_id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspace/{workspace_id}/signer-terms/{language}": {
      "put": {
        "summary": "Cr\u00e9er ou mettre \u00e0 jour les conditions signataire de l'espace de travail",
        "description": "Cr\u00e9e ou met \u00e0 jour les conditions signataire au niveau de l'espace de travail pour une langue sp\u00e9cifique. La d\u00e9claration soumise est nettoy\u00e9e avant stockage.",
        "tags": [
          "Signer Terms"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          },
          {
            "name": "language",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es",
                "it",
                "pt",
                "fr",
                "de",
                "el",
                "ru",
                "pl",
                "cs",
                "sv",
                "nl",
                "ro",
                "nb"
              ]
            },
            "description": "Code de langue"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "statement_text"
                ],
                "properties": {
                  "statement_text": {
                    "type": "string",
                    "description": "D\u00e9claration de consentement du signataire au format HTML. Nettoy\u00e9e avant stockage."
                  },
                  "terms_url": {
                    "type": "string",
                    "format": "uri",
                    "nullable": true,
                    "description": "Lien externe optionnel vers les conditions"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Conditions signataire de l'espace de travail mises \u00e0 jour avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignerTermsUpdateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "updateWorkspaceSignerTerms",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signerTerms.updateWorkspaceSignerTerms({\n    workspace_id: \"workspace_id\",\n    language: \"en\",\n    statement_text: \"statement_text\"\n});\nconsole.log(response);"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer les conditions signataire de l'espace de travail",
        "description": "Supprime les conditions signataire au niveau de l'espace de travail pour une langue sp\u00e9cifique.",
        "tags": [
          "Signer Terms"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          },
          {
            "name": "language",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es",
                "it",
                "pt",
                "fr",
                "de",
                "el",
                "ru",
                "pl",
                "cs",
                "sv",
                "nl",
                "ro",
                "nb"
              ]
            },
            "description": "Code de langue"
          }
        ],
        "responses": {
          "200": {
            "description": "Conditions signataire de l'espace de travail supprim\u00e9es avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignerTermsDeleteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "deleteWorkspaceSignerTerms",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signerTerms.deleteWorkspaceSignerTerms({\n    workspace_id: \"workspace_id\",\n    language: \"en\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/email-templates/defaults/{language}": {
      "get": {
        "summary": "Obtenir les mod\u00e8les d'email par d\u00e9faut",
        "description": "R\u00e9cup\u00e8re les mod\u00e8les d'email par d\u00e9faut int\u00e9gr\u00e9s pour une langue sp\u00e9cifique. Ce sont les mod\u00e8les utilis\u00e9s lorsqu'aucun mod\u00e8le d'entreprise ou d'espace de travail personnalis\u00e9 n'est configur\u00e9.",
        "tags": [
          "Email Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "language",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "en",
                "es",
                "it",
                "pt",
                "fr",
                "de",
                "el",
                "ru",
                "pl",
                "cs",
                "sv",
                "nl",
                "ro",
                "nb"
              ]
            },
            "description": "Code de langue"
          }
        ],
        "responses": {
          "200": {
            "description": "Mod\u00e8les par d\u00e9faut r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailTemplateDefaultsResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "getEmailTemplateDefaults",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailTemplates.getEmailTemplateDefaults({\n    language: \"en\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/email-templates/placeholders": {
      "get": {
        "summary": "Obtenir les placeholders des mod\u00e8les d'email",
        "description": "R\u00e9cup\u00e8re la liste des placeholders disponibles pouvant \u00eatre utilis\u00e9s dans les mod\u00e8les d'email. Les placeholders sont remplac\u00e9s par les valeurs r\u00e9elles lors de l'envoi des emails.",
        "tags": [
          "Email Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Placeholders r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailTemplatePlaceholdersResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listEmailTemplatePlaceholders",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailTemplates.listEmailTemplatePlaceholders();\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspace/{workspace_id}/settings": {
      "get": {
        "summary": "Obtenir les param\u00e8tres de l'espace de travail",
        "description": "R\u00e9cup\u00e8re les param\u00e8tres de l'espace de travail",
        "tags": [
          "Workspace Settings"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Param\u00e8tres de l'espace de travail r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceSettings"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "getWorkspaceSettings",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.workspaceSettings.getWorkspaceSettings({\n    workspace_id: \"workspace_id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "put": {
        "summary": "Mettre \u00e0 jour les param\u00e8tres de l'espace de travail",
        "description": "Met \u00e0 jour les param\u00e8tres de l'espace de travail",
        "tags": [
          "Workspace Settings"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "signing_request_email_header": {
                    "type": "string"
                  },
                  "signing_request_email_body": {
                    "type": "string"
                  },
                  "team_email": {
                    "type": "string",
                    "format": "email"
                  },
                  "timezone": {
                    "type": "string"
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "es",
                      "it",
                      "pt",
                      "fr",
                      "de",
                      "el",
                      "ru",
                      "pl",
                      "cs",
                      "sv",
                      "nl",
                      "ro",
                      "nb"
                    ],
                    "description": "Langue de l'espace de travail pour les mod\u00e8les d'email"
                  },
                  "show_credit_cost_in_editor": {
                    "type": "boolean",
                    "description": "Indique s'il faut afficher le co\u00fbt en cr\u00e9dits dans les \u00e9diteurs int\u00e9gr\u00e9s"
                  },
                  "require_otp_verification": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Indique si les signataires doivent v\u00e9rifier leur email via OTP. null = h\u00e9rite de l'entreprise"
                  },
                  "require_terms_acceptance": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Indique si les signataires doivent accepter les conditions avant de signer. null h\u00e9rite du param\u00e8tre au niveau de l'entreprise."
                  },
                  "disable_guided_navigation": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "D\u00e9sactive le d\u00e9filement automatique vers le prochain champ requis pendant la signature. H\u00e9rite de l'espace de travail ou de l'entreprise si non d\u00e9fini."
                  },
                  "show_signature_frame": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Indique s'il faut afficher les cadres de signature dans les PDF termin\u00e9s. null = h\u00e9rite de l'entreprise"
                  },
                  "color_primary": {
                    "type": "string",
                    "nullable": true,
                    "description": "Remplacement de la couleur principale (hex #rrggbb). Null pour h\u00e9riter de l'entreprise."
                  },
                  "color_primary_fg": {
                    "type": "string",
                    "nullable": true,
                    "description": "Surcharge de la couleur de premier plan principale. Null pour h\u00e9riter de l'entreprise."
                  },
                  "color_background": {
                    "type": "string",
                    "nullable": true,
                    "description": "Surcharge de la couleur d'arri\u00e8re-plan. Null pour h\u00e9riter de l'entreprise."
                  },
                  "color_foreground": {
                    "type": "string",
                    "nullable": true,
                    "description": "Surcharge de la couleur de premier plan/texte. Null pour h\u00e9riter de l'entreprise."
                  },
                  "color_card": {
                    "type": "string",
                    "nullable": true,
                    "description": "Surcharge de la couleur d'arri\u00e8re-plan des cartes. Null pour h\u00e9riter de l'entreprise."
                  },
                  "color_border": {
                    "type": "string",
                    "nullable": true,
                    "description": "Surcharge de la couleur de bordure. Null pour h\u00e9riter de l'entreprise."
                  },
                  "color_accent": {
                    "type": "string",
                    "nullable": true,
                    "description": "Couleur d'accent de l'interface de l'\u00e9diteur. Null pour h\u00e9riter de l'entreprise."
                  },
                  "color_accent_fg": {
                    "type": "string",
                    "nullable": true,
                    "description": "Couleur de premier plan sur les surfaces d'accent. Null pour h\u00e9riter de l'entreprise."
                  },
                  "color_canvas": {
                    "type": "string",
                    "nullable": true,
                    "description": "Couleur du pourtour du canevas de document dans l'\u00e9diteur. Null pour h\u00e9riter de l'entreprise."
                  },
                  "color_muted": {
                    "type": "string",
                    "nullable": true,
                    "description": "Couleur de surface att\u00e9nu\u00e9e. Null pour h\u00e9riter de l'entreprise."
                  },
                  "color_muted_fg": {
                    "type": "string",
                    "nullable": true,
                    "description": "Couleur de texte att\u00e9nu\u00e9e. Null pour h\u00e9riter de l'entreprise."
                  },
                  "email_local_part": {
                    "type": "string",
                    "nullable": true,
                    "description": "La partie locale (avant le @) de l'adresse email de l'exp\u00e9diteur. Null pour h\u00e9riter du param\u00e8tre de l'entreprise.",
                    "pattern": "^[a-z0-9]([a-z0-9._-]*[a-z0-9])?$",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "allow_presigning_download": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Autoriser les signataires \u00e0 t\u00e9l\u00e9charger le document original avant de signer. H\u00e9rite du param\u00e8tre de l'espace de travail ou de l'entreprise quand null."
                  },
                  "show_partial_watermark": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Afficher un filigrane EN COURS sur les t\u00e9l\u00e9chargements PDF partiels lorsque tous les signataires n'ont pas termin\u00e9. null h\u00e9rite du param\u00e8tre au niveau de l'entreprise."
                  },
                  "show_qr_code": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "Afficher un code QR sur la page de signature permettant aux signataires de continuer sur leur t\u00e9l\u00e9phone. H\u00e9rite du param\u00e8tre de l'espace de travail ou de l'entreprise quand null."
                  },
                  "signing_button_label_overrides": {
                    "type": "object",
                    "nullable": true,
                    "description": "Libell\u00e9s de boutons personnalis\u00e9s par langue pour la vue de signature. Les cl\u00e9s sont des codes de langue (en, de, etc.) ; les valeurs sont des objets associant des cl\u00e9s de traduction \u00e0 un texte personnalis\u00e9. Null pour utiliser les valeurs par d\u00e9faut.",
                    "additionalProperties": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Param\u00e8tres de l'espace de travail mis \u00e0 jour avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceSettings"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "updateWorkspaceSettings",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.workspaceSettings.updateWorkspaceSettings({\n    workspace_id: \"workspace_id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspace/{workspace_id}/domains": {
      "get": {
        "summary": "Lister les domaines de l'espace de travail",
        "description": "Lister tous les domaines email configur\u00e9s pour un espace de travail sp\u00e9cifique. Ces domaines sont utilis\u00e9s pour envoyer les emails de demande de signature depuis cet espace de travail.",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          }
        ],
        "responses": {
          "200": {
            "description": "Domaines de l'espace de travail r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainListResponse"
                },
                "example": {
                  "results": [
                    {
                      "id": "123e4567-e89b-12d3-a456-426614174000",
                      "domain": "sales.acme.com",
                      "verification_status": 2,
                      "domain_status": 1,
                      "is_primary": true,
                      "date_created": "2024-01-15T10:30:00Z",
                      "date_changed": "2024-01-16T14:00:00Z"
                    }
                  ],
                  "workspace_id": "456e4567-e89b-12d3-a456-426614174000"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "listWorkspaceDomains",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.listWorkspaceDomains({\n    workspace_id: \"workspace_id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "post": {
        "summary": "Ajouter un domaine \u00e0 l'espace de travail",
        "description": "Ajouter un nouveau domaine email pour un espace de travail sp\u00e9cifique. Cela lance le processus de v\u00e9rification du domaine. Apr\u00e8s la cr\u00e9ation, vous devez :\n1. Ajouter un enregistrement TXT \u00e0 votre DNS avec le jeton de v\u00e9rification\n2. Appeler POST /workspace/{workspace_id}/domains/{id}/verify-ownership pour v\u00e9rifier la propri\u00e9t\u00e9 du domaine\n3. Appeler POST /workspace/{workspace_id}/domains/{id}/finalize pour l'enregistrer aupr\u00e8s du fournisseur d'email\n4. Ajouter les enregistrements DNS retourn\u00e9s (SPF, DKIM, etc.)\n5. Appeler POST /workspace/{workspace_id}/domains/{id}/verify-dns pour terminer la v\u00e9rification",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "domain"
                ],
                "properties": {
                  "domain": {
                    "type": "string",
                    "description": "Nom de domaine \u00e0 ajouter (par ex., 'example.com'). Doit \u00eatre un format de domaine valide.",
                    "example": "sales.acme.com"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Domaine cr\u00e9\u00e9 avec succ\u00e8s. Ajoutez l'enregistrement TXT de v\u00e9rification \u00e0 votre DNS.",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 120 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainCreateResponse"
                },
                "example": {
                  "domain": {
                    "id": "123e4567-e89b-12d3-a456-426614174000",
                    "domain": "sales.acme.com",
                    "verification_status": 0,
                    "domain_status": 0,
                    "is_primary": false,
                    "verification_token": "firma-verify=abc123xyz",
                    "date_created": "2024-01-15T10:30:00Z",
                    "date_changed": "2024-01-15T10:30:00Z"
                  },
                  "verification_instructions": {
                    "record_type": "TXT",
                    "record_name": "_firma-verification.sales.acme.com",
                    "record_value": "firma-verify=abc123xyz",
                    "next_step": "Add this TXT record to your DNS, then call POST /workspace/{workspace_id}/domains/{id}/verify-ownership"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Format de domaine invalide ou domaine d\u00e9j\u00e0 existant",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalidDomain": {
                    "value": {
                      "error": "Invalid domain format",
                      "message": "Please provide a valid domain name (e.g., example.com)"
                    }
                  },
                  "domainExists": {
                    "value": {
                      "error": "Domain already exists",
                      "message": "This domain is already configured for this workspace"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "createWorkspaceDomain",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.createWorkspaceDomain({\n    workspace_id: \"workspace_id\",\n    domain: \"sales.acme.com\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspace/{workspace_id}/domains/{id}": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer un domaine de l'espace de travail",
        "description": "R\u00e9cup\u00e9rer les d\u00e9tails d'un domaine sp\u00e9cifique dans un espace de travail, y compris le statut de v\u00e9rification et les enregistrements DNS",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du domaine"
          }
        ],
        "responses": {
          "200": {
            "description": "Domaine r\u00e9cup\u00e9r\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Domain"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "getWorkspaceDomain",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.getWorkspaceDomain({\n    workspace_id: \"workspace_id\",\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer un domaine de l'espace de travail",
        "description": "Supprimer un domaine de l'espace de travail. Si le domaine est le domaine principal ou unique, l'envoi revient \u00e0 l'exp\u00e9diteur de l'entreprise ou par d\u00e9faut.",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du domaine"
          }
        ],
        "responses": {
          "200": {
            "description": "Domaine supprim\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainDeleteResponse"
                },
                "example": {
                  "message": "Domain deleted successfully",
                  "domain_id": "123e4567-e89b-12d3-a456-426614174000"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "deleteWorkspaceDomain",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.deleteWorkspaceDomain({\n    workspace_id: \"workspace_id\",\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspace/{workspace_id}/domains/{id}/verify-ownership": {
      "post": {
        "summary": "V\u00e9rifier la propri\u00e9t\u00e9 d'un domaine de l'espace de travail",
        "description": "V\u00e9rifier la propri\u00e9t\u00e9 du domaine en contr\u00f4lant l'enregistrement TXT. Appelez ceci apr\u00e8s avoir ajout\u00e9 l'enregistrement TXT de v\u00e9rification \u00e0 votre DNS. La propagation DNS peut prendre jusqu'\u00e0 48 heures, mais se termine g\u00e9n\u00e9ralement en quelques minutes.",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du domaine"
          }
        ],
        "responses": {
          "200": {
            "description": "Propri\u00e9t\u00e9 du domaine v\u00e9rifi\u00e9e avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainVerifyOwnershipResponse"
                },
                "example": {
                  "message": "Domain ownership verified",
                  "domain": {
                    "id": "123e4567-e89b-12d3-a456-426614174000",
                    "domain": "sales.acme.com",
                    "verification_status": 1,
                    "domain_status": 0
                  },
                  "next_step": "Call POST /workspace/{workspace_id}/domains/{id}/finalize to complete domain setup and receive DNS records for email sending"
                }
              }
            }
          },
          "400": {
            "description": "\u00c9chec de la v\u00e9rification",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "recordNotFound": {
                    "value": {
                      "error": "Verification failed",
                      "message": "TXT record not found. Please ensure the record is added correctly and DNS has propagated.",
                      "details": {
                        "expected_record": "_firma-verification.sales.acme.com",
                        "expected_value": "firma-verify=abc123xyz"
                      }
                    }
                  },
                  "alreadyVerified": {
                    "value": {
                      "error": "Already verified",
                      "message": "Domain ownership has already been verified"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "verifyWorkspaceDomainOwnership",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.verifyWorkspaceDomainOwnership({\n    workspace_id: \"workspace_id\",\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspace/{workspace_id}/domains/{id}/finalize": {
      "post": {
        "summary": "Finaliser la configuration du domaine de l'espace de travail",
        "description": "Finaliser la configuration du domaine en l'enregistrant aupr\u00e8s du fournisseur d'email. Cela retourne les enregistrements DNS (SPF, DKIM, DMARC) qui doivent \u00eatre ajout\u00e9s pour activer l'envoi d'emails. Ne peut \u00eatre appel\u00e9 qu'apr\u00e8s v\u00e9rification de la propri\u00e9t\u00e9 du domaine.",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du domaine"
          }
        ],
        "responses": {
          "200": {
            "description": "Domaine finalis\u00e9 avec succ\u00e8s. Ajoutez les enregistrements DNS retourn\u00e9s.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainFinalizeResponse"
                },
                "example": {
                  "message": "Domain finalized. Add the following DNS records to enable email sending.",
                  "domain": {
                    "id": "123e4567-e89b-12d3-a456-426614174000",
                    "domain": "sales.acme.com",
                    "verification_status": 2,
                    "domain_status": 0
                  },
                  "dns_records": [
                    {
                      "type": "TXT",
                      "name": "@",
                      "value": "v=spf1 include:amazonses.com ~all",
                      "ttl": "Auto",
                      "status": "pending"
                    },
                    {
                      "type": "CNAME",
                      "name": "resend._domainkey",
                      "value": "resend._domainkey.amazonses.com",
                      "ttl": "Auto",
                      "status": "pending"
                    },
                    {
                      "type": "TXT",
                      "name": "_dmarc",
                      "value": "v=DMARC1; p=none;",
                      "ttl": "Auto",
                      "status": "pending"
                    }
                  ],
                  "next_step": "Add these DNS records, then call POST /workspace/{workspace_id}/domains/{id}/verify-dns to complete verification"
                }
              }
            }
          },
          "400": {
            "description": "Impossible de finaliser",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "notVerified": {
                    "value": {
                      "error": "Ownership not verified",
                      "message": "Please verify domain ownership first by calling POST /workspace/{workspace_id}/domains/{id}/verify-ownership"
                    }
                  },
                  "alreadyFinalized": {
                    "value": {
                      "error": "Already finalized",
                      "message": "Domain has already been finalized"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "finalizeWorkspaceDomain",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.finalizeWorkspaceDomain({\n    workspace_id: \"workspace_id\",\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspace/{workspace_id}/domains/{id}/verify-dns": {
      "post": {
        "summary": "V\u00e9rifier les enregistrements DNS du domaine de l'espace de travail",
        "description": "V\u00e9rifie que tous les enregistrements DNS requis (SPF, DKIM, DMARC) sont correctement configur\u00e9s. Appelle ce endpoint apr\u00e8s avoir ajout\u00e9 tous les enregistrements DNS depuis l'\u00e9tape de finalisation. Une fois v\u00e9rifi\u00e9, le domaine est pr\u00eat pour l'envoi d'e-mails.",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du domaine"
          }
        ],
        "responses": {
          "200": {
            "description": "R\u00e9sultat de la v\u00e9rification DNS",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainVerifyDnsResponse"
                },
                "examples": {
                  "verified": {
                    "summary": "Tous les enregistrements sont v\u00e9rifi\u00e9s",
                    "value": {
                      "verified": true,
                      "message": "Domain is fully verified and ready to send emails",
                      "domain": {
                        "id": "123e4567-e89b-12d3-a456-426614174000",
                        "domain": "sales.acme.com",
                        "verification_status": 2,
                        "domain_status": 1,
                        "is_primary": true
                      },
                      "dns_records": [
                        {
                          "type": "TXT",
                          "name": "@",
                          "value": "v=spf1 include:amazonses.com ~all",
                          "status": "verified"
                        },
                        {
                          "type": "CNAME",
                          "name": "resend._domainkey",
                          "value": "resend._domainkey.amazonses.com",
                          "status": "verified"
                        },
                        {
                          "type": "TXT",
                          "name": "_dmarc",
                          "value": "v=DMARC1; p=none;",
                          "status": "verified"
                        }
                      ]
                    }
                  },
                  "pending": {
                    "summary": "Certains enregistrements sont en attente",
                    "value": {
                      "verified": false,
                      "message": "Some DNS records are not yet verified. Please check your DNS configuration.",
                      "domain": {
                        "id": "123e4567-e89b-12d3-a456-426614174000",
                        "domain": "sales.acme.com",
                        "verification_status": 2,
                        "domain_status": 0
                      },
                      "dns_records": [
                        {
                          "type": "TXT",
                          "name": "@",
                          "value": "v=spf1 include:amazonses.com ~all",
                          "status": "verified"
                        },
                        {
                          "type": "CNAME",
                          "name": "resend._domainkey",
                          "value": "resend._domainkey.amazonses.com",
                          "status": "pending"
                        },
                        {
                          "type": "TXT",
                          "name": "_dmarc",
                          "value": "v=DMARC1; p=none;",
                          "status": "pending"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Domaine non finalis\u00e9",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Domain not finalized",
                  "message": "Please finalize domain setup first by calling POST /workspace/{workspace_id}/domains/{id}/finalize"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "verifyWorkspaceDomainDns",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.verifyWorkspaceDomainDns({\n    workspace_id: \"workspace_id\",\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspace/{workspace_id}/domains/{id}/set-primary": {
      "post": {
        "summary": "D\u00e9finir le domaine principal de l'espace de travail",
        "description": "D\u00e9finit un domaine comme domaine d'envoi principal pour l'espace de travail. Seuls les domaines enti\u00e8rement v\u00e9rifi\u00e9s (domain_status=1) peuvent \u00eatre d\u00e9finis comme principaux.",
        "tags": [
          "Email Domains"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID du domaine"
          }
        ],
        "responses": {
          "200": {
            "description": "Domaine principal mis \u00e0 jour avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainSetPrimaryResponse"
                },
                "example": {
                  "message": "Primary domain updated",
                  "domain": {
                    "id": "123e4567-e89b-12d3-a456-426614174000",
                    "domain": "sales.acme.com",
                    "verification_status": 2,
                    "domain_status": 1,
                    "is_primary": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "Domaine non v\u00e9rifi\u00e9",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Domain not verified",
                  "message": "Only fully verified domains can be set as primary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        },
        "operationId": "setWorkspacePrimaryDomain",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.emailDomains.setWorkspacePrimaryDomain({\n    workspace_id: \"workspace_id\",\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspace/{workspace_id}/custom-fields": {
      "get": {
        "summary": "Lister les champs personnalis\u00e9s de l'espace de travail",
        "description": "R\u00e9cup\u00e8re toutes les d\u00e9finitions de champs personnalis\u00e9s pour un espace de travail",
        "tags": [
          "Custom Fields"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "description": "ID de l'espace de travail",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Champs personnalis\u00e9s r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomFieldListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          }
        },
        "operationId": "listWorkspaceCustomFields",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.customFields.listWorkspaceCustomFields({\n    workspace_id: \"workspace_id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "post": {
        "summary": "Cr\u00e9er un champ personnalis\u00e9 pour l'espace de travail",
        "description": "Cr\u00e9e une nouvelle d\u00e9finition de champ personnalis\u00e9 pour un espace de travail",
        "tags": [
          "Custom Fields"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "description": "ID de l'espace de travail",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "field_label"
                ],
                "properties": {
                  "field_label": {
                    "type": "string",
                    "description": "Libell\u00e9 d'affichage (1 \u00e0 100 caract\u00e8res)",
                    "maxLength": 100
                  },
                  "field_name": {
                    "type": "string",
                    "description": "Nom lisible par machine facultatif (g\u00e9n\u00e9r\u00e9 automatiquement \u00e0 partir du libell\u00e9 si non fourni)",
                    "maxLength": 50
                  },
                  "is_preset": {
                    "type": "boolean",
                    "description": "Si vrai, le champ a une valeur pr\u00e9d\u00e9finie pour tous les utilisateurs",
                    "default": false
                  },
                  "preset_value": {
                    "type": "string",
                    "description": "Valeur pr\u00e9d\u00e9finie (500 caract\u00e8res max, utilis\u00e9e uniquement quand is_preset=true)",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Champ personnalis\u00e9 cr\u00e9\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceCustomField"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "409": {
            "description": "Conflit - Un champ personnalis\u00e9 avec ce nom existe d\u00e9j\u00e0",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "operationId": "createWorkspaceCustomField",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.customFields.createWorkspaceCustomField({\n    workspace_id: \"workspace_id\",\n    field_label: \"field_label\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspace/{workspace_id}/custom-fields/{field_id}": {
      "put": {
        "summary": "Mettre \u00e0 jour un champ personnalis\u00e9 de l'espace de travail",
        "description": "Met \u00e0 jour une d\u00e9finition de champ personnalis\u00e9 existante",
        "tags": [
          "Custom Fields"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "field_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "field_label": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "is_preset": {
                    "type": "boolean"
                  },
                  "preset_value": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Champ personnalis\u00e9 mis \u00e0 jour avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceCustomField"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "409": {
            "description": "Conflit - Un champ personnalis\u00e9 avec ce nom existe d\u00e9j\u00e0",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "operationId": "updateWorkspaceCustomField",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.customFields.updateWorkspaceCustomField({\n    workspace_id: \"workspace_id\",\n    field_id: \"field_id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "delete": {
        "summary": "Supprimer un champ personnalis\u00e9 de l'espace de travail",
        "description": "Supprime (suppression douce) une d\u00e9finition de champ personnalis\u00e9",
        "tags": [
          "Custom Fields"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "workspace_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "field_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Champ personnalis\u00e9 supprim\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          }
        },
        "operationId": "deleteWorkspaceCustomField",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.customFields.deleteWorkspaceCustomField({\n    workspace_id: \"workspace_id\",\n    field_id: \"field_id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/templates/{template_id}/custom-fields": {
      "get": {
        "summary": "Lister les champs personnalis\u00e9s du mod\u00e8le",
        "description": "R\u00e9cup\u00e8re toutes les d\u00e9finitions de champs personnalis\u00e9s pour un mod\u00e8le",
        "tags": [
          "Custom Fields"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "template_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Champs personnalis\u00e9s r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomFieldListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          }
        },
        "operationId": "listTemplateCustomFields",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.customFields.listTemplateCustomFields({\n    template_id: \"template_id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "post": {
        "summary": "Cr\u00e9er un champ personnalis\u00e9 pour le mod\u00e8le",
        "description": "Cr\u00e9e une nouvelle d\u00e9finition de champ personnalis\u00e9 pour un mod\u00e8le",
        "tags": [
          "Custom Fields"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "template_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "field_label"
                ],
                "properties": {
                  "field_label": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "field_name": {
                    "type": "string",
                    "maxLength": 50
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Champ personnalis\u00e9 cr\u00e9\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateCustomField"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "409": {
            "description": "Conflit - Un champ personnalis\u00e9 avec ce nom existe d\u00e9j\u00e0",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "operationId": "createTemplateCustomField",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.customFields.createTemplateCustomField({\n    template_id: \"template_id\",\n    field_label: \"field_label\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/templates/{template_id}/custom-fields/{field_id}": {
      "delete": {
        "summary": "Supprimer un champ personnalis\u00e9 du mod\u00e8le",
        "description": "Supprime (suppression douce) une d\u00e9finition de champ personnalis\u00e9 d'un mod\u00e8le",
        "tags": [
          "Custom Fields"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "template_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "field_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Champ personnalis\u00e9 supprim\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          }
        },
        "operationId": "deleteTemplateCustomField",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.customFields.deleteTemplateCustomField({\n    template_id: \"template_id\",\n    field_id: \"field_id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{request_id}/custom-fields": {
      "get": {
        "summary": "Lister les champs personnalis\u00e9s de la demande de signature",
        "description": "R\u00e9cup\u00e8re toutes les d\u00e9finitions de champs personnalis\u00e9s pour une demande de signature",
        "tags": [
          "Custom Fields"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "request_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Champs personnalis\u00e9s r\u00e9cup\u00e9r\u00e9s avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomFieldListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          }
        },
        "operationId": "listSigningRequestCustomFields",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.customFields.listSigningRequestCustomFields({\n    request_id: \"request_id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "post": {
        "summary": "Cr\u00e9er un champ personnalis\u00e9 pour la demande de signature",
        "description": "Cr\u00e9e une nouvelle d\u00e9finition de champ personnalis\u00e9 pour une demande de signature",
        "tags": [
          "Custom Fields"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "request_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "field_label"
                ],
                "properties": {
                  "field_label": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "field_name": {
                    "type": "string",
                    "maxLength": 50
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Champ personnalis\u00e9 cr\u00e9\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningRequestCustomField"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "409": {
            "description": "Conflit - Un champ personnalis\u00e9 avec ce nom existe d\u00e9j\u00e0",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "operationId": "createSigningRequestCustomField",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.customFields.createSigningRequestCustomField({\n    request_id: \"request_id\",\n    field_label: \"field_label\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{request_id}/custom-fields/{field_id}": {
      "delete": {
        "summary": "Supprimer un champ personnalis\u00e9 de la demande de signature",
        "description": "Supprime (suppression douce) une d\u00e9finition de champ personnalis\u00e9 d'une demande de signature",
        "tags": [
          "Custom Fields"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "request_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "field_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Champ personnalis\u00e9 supprim\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          }
        },
        "operationId": "deleteSigningRequestCustomField",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.customFields.deleteSigningRequestCustomField({\n    request_id: \"request_id\",\n    field_id: \"field_id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspaces/{id}/webhooks/rotate-secret": {
      "post": {
        "summary": "Faire tourner le secret webhook de l'espace de travail",
        "description": "G\u00e9n\u00e8re un nouveau secret de signature webhook pour l'espace de travail. L'ancien secret reste valide pendant 7 jours.",
        "operationId": "rotateWorkspaceWebhookSecret",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de l'espace de travail",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Secret chang\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RotateSecretResponse"
                }
              }
            }
          },
          "429": {
            "description": "P\u00e9riode de blocage active \u2014 le secret a \u00e9t\u00e9 chang\u00e9 r\u00e9cemment"
          }
        },
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.webhooks.rotateWorkspaceWebhookSecret({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspaces/{id}/webhooks/secret-status": {
      "get": {
        "summary": "R\u00e9cup\u00e9rer le statut du secret webhook de l'espace de travail",
        "description": "Retourne le statut du secret webhook de l'espace de travail, incluant la date de cr\u00e9ation, la date de rotation et le statut de la p\u00e9riode de gr\u00e2ce.",
        "operationId": "getWorkspaceWebhookSecretStatus",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de l'espace de travail",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Statut du secret r\u00e9cup\u00e9r\u00e9",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretStatusResponse"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.webhooks.getWorkspaceWebhookSecretStatus({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{id}/download": {
      "get": {
        "summary": "T\u00e9l\u00e9charger le document de la demande de signature",
        "description": "R\u00e9cup\u00e8re une URL de t\u00e9l\u00e9chargement pour le document sign\u00e9 d'une demande de signature. Pour les demandes de signature termin\u00e9es, retourne le PDF final sign\u00e9. Pour les demandes de signature en cours o\u00f9 le t\u00e9l\u00e9chargement partiel est activ\u00e9, retourne une URL vers le document partiellement sign\u00e9 g\u00e9n\u00e9r\u00e9 au moment de la derni\u00e8re signature effectu\u00e9e.\n\n**T\u00e9l\u00e9chargements partiels :** Les t\u00e9l\u00e9chargements partiels sont disponibles uniquement lorsque `allow_partial_download` est activ\u00e9 dans les param\u00e8tres de la demande de signature. Si le document n'a pas encore \u00e9t\u00e9 g\u00e9n\u00e9r\u00e9 partiellement, un `503` est retourn\u00e9 \u2014 r\u00e9essaie apr\u00e8s l'intervalle indiqu\u00e9 dans `Retry-After`.\n\n**Expiration de l'URL :** `download_url` est une URL pr\u00e9-sign\u00e9e qui expire. L'horodatage d'expiration est fourni dans `expires_at`.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de la demande de signature",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "URL de t\u00e9l\u00e9chargement r\u00e9cup\u00e9r\u00e9e avec succ\u00e8s.",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Limite de d\u00e9bit : 200 requ\u00eates par minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningRequestDownloadResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "description": "Demande de signature introuvable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "not_found"
                }
              }
            }
          },
          "409": {
            "description": "La demande de signature n'a pas encore \u00e9t\u00e9 envoy\u00e9e. Le t\u00e9l\u00e9chargement est disponible uniquement apr\u00e8s l'envoi de la demande.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "no_document_available",
                  "message": "Signing request has not been sent yet"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "503": {
            "description": "La g\u00e9n\u00e9ration du document est en cours. R\u00e9essayez apr\u00e8s l'intervalle indiqu\u00e9.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Secondes \u00e0 attendre avant de r\u00e9essayer"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "generation_timeout": {
                    "summary": "La g\u00e9n\u00e9ration du document a expir\u00e9",
                    "value": {
                      "error": "generation_timeout"
                    }
                  },
                  "stale_at_publication": {
                    "summary": "Le document \u00e9tait obsol\u00e8te au moment de la publication",
                    "value": {
                      "error": "stale_at_publication"
                    }
                  }
                }
              }
            }
          }
        },
        "operationId": "downloadSigningRequest",
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.downloadSigningRequest({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{id}/signers/{signer_id}/signature": {
      "get": {
        "operationId": "retrieveSignerSignature",
        "summary": "R\u00e9cup\u00e9rer l'Image de Signature du Signataire",
        "description": "R\u00e9cup\u00e8re la signature adopt\u00e9e d'un signataire sous forme d'URI de donn\u00e9es PNG en base64, s\u00e9par\u00e9ment du PDF sign\u00e9. Un signataire adopte une seule signature appliqu\u00e9e \u00e0 tous ses champs de signature, donc aucun field_id n'est n\u00e9cessaire. Les signatures dessin\u00e9es renvoient l'image captur\u00e9e ; les signatures tap\u00e9es sont rendues en PNG c\u00f4t\u00e9 serveur. `image` est une URI `data:image/png;base64,...` utilisable directement dans un `<img src>`. Par d\u00e9faut, un cadre d'identification du signataire est superpos\u00e9 (`include_frame=false` pour l'omettre). Chaque r\u00e9cup\u00e9ration r\u00e9ussie est enregistr\u00e9e dans un journal d'audit. Limit\u00e9 \u00e0 60/min. La validit\u00e9 juridique repose sur le PDF scell\u00e9 et le certificat d'ach\u00e8vement, pas sur cette image.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de la demande de signature",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "signer_id",
            "in": "path",
            "required": true,
            "description": "ID du signataire (destinataire) \u2014 le recipient_id de GET /fields",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "include_frame",
            "in": "query",
            "required": false,
            "description": "Superposer le cadre d'identification du signataire sur l'image (true par d\u00e9faut). R\u00e9glez sur false pour la marque brute.",
            "schema": {
              "type": "boolean",
              "default": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "La marque du signataire sous forme d'URI de donn\u00e9es PNG en base64.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "signer_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "signature",
                        "initials",
                        "stamp"
                      ]
                    },
                    "format": {
                      "type": "string",
                      "example": "png"
                    },
                    "framed": {
                      "type": "boolean",
                      "description": "Indique si le cadre d'identification du signataire a \u00e9t\u00e9 superpos\u00e9."
                    },
                    "image": {
                      "type": "string",
                      "description": "PNG sous forme d'URI de donn\u00e9es.",
                      "example": "data:image/png;base64,iVBORw0KGgo..."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Cl\u00e9 API manquante ou invalide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Demande de signature/signataire/champ introuvable ou n'appartenant pas \u00e0 votre espace de travail (NOT_FOUND), ou aucune marque captur\u00e9e (SIGNATURE_NOT_AVAILABLE).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de d\u00e9bit d\u00e9pass\u00e9e (60/min pour la r\u00e9cup\u00e9ration de signature).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Le rendu a \u00e9chou\u00e9 (RENDER_FAILED) ou l'\u00e9criture obligatoire du journal d'audit d'acc\u00e8s a \u00e9chou\u00e9 (AUDIT_WRITE_FAILED) ; aucune image n'est renvoy\u00e9e.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.retrieveSignerSignature({\n    id: \"id\",\n    signer_id: \"signer_id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{id}/signers/{signer_id}/initials": {
      "get": {
        "operationId": "retrieveSignerInitials",
        "summary": "R\u00e9cup\u00e9rer l'Image des Initiales du Signataire",
        "description": "R\u00e9cup\u00e8re les initiales adopt\u00e9es d'un signataire sous forme d'URI de donn\u00e9es PNG en base64. Une seule marque d'initiales par signataire (pas de field_id). M\u00eame forme de r\u00e9ponse, cadre, audit et limite de d\u00e9bit que le point de terminaison de signature.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de la demande de signature",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "signer_id",
            "in": "path",
            "required": true,
            "description": "ID du signataire (destinataire)",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "include_frame",
            "in": "query",
            "required": false,
            "description": "Superposer le cadre d'identification du signataire sur l'image (true par d\u00e9faut). R\u00e9glez sur false pour la marque brute.",
            "schema": {
              "type": "boolean",
              "default": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "La marque du signataire sous forme d'URI de donn\u00e9es PNG en base64.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "signer_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "signature",
                        "initials",
                        "stamp"
                      ]
                    },
                    "format": {
                      "type": "string",
                      "example": "png"
                    },
                    "framed": {
                      "type": "boolean",
                      "description": "Indique si le cadre d'identification du signataire a \u00e9t\u00e9 superpos\u00e9."
                    },
                    "image": {
                      "type": "string",
                      "description": "PNG sous forme d'URI de donn\u00e9es.",
                      "example": "data:image/png;base64,iVBORw0KGgo..."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Cl\u00e9 API manquante ou invalide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Demande de signature/signataire/champ introuvable ou n'appartenant pas \u00e0 votre espace de travail (NOT_FOUND), ou aucune marque captur\u00e9e (SIGNATURE_NOT_AVAILABLE).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de d\u00e9bit d\u00e9pass\u00e9e (60/min pour la r\u00e9cup\u00e9ration de signature).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Le rendu a \u00e9chou\u00e9 (RENDER_FAILED) ou l'\u00e9criture obligatoire du journal d'audit d'acc\u00e8s a \u00e9chou\u00e9 (AUDIT_WRITE_FAILED) ; aucune image n'est renvoy\u00e9e.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.retrieveSignerInitials({\n    id: \"id\",\n    signer_id: \"signer_id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{id}/signers/{signer_id}/stamps/{field_id}": {
      "get": {
        "operationId": "retrieveSignerStamp",
        "summary": "R\u00e9cup\u00e9rer l'Image du Tampon du Signataire",
        "description": "R\u00e9cup\u00e8re le tampon d'un signataire pour un champ de tampon sp\u00e9cifique sous forme d'URI de donn\u00e9es PNG en base64. Les tampons sont par champ, donc `field_id` est requis (obtenez-le via GET /signing-requests/{id}/fields, en filtrant sur type=stamp). M\u00eame cadre, audit et limite de 60/min.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de la demande de signature",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "signer_id",
            "in": "path",
            "required": true,
            "description": "ID du signataire (destinataire)",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "field_id",
            "in": "path",
            "required": true,
            "description": "ID du champ de tampon",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "include_frame",
            "in": "query",
            "required": false,
            "description": "Superposer le cadre d'identification du signataire sur l'image (true par d\u00e9faut). R\u00e9glez sur false pour la marque brute.",
            "schema": {
              "type": "boolean",
              "default": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "La marque du signataire sous forme d'URI de donn\u00e9es PNG en base64.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "signer_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "signature",
                        "initials",
                        "stamp"
                      ]
                    },
                    "format": {
                      "type": "string",
                      "example": "png"
                    },
                    "framed": {
                      "type": "boolean",
                      "description": "Indique si le cadre d'identification du signataire a \u00e9t\u00e9 superpos\u00e9."
                    },
                    "image": {
                      "type": "string",
                      "description": "PNG sous forme d'URI de donn\u00e9es.",
                      "example": "data:image/png;base64,iVBORw0KGgo..."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Le champ n'est pas du type attendu (INVALID_FIELD_TYPE).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Cl\u00e9 API manquante ou invalide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Demande de signature/signataire/champ introuvable ou n'appartenant pas \u00e0 votre espace de travail (NOT_FOUND), ou aucune marque captur\u00e9e (SIGNATURE_NOT_AVAILABLE).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de d\u00e9bit d\u00e9pass\u00e9e (60/min pour la r\u00e9cup\u00e9ration de signature).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Le rendu a \u00e9chou\u00e9 (RENDER_FAILED) ou l'\u00e9criture obligatoire du journal d'audit d'acc\u00e8s a \u00e9chou\u00e9 (AUDIT_WRITE_FAILED) ; aucune image n'est renvoy\u00e9e.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.retrieveSignerStamp({\n    id: \"id\",\n    signer_id: \"signer_id\",\n    field_id: \"field_id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/signing-requests/{id}/signers/{signer_id}/files/{field_id}": {
      "get": {
        "operationId": "retrieveSignerFile",
        "summary": "R\u00e9cup\u00e9rer un Fichier T\u00e9l\u00e9vers\u00e9 par le Signataire",
        "description": "R\u00e9cup\u00e8re un fichier qu'un signataire a t\u00e9l\u00e9vers\u00e9 dans un champ de fichier. Renvoie une URL de t\u00e9l\u00e9chargement pr\u00e9-sign\u00e9e de courte dur\u00e9e (300s), pas les octets. `field_id` est requis (via GET /signing-requests/{id}/fields, en filtrant sur type=file). Chaque r\u00e9cup\u00e9ration est enregistr\u00e9e dans un journal d'audit ; limite de 60/min. T\u00e9l\u00e9chargez rapidement c\u00f4t\u00e9 serveur avant l'expiration de l'URL.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ID de la demande de signature",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "signer_id",
            "in": "path",
            "required": true,
            "description": "ID du signataire (destinataire)",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "field_id",
            "in": "path",
            "required": true,
            "description": "ID du champ de fichier",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Une URL pr\u00e9-sign\u00e9e de courte dur\u00e9e pour le fichier t\u00e9l\u00e9vers\u00e9 par le signataire.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "signer_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "kind": {
                      "type": "string",
                      "example": "file"
                    },
                    "file_name": {
                      "type": "string",
                      "nullable": true
                    },
                    "file_type": {
                      "type": "string",
                      "nullable": true
                    },
                    "file_size": {
                      "type": "integer",
                      "nullable": true
                    },
                    "url": {
                      "type": "string",
                      "description": "URL de t\u00e9l\u00e9chargement pr\u00e9-sign\u00e9e."
                    },
                    "expires_in": {
                      "type": "integer",
                      "example": 300,
                      "description": "Secondes avant l'expiration de l'URL."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Le champ n'est pas un champ fichier (INVALID_FIELD_TYPE).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Cl\u00e9 API manquante ou invalide.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Non trouv\u00e9 / pas dans ton espace de travail (NOT_FOUND) ou aucun fichier t\u00e9l\u00e9vers\u00e9 (SIGNATURE_NOT_AVAILABLE).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Limite de taux d\u00e9pass\u00e9e (60/min).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "La g\u00e9n\u00e9ration de l'URL sign\u00e9e a \u00e9chou\u00e9 (INTERNAL_ERROR) ou l'\u00e9criture obligatoire de l'audit d'acc\u00e8s a \u00e9chou\u00e9 (AUDIT_WRITE_FAILED) ; aucune URL n'est retourn\u00e9e.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.retrieveSignerFile({\n    id: \"id\",\n    signer_id: \"signer_id\",\n    field_id: \"field_id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/company/logo": {
      "post": {
        "tags": [
          "Company"
        ],
        "summary": "T\u00e9l\u00e9verser le logo de l'entreprise",
        "description": "T\u00e9l\u00e9verse une image de logo pour l'entreprise. Accepte PNG ou JPEG, 2 Mo maximum. Remplace le logo existant, s'il y en a un.",
        "operationId": "uploadCompanyLogo",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "Fichier image du logo (PNG ou JPEG, 2 Mo maximum)"
                  }
                },
                "required": [
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Logo t\u00e9l\u00e9vers\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LogoUploadResponse"
                }
              }
            }
          },
          "400": {
            "description": "Fichier invalide (mauvais format, trop volumineux, ou manquant)"
          }
        },
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import * as fs from \"fs\";\nimport { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.company.uploadCompanyLogo({\n    file: fs.createReadStream(\"/path/to/your/file\")\n});\nconsole.log(response);"
          }
        ]
      },
      "delete": {
        "tags": [
          "Company"
        ],
        "summary": "Supprimer le logo de l'entreprise",
        "description": "Supprime le logo de l'entreprise. Les certificats utiliseront le logo par d\u00e9faut de Firma.",
        "operationId": "deleteCompanyLogo",
        "responses": {
          "200": {
            "description": "Logo supprim\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LogoDeleteResponse"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.company.deleteCompanyLogo();\nconsole.log(response);"
          }
        ]
      }
    },
    "/workspaces/{id}/logo": {
      "post": {
        "tags": [
          "Workspaces"
        ],
        "summary": "T\u00e9l\u00e9verser le logo de l'espace de travail",
        "description": "T\u00e9l\u00e9verse un logo pour un espace de travail sp\u00e9cifique. Remplace le logo de l'entreprise sur les certificats et les e-mails pour cet espace de travail. Accepte PNG ou JPEG, 2 Mo maximum.",
        "operationId": "uploadWorkspaceLogo",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "Fichier image du logo (PNG ou JPEG, 2 Mo maximum)"
                  }
                },
                "required": [
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Logo t\u00e9l\u00e9vers\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LogoUploadResponse"
                }
              }
            }
          },
          "400": {
            "description": "Fichier invalide (mauvais format, trop volumineux, ou manquant)"
          }
        },
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import * as fs from \"fs\";\nimport { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.workspaces.uploadWorkspaceLogo({\n    file: fs.createReadStream(\"/path/to/your/file\"),\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      },
      "delete": {
        "tags": [
          "Workspaces"
        ],
        "summary": "Supprimer le logo de l'espace de travail",
        "description": "Supprime le logo de l'espace de travail. Les certificats utiliseront alors le logo de l'entreprise, ou celui par d\u00e9faut de Firma.",
        "operationId": "deleteWorkspaceLogo",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID de l'espace de travail"
          }
        ],
        "responses": {
          "200": {
            "description": "Logo supprim\u00e9 avec succ\u00e8s",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LogoDeleteResponse"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.workspaces.deleteWorkspaceLogo({\n    id: \"id\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/documents": {
      "post": {
        "summary": "T\u00e9l\u00e9verser un document",
        "description": "Demande une URL de t\u00e9l\u00e9versement pr\u00e9autoris\u00e9e pour un document. T\u00e9l\u00e9verse le fichier directement vers l'URL retourn\u00e9e, puis passe le document_id lors de la cr\u00e9ation d'une demande de signature. Utilise ceci pour les documents de plus de 5 Mo qui d\u00e9passent la limite de taille des requ\u00eates en base64 inline.",
        "tags": [
          "Signing Requests"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "operationId": "uploadDocument",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "file_name",
                  "file_size",
                  "content_type"
                ],
                "properties": {
                  "file_name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Nom du fichier du document",
                    "example": "contract.pdf"
                  },
                  "file_size": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 52428800,
                    "description": "Taille du fichier en octets. Maximum 50 Mo (52 428 800 octets).",
                    "example": 15000000
                  },
                  "content_type": {
                    "type": "string",
                    "enum": [
                      "application/pdf",
                      "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
                    ],
                    "description": "Type MIME du document",
                    "example": "application/pdf"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "URL de t\u00e9l\u00e9versement cr\u00e9\u00e9e",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "document_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "ID du document \u00e0 passer dans la demande de signature"
                    },
                    "upload_url": {
                      "type": "string",
                      "format": "uri",
                      "description": "URL pr\u00e9autoris\u00e9e sur laquelle faire un PUT du fichier du document. Envoie les octets bruts du fichier avec un Content-Type correspondant au content_type demand\u00e9."
                    },
                    "upload_token": {
                      "type": "string",
                      "description": "Jeton d'authentification du t\u00e9l\u00e9versement (inclus dans l'upload_url)"
                    },
                    "expires_in": {
                      "type": "integer",
                      "description": "Secondes avant l'expiration de l'URL de t\u00e9l\u00e9versement",
                      "example": 3600
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Erreur de validation (file_size, content_type invalides, etc.)"
          },
          "401": {
            "description": "Cl\u00e9 API invalide ou manquante"
          }
        },
        "x-codeSamples": [
          {
            "lang": "TypeScript",
            "label": "@firma-dev/sdk",
            "source": "import { FirmaClient } from \"@firma-dev/sdk\";\n\nconst firma = new FirmaClient({ apiKey: \"YOUR_API_KEY\" });\n\nconst response = await firma.signingRequests.uploadDocument({\n    file_name: \"contract.pdf\",\n    file_size: 15000000,\n    content_type: \"application/pdf\"\n});\nconsole.log(response);"
          }
        ]
      }
    },
    "/templates/{id}/copy": {
      "post": {
        "summary": "Copy template to another workspace",
        "description": "Deep-copies a template (including fields, recipients, CC, reminders, custom field definitions, and the PDF document) to a target workspace within the same company. Requires a company-level (protected) API key.",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Template ID to copy"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "workspace_id"
                ],
                "properties": {
                  "workspace_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Target workspace ID to copy the template into"
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Name for the copied template (defaults to original name with \" (copy)\" suffix)"
                  }
                }
              },
              "example": {
                "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
                "name": "My Template Copy"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Template copied successfully",
            "headers": {
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                },
                "description": "Rate limit: 120 requests per minute"
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateCopyResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing workspace_id or invalid name",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "description": "Protected API key required, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "protected_key_required": {
                    "value": {
                      "error": "This operation requires a protected workspace API key",
                      "code": "PROTECTED_KEY_REQUIRED"
                    }
                  },
                  "access_denied": {
                    "value": {
                      "error": "Template not found or access denied",
                      "code": "ACCESS_DENIED"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Template or target workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          }
        }
      }
    }
  }
}
