Signature Requests
Création et récupération des requêtes de signature électronique.
POST /api/v1/signature_requests
Crée une signature request à partir de documents préalablement uploadés via
POST /api/v1/documents.
Tous les champs sont wrappés sous une clé racine signature_request :
{
"signature_request": {
/* champs ci-dessous */
}
}Body — champs racine
| Champ | Type | Requis | Description |
|---|---|---|---|
mode | string | ✓ | "sequential" ou "parallel". |
validity_days | int | ✓ | 1 à 90. |
send_email | bool | Défaut false. Si true, Signlift notifie le premier signataire (mode sequential) ou tous (mode parallel). | |
identity_declaration_accepted | bool | ✓ si send_email: true | Atteste que vous avez collecté l'identité des signataires hors-Signlift (exigence eIDAS pour la signature simple). Sans ce flag avec send_email: true, l'API répond 422 identity_declaration_required. |
initials_required | bool | Paraphes par page. Plans Pro et Enterprise uniquement. Sinon 403 initials_not_available_on_plan. | |
notify_signers_on_completion | bool | Défaut false. E-mail récapitulatif envoyé aux signataires à la complétion. | |
callback_url | string | URL https qui reçoit les événements terminaux de cette demande — request.completed et request.expired — avec les mêmes headers et la même signature HMAC que le webhook d'application. S'y ajoute, ne le remplace pas. Les événements intermédiaires n'y sont jamais envoyés. Cf. Webhooks. | |
branding_profile_id | int | Applique une charte graphique personnalisée au parcours du signataire. Doit correspondre à un profil créé depuis votre organisation (dashboard → Charte). Plans Pro et Enterprise uniquement. Omis ou null → palette Signlift par défaut. Un id qui n'appartient pas à votre organisation est rejeté en 422 validation_error. | |
signers | array | ✓ | Liste des signataires (cf. schéma ci-dessous). |
documents | array | ✓ | Liste des documents à signer avec leurs placements de signature (cf. schéma ci-dessous). |
Les limites sur le nombre de signataires et de documents dépendent du plan : voir Limites et rate-limits.
Schéma d'un signer (entrée)
{
"ref": "jeanne",
"first_name": "Jeanne",
"last_name": "Dupont",
"email": "jeanne@example.com",
"phone": "+33612345678",
"order": 1,
"otp_channel": "email"
}ref: identifiant arbitraire choisi par votre code, utilisé pour lier le signataire à ses placements dansdocuments[].signers[].signer_ref. Non persisté.phone: format E.164 (+CCXXXXXXXXX). Requis si le code part par SMS.order: ordre de signature en modesequential(ignoré enparallel).otp_channel:emailousms. Détermine par quel canal arrive le code à usage unique qui authentifie la signature.
sms requiert un phone et un plan Pro ou Enterprise ; email est
toujours disponible.
Schéma d'un document (entrée)
{
"id": 42,
"signers": [
{
"signer_ref": "jeanne",
"stamps": [
{ "type": "magic_field", "value": { "tag": "[SIG_JEANNE_1]" } },
{ "type": "magic_field", "optional": true, "value": { "tag": "[SIG_JEANNE_2]" } },
{ "type": "coordinates", "value": { "page_number": 3, "x": 100, "y": 120 } }
]
}
]
}id: identifiant renvoyé parPOST /api/v1/documents.signers: les signataires qui signent ce document, au moins un. Un signataire absent de la liste ne signe pas ce document, mais chaque signataire déclaré à la racine doit en signer au moins un.signer_ref: lerefd'un signataire de la liste racine. Un signataire n'apparaît qu'une fois par document : tous ses tampons vont dans son tableaustamps.stamps: les emplacements où sa signature apparaît sur ce document, de 1 à 10.
Tampons
type | value | Placement |
|---|---|---|
magic_field | { "tag": "[SIG_JEANNE]" } | Le tampon se place juste sous le texte tag, centré sur lui. Le texte doit figurer tel quel dans le PDF, sinon l'API répond 422 (sauf tampon optional). |
coordinates | { "page_number", "x", "y", "width", "height" } | Position en points PDF, origine en bas à gauche de la page, page_number à partir de 1. width (80 à 400, défaut 200) et height (30 à 160, défaut 80) sont optionnels. Le tampon doit tenir dans la page. |
Tampons optionnels
Un gabarit de tampons envoyé sur des PDF qui ne portent pas tous les mêmes
tags peut marquer un tampon optional :
optional: booléen JSON,falsepar défaut. Àtrue, un tamponmagic_fielddont le tag est absent du PDF est ignoré au lieu de faire échouer la demande. Il n'apparaît pas sur le document signé.- Le signataire doit malgré tout garder au moins un tampon trouvé sur
chaque document qu'il signe : si tous ses tampons y sont introuvables,
la demande est refusée en
422. - Sans effet sur
coordinates: un tampon hors de la page reste refusé. - Les tampons optionnels comptent dans la limite de 10 et dans l'unicité des tags.
Un placement invalide est refusé en 422 validation_error, et aucune
demande n'est créée :
stampsabsent ou vide, ou plus de 10 tampons pour un signataire sur un document ;- un signataire listé deux fois sur un même document ;
- un même tag utilisé deux fois par un signataire sur un document ;
- un
tagintrouvable dans le PDF sur un tampon qui n'est pasoptional, une page inexistante, un tampon qui déborde de la page ; - aucun tampon trouvé pour un signataire sur un document, quand tous ses
tampons y sont
optional; - un
optionalqui n'est pas un booléen JSON ("true"ounullsont refusés) ; - un
signer_refqui ne correspond à aucun signataire.
Charte graphique du parcours
Les organisations sur les plans Pro et Enterprise peuvent
personnaliser les couleurs du parcours de signature (fond, texte,
accentuation). Les profils sont créés et gérés depuis le dashboard, dans
Charte au niveau de l'organisation — l'API n'expose que leur lecture, via
GET /api/v1/branding_profiles, pas
leur création. Limite : 2 profils sur Pro, 10 sur Enterprise.
Pour appliquer un profil à une demande, transmettez son identifiant dans
branding_profile_id :
curl https://app.signlift.eu/api/v1/signature_requests \
-H "X-Api-Key: $SIGNLIFT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"signature_request": {
"mode": "parallel",
"validity_days": 30,
"branding_profile_id": 7,
"signers": [ /* … */ ],
"documents": [ /* … */ ]
}
}'Si l'identifiant n'appartient pas à votre organisation, l'API répond
422 validation_error. Les demandes créées sans branding_profile_id
conservent l'apparence générique Signlift.
L'objet branding_profile est renvoyé dans la réponse de tous les endpoints
qui retournent une signature_request (cf. ci-dessous), ou null quand la
demande utilise la palette par défaut.
Exemple minimal
curl https://app.signlift.eu/api/v1/signature_requests \
-H "X-Api-Key: $SIGNLIFT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"signature_request": {
"mode": "sequential",
"validity_days": 30,
"send_email": true,
"identity_declaration_accepted": true,
"signers": [
{
"ref": "jeanne",
"first_name": "Jeanne",
"last_name": "Dupont",
"email": "jeanne@example.com",
"order": 1
}
],
"documents": [
{
"id": 42,
"signers": [
{
"signer_ref": "jeanne",
"stamps": [{ "type": "magic_field", "value": { "tag": "[SIG_JEANNE]" } }]
}
]
}
]
}
}'Pour un payload complet (mode parallel, placements par coordonnées, paraphes), utilisez le playground interactif.
Réponse 201
{
"id": 42,
"mode": "sequential",
"status": "pending",
"validity_days": 30,
"initials_required": false,
"notify_signers_on_completion": false,
"expires_at": "2026-06-16T15:00:00Z",
"created_at": "2026-05-17T15:00:00Z",
"document_ids": [42],
"signers": [
{
"id": 1768,
"first_name": "Jeanne",
"last_name": "Dupont",
"full_name": "Jeanne Dupont",
"email": "jeanne@example.com",
"order": 1,
"status": "pending",
"signed_at": null,
"signing_url": "https://app.signlift.eu/sign/eyJhbGciOiJIUzI1NiJ9..."
}
],
"branding_profile": {
"id": 7,
"name": "Marque Acme",
"background_color": "#f5f0e6",
"text_color": "#173039",
"accent_color": "#202c90"
}
}branding_profile vaut null quand la demande utilise la palette par défaut.
Le statut du signer est pending à la réponse synchrone — il passe à
notified une fois l'e-mail envoyé (job asynchrone).
Le champ signing_url est l'URL absolue à transmettre au signataire — voir
Authentification et
Intégration iframe.
Le champ download_urls n'est pas présent à la création — il apparaît
uniquement sur le GET ci-dessous, et uniquement lorsque la signature
request est completed.
GET /api/v1/signature_requests
Liste paginée de vos demandes de signature. C'est le seul moyen de retrouver vos enveloppes sans en avoir conservé les identifiants — rejouer une archive, réconcilier après un incident, alimenter un tableau de bord.
Enveloppe, pagination et filtres : voir
Collections paginées.
Le filtre status accepte pending, completed et expired.
Exemple
curl "https://app.signlift.eu/api/v1/signature_requests?status=completed&created_after=2026-05-01" \
-H "X-Api-Key: $SIGNLIFT_API_KEY"Réponse 200
{
"data": [
{
"id": 42,
"status": "completed",
"finalized": true,
"mode": "sequential",
"expires_at": "2026-06-16T15:00:00Z",
"created_at": "2026-05-17T15:00:00Z",
"document_ids": [7],
"signers": []
}
],
"pagination": { "page": 1, "limit": 20, "count": 1, "pages": 1 }
}Chaque entrée reprend la sérialisation du GET unitaire ci-dessous, à une
exception près : download_urls n'apparaît jamais dans la liste, même
pour une demande finalisée. Le générer coûterait une URL S3 présignée par
document, multipliée par le nombre de documents de chaque enveloppe de la
page. Appelez le GET unitaire pour les obtenir.
GET /api/v1/signature_requests/{id}
Récupère l'état actuel d'une signature request.
Statuts possibles
| Status | Signification |
|---|---|
pending | Au moins un signataire n'a pas encore signé. |
completed | Tous les signataires ont signé. Le scellement suit, voir finalized. |
expired | validity_days dépassé sans complétion. |
Les signataires individuels ont leur propre cycle de statut
(pending → notified → signed), exposé dans signers[].status.
Réponse 200 — signature complétée
{
"id": 42,
"mode": "sequential",
"status": "completed",
"finalized": true,
"validity_days": 30,
"initials_required": false,
"notify_signers_on_completion": false,
"expires_at": "2026-06-16T15:00:00Z",
"created_at": "2026-05-17T15:00:00Z",
"document_ids": [42],
"signers": [
{
"id": 1768,
"first_name": "Jeanne",
"last_name": "Dupont",
"full_name": "Jeanne Dupont",
"email": "jeanne@example.com",
"order": 1,
"status": "signed",
"signed_at": "2026-05-17T15:12:43Z",
"signing_url": null
}
],
"branding_profile": null,
"download_urls": [
{
"document_id": 42,
"signed_url": "https://s3.eu-west-1.amazonaws.com/...?X-Amz-Signature=...",
"certificate_url": "https://s3.eu-west-1.amazonaws.com/...?X-Amz-Signature=...",
"expires_in": 900
}
]
}Les URLs signed_url et certificate_url sont des URLs S3 présignées valides
pendant expires_in secondes (900 = 15 minutes). Pour les récupérer à
nouveau, rappelez ce même endpoint.
status et finalized ne disent pas la même chose
status: "completed" signifie que le dernier signataire a signé. Le
scellement des PDF et l'émission du dossier de preuve se font juste après,
de façon asynchrone.
finalized passe à true quand tous les artefacts sont disponibles, et
download_urls n'apparaît pas avant. C'est donc finalized qu'il faut
attendre, pas status : une intégration qui déclenche son téléchargement sur
completed reçoit une réponse sans URLs.
Le dossier de preuve
C'est un PDF distinct du document signé, scellé lui aussi, unique par
demande : avec plusieurs documents, chaque entrée de download_urls porte
la même certificate_url, un seul téléchargement suffit.
Il contient :
- les signataires, avec le canal d'authentification utilisé (SMS ou e-mail) et la destination exacte à laquelle le code à usage unique a été envoyé ;
- pour chaque document : son nom, son nombre de pages, et deux empreintes SHA-256, celle du fichier déposé et celle du fichier signé ;
- le journal d'audit horodaté à la milliseconde, fuseau inclus, chaque ligne attribuée nominativement à son signataire ;
- l'horodatage RFC 3161 du sceau, avec le nom de l'autorité qui l'a délivré.
La version exploitable par une machine du même journal est disponible via
GET /api/v1/signature_requests/:id/audit_logs.