> ## Documentation Index
> Fetch the complete documentation index at: https://docs.firma.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Envoi d'une demande de signature

> Comment créer et envoyer des demandes de signature aux destinataires.

# Envoi d'une demande de signature

Ce guide couvre la création d'une demande de signature, l'ajout d'un modèle ou d'un document, et l'invitation des destinataires à signer.

## Étapes

1. Créez ou sélectionnez un modèle
2. Créez une demande de signature référençant le modèle
3. Ajoutez des destinataires avec les informations requises (prénom, nom, email)
4. Ajoutez éventuellement des champs de formulaire avec un positionnement basé sur des pourcentages
5. Envoyez la demande par email ou intégrez la vue de signature

## Schéma du destinataire (champs requis)

<Warning>
  **Changement majeur** : les destinataires nécessitent désormais `first_name` et `last_name` séparément au lieu d'un seul champ `name`.
</Warning>

Chaque destinataire doit inclure :

* `first_name` (requis) - Prénom du destinataire
* `last_name` (requis) - Nom du destinataire
* `email` (requis) - Adresse email valide
* `designation` (requis) - Rôle : `"Signer"`, `"CC"`, ou `"Approver"`. Les approbateurs examinent et approuvent le document (sans signature) via les types de champs `approval_*` ci-dessous
* `order` (optionnel) - Ordre de signature pour les workflows séquentiels

Champs optionnels :

* `phone_number`, `street_address`, `city`, `state_province`, `postal_code`, `country`, `title`, `company`
* `custom_fields` - Objet avec des paires clé-valeur personnalisées

## Créer une demande de signature à partir d'un modèle (API)

> Endpoint : POST /signing-requests

Exemple curl (création d'une demande à partir d'un modèle) :

```bash theme={null}
curl -X POST "https://api.firma.dev/functions/v1/signing-request-api/signing-requests" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template_id": "tmpl_123",
    "name": "NDA - Acme Corp",
    "recipients": [
      { 
        "first_name": "Alice",
        "last_name": "Johnson",
        "email": "alice@example.com",
        "designation": "Signer",
        "order": 1
      }
    ]
  }'
```

Une réponse réussie (201) renvoie une ressource `Document` incluant `id` (le signing\_request\_id) et `document_url` le cas échéant.

## Créer une demande de signature (exemple serveur) — Node (fetch)

```js theme={null}
const fetch = require('node-fetch')

async function createFromTemplate(templateId) {
  const resp = await fetch('https://api.firma.dev/functions/v1/signing-request-api/signing-requests', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.FIRMA_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      template_id: templateId,
      name: 'NDA - Acme Corp',
      recipients: [
        {
          first_name: 'Alice',
          last_name: 'Johnson',
          email: 'alice@example.com',
          designation: 'Signer',
          order: 1
        }
      ]
    })
  })
  if (!resp.ok) throw new Error('failed to create')
  const body = await resp.json()
  return body // contient id, document_url, recipients, etc.
}
```

## Créer une demande de signature (exemple serveur) — Python (requests)

```py theme={null}
import os
import requests

def create_from_template(template_id):
    url = 'https://api.firma.dev/functions/v1/signing-request-api/signing-requests'
    resp = requests.post(url, headers={
        'Authorization': f"Bearer {os.environ['FIRMA_API_KEY']}",
        'Content-Type': 'application/json'
    }, json={
        'template_id': template_id,
        'name': 'NDA - Acme Corp',
        'recipients': [
            {
                'first_name': 'Alice',
                'last_name': 'Johnson',
                'email': 'alice@example.com',
                'designation': 'Signer',
                'order': 1
            }
        ]
    })
    resp.raise_for_status()
    return resp.json()
```

## Créer une demande de signature à partir d'un document

Au lieu d'utiliser un modèle, vous pouvez créer une demande de signature en téléversant directement un document PDF ou DOCX. Choisissez la méthode en fonction de la taille de votre fichier :

<Tabs>
  <Tab title="Petits fichiers (moins de 5 Mo)">
    Pour les documents de moins de 5 Mo, incluez le fichier encodé en base64 directement dans le corps de la requête :

    ```bash theme={null}
    curl -X POST "https://api.firma.dev/functions/v1/signing-request-api/signing-requests/create-and-send" \
      -H "Authorization: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Employment Contract",
        "document": "JVBERi0xLjQK... (base64-encoded PDF)",
        "recipients": [
          {
            "first_name": "Alice",
            "last_name": "Johnson",
            "email": "alice@example.com",
            "designation": "Signer"
          }
        ]
      }'
    ```
  </Tab>

  <Tab title="Fichiers volumineux (jusqu'à 50 Mo)">
    Pour les documents de plus de 5 Mo, utilisez le flux de téléversement en deux étapes :

    **Étape 1 : demander une URL de téléversement**

    ```bash theme={null}
    curl -X POST "https://api.firma.dev/functions/v1/signing-request-api/documents" \
      -H "Authorization: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "file_name": "contract.pdf",
        "file_size": 15000000,
        "content_type": "application/pdf"
      }'
    ```

    Réponse :

    ```json theme={null}
    {
      "document_id": "c251c2c0-a184-4f8c-8e65-be433e6a714a",
      "upload_url": "https://...",
      "upload_token": "eyJ...",
      "expires_in": 3600
    }
    ```

    **Étape 2 : téléverser le fichier**

    ```bash theme={null}
    curl -X PUT "UPLOAD_URL_FROM_STEP_1" \
      -H "Content-Type: application/pdf" \
      --data-binary @contract.pdf
    ```

    **Étape 3 : créer la demande de signature**

    ```bash theme={null}
    curl -X POST "https://api.firma.dev/functions/v1/signing-request-api/signing-requests/create-and-send" \
      -H "Authorization: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Employment Contract",
        "document_id": "c251c2c0-a184-4f8c-8e65-be433e6a714a",
        "recipients": [
          {
            "first_name": "Alice",
            "last_name": "Johnson",
            "email": "alice@example.com",
            "designation": "Signer"
          }
        ]
      }'
    ```

    <Note>
      L'URL de téléversement expire après 1 heure et ne peut être utilisée qu'une seule fois. Chaque `document_id` ne peut être utilisé que dans une seule demande de signature.
    </Note>
  </Tab>
</Tabs>

<Warning>
  Vous devez fournir exactement un seul des paramètres `document`, `document_id`, ou `template_id`. Ils sont mutuellement exclusifs.
</Warning>

## Ajout de champs de formulaire (positionnement basé sur des pourcentages)

<Warning>
  **Important** : toutes les coordonnées de position des champs (x, y, width, height) doivent être des **pourcentages (0-100)** relatifs aux dimensions de la page, et non des pixels. Le champ `page_number` est requis.
</Warning>

Lors de la création directe d'une demande de signature (POST `/signing-requests`) ou de sa mise à jour, vous pouvez ajouter des champs de formulaire :

### Exemple de positionnement de champ

```json theme={null}
{
  "name": "Contract with Fields",
  "recipients": [
    {
      "first_name": "Bob",
      "last_name": "Smith",
      "email": "bob@example.com",
      "designation": "Signer",
      "order": 1
    }
  ],
  "fields": [
    {
      "type": "signature",
      "required": true,
      "recipient_id": "recipient_uuid_here",
      "page_number": 1,
      "position": {
        "x": 10,
        "y": 80,
        "width": 30,
        "height": 8
      }
    },
    {
      "type": "text",
      "required": true,
      "recipient_id": "recipient_uuid_here",
      "variable_name": "company_name",
      "page_number": 1,
      "position": {
        "x": 50,
        "y": 20,
        "width": 40,
        "height": 5
      }
    },
    {
      "type": "date",
      "required": true,
      "page_number": 1,
      "date_signing_default": true,
      "position": {
        "x": 10,
        "y": 90,
        "width": 20,
        "height": 4
      }
    }
  ]
}
```

### Types de champs

* `signature` - Champ de signature
* `text` - Saisie de texte sur une seule ligne
* `date` - Sélecteur de date
* `checkbox` - Case à cocher
* `dropdown` - Sélecteur déroulant (nécessite `dropdown_options`)
* `initials` - Champ d'initiales
* `image` - Champ image
* `approval_signature` - Tampon APPROVED (Approbateur uniquement)
* `approval_checkmark` - Coche d'approbation (Approbateur uniquement)
* `approval_date` - Date d'approbation (Approbateur uniquement)

<Note>
  Les types de champs `approval_*` ne peuvent être attribués qu'à un destinataire dont la `designation` est `"Approver"` (en attribuer un à un Signataire renvoie une erreur `400`). Leur valeur est établie côté serveur lorsque l'approbateur termine son examen, vous n'avez donc pas à soumettre de valeur pour eux, et le tampon d'approbation est apposé sur le certificat d'achèvement.
</Note>

### Directives de positionnement

Le système de coordonnées utilise des pourcentages pour une mise à l'échelle responsive :

* `x` : 0 (bord gauche) à 100 (bord droit)
* `y` : 0 (bord supérieur) à 100 (bord inférieur)
* `width` : pourcentage de la largeur de la page (par ex., 30 = 30 % de largeur)
* `height` : pourcentage de la hauteur de la page (par ex., 8 = 8 % de hauteur)

<Tip>
  Pour une page US Letter (8,5" × 11"), utilisez ces conversions approximatives :

  * 1 pouce ≈ 11,76 % de largeur
  * 1 pouce ≈ 9,09 % de hauteur
</Tip>

## Mise à jour des demandes de signature

Avant qu'une demande de signature ne soit envoyée, vous pouvez mettre à jour ses détails via l'API. L'API propose deux méthodes :

<Warning>
  **Impossible de mettre à jour après l'envoi** : une fois qu'une demande de signature est envoyée, elle ne peut plus être modifiée. Les mises à jour ne fonctionnent que pour les demandes ayant le statut `not_sent`.
</Warning>

### Mise à jour complète (PUT)

Utilisez [`comprehensive-update-signing-request`](/api-reference/v01.15.00/signing-requests/comprehensive-update-signing-request) pour les mises à jour complexes impliquant plusieurs sections.

**Quand l'utiliser** :

* Mise à jour de plusieurs destinataires à la fois
* Suppression de destinataires (avec réattribution/suppression des champs)
* Mise à jour des champs et des rappels ensemble
* Effectuer des modifications coordonnées sur plusieurs sections

**Structure** : toutes les sections sont optionnelles, mais au moins une doit être fournie :

* `signing_request_properties` - Mettre à jour le nom, la description, le document, l'expiration, les paramètres
* `recipients` - Upsert des destinataires (inclure id pour mettre à jour, omettre pour créer)
* `deleted_recipients` - Supprimer des destinataires avec `field_action` (supprimer ou réattribuer les champs)
* `fields` - Upsert des champs (inclure id pour mettre à jour, omettre pour créer)
* `reminders` - Upsert des rappels (inclure id pour mettre à jour, omettre pour créer)

**Exigences** :

* ✅ Peut mettre à jour plusieurs sections en une seule requête
* ✅ Prend en charge la suppression de destinataires avec gestion des champs
* ✅ Ne fonctionne que si la demande n'a pas encore été envoyée

**Exemple** (Node.js) :

```javascript theme={null}
const response = await fetch(`https://api.firma.dev/functions/v1/signing-request-api/signing-requests/${signingRequestId}`, {
  method: 'PUT',
  headers: {
    'Authorization': `Bearer ${process.env.FIRMA_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    signing_request_properties: {
      name: 'Updated Contract Name',
      expiration_hours: 72
    },
    recipients: [
      {
        id: 'rec1-e89b-12d3-a456-426614174000', // Inclure id pour mettre à jour un destinataire existant
        first_name: 'Jane',
        last_name: 'Smith',
        email: 'jane@example.com',
        designation: 'Signer',
        order: 1
      },
      {
        // Omettre id pour créer un nouveau destinataire
        first_name: 'Bob',
        last_name: 'Johnson',
        email: 'bob@example.com',
        designation: 'CC',
        order: 2
      }
    ],
    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'
      }
    ]
  })
});

const updatedRequest = await response.json();
```

### Mise à jour partielle (PATCH)

Utilisez [`partially-update-signing-request`](/api-reference/v01.15.00/signing-requests/partially-update-signing-request) pour mettre à jour des propriétés spécifiques ou un seul destinataire.

**Quand l'utiliser** :

* Mise à jour du nom, de la description ou des paramètres
* Ajout ou mise à jour d'un destinataire à la fois
* Effectuer des modifications ciblées sans affecter les autres données

**Important** : impossible de mettre à jour à la fois les propriétés ET un destinataire dans la même requête. Choisissez l'un ou l'autre :

* Mettre à jour uniquement les propriétés (name, description, document, expiration\_hours, settings)
* OU mettre à jour/créer un seul destinataire

**Avantages** :

* ✅ N'envoyez que les champs que vous souhaitez modifier
* ✅ Plus efficace pour les petits changements
* ✅ Les autres champs restent inchangés
* ✅ Plus sûr pour les modifications concurrentes

**Exemple** (Node.js) :

```javascript theme={null}
// Mettre à jour un seul destinataire
const response = await fetch(`https://api.firma.dev/functions/v1/signing-request-api/signing-requests/${signingRequestId}`, {
  method: 'PATCH',
  headers: {
    'Authorization': `Bearer ${process.env.FIRMA_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    recipient: {
      id: 'rec123-e89b-12d3-a456-426614174000', // Inclure id pour mettre à jour un destinataire existant
      first_name: 'John',
      last_name: 'Updated',
      email: 'john.updated@example.com',
      designation: 'Signer',
      order: 1
    }
  })
});

const updatedRequest = await response.json();
```

**Exemple** (Python) :

```python theme={null}
import requests
import os

# Mettre à jour uniquement les propriétés (nom et expiration)
response = requests.patch(
    f"https://api.firma.dev/functions/v1/signing-request-api/signing-requests/{signing_request_id}",
    headers={
        "Authorization": f"Bearer {os.getenv('FIRMA_API_KEY')}",
        "Content-Type": "application/json"
    },
    json={
        "name": "Updated Contract Name",
        "expiration_hours": 72
    }
)

updated_request = response.json()
```

### Choisir entre PUT et PATCH

| Scénario                                                   | Utiliser | Raison                                                                                    |
| ---------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------- |
| Reconstruction complète de la demande de signature         | PUT      | Remplacement complet avec toutes les sections (properties, recipients, fields, reminders) |
| Mise à jour du nom ou des paramètres uniquement            | PATCH    | Plus efficace, préserve les destinataires et les champs                                   |
| Ajout/mise à jour d'un destinataire                        | PATCH    | Mode destinataire unique, les autres destinataires restent inchangés                      |
| Mise à jour de plusieurs destinataires                     | PUT      | Peut upserter plusieurs destinataires en une seule requête                                |
| Suppression de destinataires avec réattribution des champs | PUT      | Prend en charge deleted\_recipients avec field\_action                                    |
| Modification du document et de tous les champs             | PUT      | Changements structurels majeurs                                                           |
| Mise à jour des champs personnalisés                       | PATCH    | Préserve la demande de signature principale                                               |
| Remplacement de tous les destinataires                     | PUT      | Approche table rase                                                                       |

<Warning>
  **Important** : les deux méthodes de mise à jour ne fonctionnent qu'**avant** l'envoi de la demande de signature. Une fois envoyée, la demande de signature devient immuable pour empêcher toute altération des workflows de signature actifs.
</Warning>

**Bonnes pratiques** :

* Mettez à jour les demandes de signature avant d'appeler `/send`
* Validez les données des destinataires avant de mettre à jour
* Utilisez PATCH pour les modifications incrémentales
* Implémentez une logique de nouvelle tentative avec un backoff exponentiel

***

## Envoi (invitations par email)

Une fois que vous avez un ID de demande de signature (et avez effectué les mises à jour nécessaires), appelez POST `/signing-requests/{signing_request_id}/send` pour envoyer des emails à tous les destinataires.

### Exemple

```bash theme={null}
curl -X POST "https://api.firma.dev/functions/v1/signing-request-api/signing-requests/sr_abc123/send" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "custom_message": "Please sign this NDA by EOD." }'
```

<Note>
  L'endpoint `/send` vérifie que tous les destinataires disposent des informations requises (`first_name`, `last_name`, `email`) et que tous les champs avec `variable_name` ont des données correspondantes dans les enregistrements des destinataires.
</Note>

***

## Intégration de la vue de signature

L'interface publique de signature est disponible selon le modèle suivant :

`https://app.firma.dev/signing/{signing_request_user_id}`

Notes :

* Le `signing_request_user_id` est généralement renvoyé dans le cadre de l'objet `recipients` ou en tant que jeton propre à chaque destinataire ; consultez la réponse de GET /signing-requests/id pour les liens ou jetons de signature au niveau du destinataire.
* Si l'API renvoie directement un `document_url` ou `embed_url`, utilisez-le. Sinon, générez un lien de signature éphémère côté serveur et renvoyez-le au frontend.

### Exemple — récupérer les détails de signature et afficher un iframe

````js theme={null}
### Obtenir l'URL de signature

- Le `signing_request_user_id` est renvoyé dans le tableau `recipients` après la création
- Vous pouvez également récupérer les détails de la demande de signature via GET `/signing-requests/{id}` pour obtenir les liens de signature par destinataire

### Exemple — récupérer les détails de signature et afficher un iframe

```js
// récupérer la demande de signature
const r = await fetch('/internal/signing-request/' + signingRequestId)
const json = await r.json()

// récupérer l'URL de signature du destinataire
const recipient = json.recipients[0]
const signingUrl = recipient.signing_url || `https://app.firma.dev/signing/${recipient.id}`

// afficher l'iframe
const iframe = document.createElement('iframe')
iframe.src = signingUrl
iframe.style.width = '100%'
iframe.style.height = '900px'
iframe.frameBorder = '0'
iframe.allow = 'camera;microphone;clipboard-write'
document.getElementById('signing-root').appendChild(iframe)
````

## Cas particuliers et astuces

* **Ordre de signature** : assurez-vous que les destinataires ont des valeurs `order` séquentielles (1, 2, 3...) pour les workflows de signature séquentiels
* **Piste d'audit** : téléchargez la piste d'audit via GET `/signing-requests/{id}/tracking` pour voir toutes les actions des utilisateurs
* **Téléchargement du PDF terminé** : utilisez GET `/signing-requests/{id}/download` après l'achèvement
* **Webhooks** : abonnez-vous à des événements comme `signing_request.completed` plutôt que d'effectuer du polling (voir le [guide Webhooks](webhooks))

## Prochaines étapes

* [Configurer des webhooks](webhooks) pour recevoir des notifications d'événements en temps réel (60 req/min)
* [Ajouter des rappels automatisés](/api-reference/v01.15.00/signing-requests/get-signing-request-reminders) pour les destinataires en attente
* [Intégrer l'éditeur de modèles](embeddable-template-editor) avec authentification JWT (120 req/min)
* [Configurer les paramètres de l'espace de travail](workspace-settings) pour des modèles d'email personnalisés (100-200 req/min)
* [Éditeur de modèles intégrable](embeddable-template-editor) avec authentification JWT pour des workflows intégrés sécurisés

<Tip>
  - Pour les workflows de signature séquentiels avec plusieurs signataires, assurez-vous que chaque destinataire a une valeur `order` séquentielle (1, 2, 3...).
  - Pour l'audit et la conformité, téléchargez le PDF final via GET /signing-requests/signing\_request\_id/download après l'achèvement.
  - Utilisez les webhooks (voir le [Guide Webhooks](webhooks)) pour réagir aux événements de signature plutôt que d'effectuer du polling.
</Tip>
