Documentation de l'API EasyParafe

Démarrer

Un seul appel crée la demande, place les champs de signature, et envoie l'invitation. Il n'y a pas d'étape intermédiaire à orchestrer : tout réussit, ou rien n'existe.

curl https://easyparafe.fr/api/v1/requests \ -H "Authorization: Bearer pf_live_votre_secret" \ -H "Idempotency-Key: dossier-4821-envoi-1" \ -H "Content-Type: application/json" \ -d '{ "title": "Contrat de bail", "document": "JVBERi0xLjQK…", "signers": [{ "name": "Camille Durand", "email": "camille@exemple.fr", "fields": [ {"kind": "signature", "page": 0, "x": 0.62, "y": 0.78, "w": 0.25, "h": 0.08}, {"kind": "date", "page": 0, "x": 0.62, "y": 0.88, "w": 0.20, "h": 0.03} ] }] }'

Le document est le PDF encodé en base64. Les coordonnées sont normalisées : 0 et 1 désignent les bords de la page, l'origine est en haut à gauche, et page commence à 0. Chaque signataire doit avoir exactement un champ signature.

Authentification

Chaque appel porte votre clé en en-tête :

Authorization: Bearer pf_live_…

Le secret ne vous est montré qu'une fois, à la délivrance : nous n'en conservons qu'une empreinte, et nous ne pouvons pas vous le rappeler. Une clé perdue se révoque et se remplace.

Une clé inconnue et une clé révoquée rendent la même erreur, volontairement. La clé porte votre palier et votre compte émetteur : les demandes créées par l'API appartiennent à ce compte et apparaissent dans son espace.

Vos conditions générales doivent rester acceptées. À la publication d'une nouvelle version, l'API continue de répondre pendant 30 jours en ajoutant un en-tête X-EasyParafe-Warning à ses réponses, et nous prévenons par e-mail le titulaire du compte. Passé ce délai, les appels sont refusés jusqu'à l'acceptation depuis l'espace émetteur.

Idempotence

L'en-tête Idempotency-Key est obligatoire sur la création. Il n'est pas optionnel parce que le dommage qu'il évite est irrattrapable : un timeout réseau chez vous, une requête rejouée, et le document part une seconde fois au signataire.

Choisissez une valeur stable pour l'acte métier — un identifiant de dossier, pas un horodatage. Rejouer la même clé avec le même corps rend la réponse mémorisée, à l'identique et sans rien recréer. La même clé avec un corps différent rend une erreur. Les clés sont conservées 24 heures.

Créer une demande — POST /api/v1/requests

La réponse est un 201 portant la demande — le même objet que celui rendu par la lecture :

{ "id": "3f1c…", "status": "sent", "title": "Contrat de bail", "created_at": "2026-08-13T10:24:31+02:00", "sent_at": "2026-08-13T10:24:32+02:00", "completed_at": null, "metadata": {"dossier": "4821"}, "signers": [ {"order": 0, "name": "Camille Durand", "email": "camille@exemple.fr", "status": "pending", "signed_at": null, "sign_url": null} ] }

Avec notify: false, aucun e-mail ne part et sign_url vous est rendue pour le signataire dont c'est le tour : vous l'ouvrez dans votre propre parcours. Cette URL vaut session de signature — traitez-la comme un secret, et ne la journalisez pas.

notify: false ne vaut que pour le premier signataire. Dans une chaîne à plusieurs signataires, les suivants reçoivent leur invitation par e-mail au fur et à mesure des signatures. Si votre parcours doit rester entièrement chez vous, prévoyez-le.

redirect_url est proposée au signataire en bouton sur l'écran de confirmation, après la signature. Ce n'est jamais une redirection automatique : cet écran est le seul endroit où le signataire récupère son document signé et son dossier de preuve.

Lire une demande — GET /api/v1/requests/{id}

Rend le même objet que la création, avec l'état à jour. Tant que le webhook n'existe pas, c'est ainsi que vous apprenez qu'un document est signé : interrogez-nous à un rythme raisonnable — quelques appels par minute suffisent, une signature humaine ne va pas plus vite.

status vaut draft, sent, viewed, in_progress, signed, declined ou expired. Chaque signataire porte le sien, et sa date de signature.

Une demande qui appartient à un autre compte est introuvable, pas interdite : la réponse est identique à celle d'un identifiant qui n'existe pas. La lecture ne rend jamais sign_url, même pour une demande créée avec notify: false.

Le motif d'un refus de signature n'est pas exposé au lot 1 : la lecture vous dit declined, et le motif saisi par le signataire figure dans le dossier de preuve. Il rejoindra la réponse avec le webhook.

Erreurs

Toutes les erreurs ont la même forme. code est un identifiant stable, destiné à votre code ; message est en français, destiné à un humain ; field désigne le champ fautif quand il y en a un.

{"error": {"code": "invalid_signer", "message": "L'adresse e-mail du signataire est invalide.", "field": "signers[0].email"}}

Toute réponse de /api/v1/ est du JSON, y compris les erreurs et les chemins inconnus — à une exception près, décrite dans les limites ci-dessous. Nous ne redirigeons jamais : un client qui suit une redirection recevrait une page HTML avec un statut de succès.

Limites et forfait

Ce qui n'est pas encore là

Nous préférons l'écrire plutôt que vous le laisser découvrir.

Une question, un cas qui ne rentre pas ? Écrivez-nous : en bêta, vous avez un interlocuteur direct.