API Cygnable
L’API, les webhooks et la signature intégrée sont compris dans la formule Business. Un appel avec la clé d’un autre compte répond 403 (code: "plan").
Envoyez un PDF en signature depuis votre site, recevez un webhook quand tout le monde a signé, récupérez le PDF scellé et son certificat. Chaque signataire confirme par un code SMS : c’est compris dans le prix de l’enveloppe.
Authentification
Créez une clé dans Mon espace › Compte. Elle n’est affichée qu’une fois ; nous n’en gardons que l’empreinte.
Authorization: Bearer sk_live_…Créer et envoyer une enveloppe
POST https://cygnable.com/api/v1/envelopes
Content-Type: application/json
{
"title": "Bail — 18 cours de l’Argonne",
"document_base64": "JVBERi0xLjcK…",
"ordering": "sequential", // ou "parallel"
"external_ref": "bail-4521", // votre identifiant, renvoyé dans les webhooks
"signers": [
{ "name": "Paul Martin", "email": "paul@exemple.fr", "phone": "0611111111", "role": "Bailleur" },
{ "name": "Léa Durand", "email": "lea@exemple.fr", "phone": "+33622222222", "role": "Locataire",
"embedded": true, "return_url": "https://votre-site.fr/bail/4521/signe" }
],
"fields": [
{ "signer": 1, "type": "signature", "page": 3, "x": 0.08, "y": 0.72, "w": 0.35, "h": 0.08 },
{ "signer": 2, "type": "signature", "page": 3, "x": 0.55, "y": 0.72, "w": 0.35, "h": 0.08 },
{ "signer": 2, "type": "initials", "page": 1, "x": 0.85, "y": 0.93, "w": 0.1, "h": 0.04 }
],
"embed_origin": "https://votre-site.fr"
}Positions : fractions de la page (0 à 1), origine en haut à gauche ; page et signer commencent à 1. Types : signature, initials, date (remplie à la signature), text, checkbox, mention (texte à recopier à l’identique, avec expected — par exemple la mention manuscrite d’une caution, art. 2297 du Code civil).
Ancres : plutôt que des coordonnées, écrivez dans le PDF {{signature:1}}, {{paraphe:2}}, {{date:1}}, {{texte:1}}, {{case:2}} (en blanc si vous voulez les cacher) et passez "use_anchors": true. Pour tout autre champ (une mention à recopier, par exemple), donnez "anchor": "{{mention:3}}" à la place de page, x et y : le champ est posé à chaque occurrence du texte, décalé de dx/dy si besoin.
Paraphe sur chaque page : "initials_every_page": true (et "initials_position": "left" ou "right"). Chaque signataire trace son paraphe une fois ; il est apposé en bas de toutes les pages, dans la bande de preuve, sans recouvrir le contenu. Rangement : "tags": ["baux", "2026"] et "folder": "Agence Nord" servent à retrouver les documents dans l’espace.
Chaque signataire doit avoir au moins un champ signature, son propre e-mail et son propre mobile. "send": false crée un brouillon sans l’envoyer. Réponse 201 : l’enveloppe (voir plus bas). Quota épuisé et dépassement désactivé : 402 ; SMS momentanément indisponibles : 503 (rien n’est décompté).
Signature intégrée à votre site
Un signataire créé avec embedded: true ne reçoit pas d’e-mail : vous lui présentez la signature, en iframe ou en redirection. Le code SMS reste obligatoire.
POST https://cygnable.com/api/v1/envelopes/{id}/signing-url
{ "signer_id": "cm…" }
→ { "url": "https://cygnable.com/s/…?embed=1" }En iframe, seule l’origine embed_origin (ou celles déclarées dans votre compte) peut afficher la page. À la fin, la page envoie postMessage({ type: "signature.signed", envelope_id, signer_id, completed }) à la fenêtre parente ; hors iframe, elle redirige vers return_url. Ne vous fiez pas au message seul : attendez le webhook.
Consulter, télécharger, annuler
GET https://cygnable.com/api/v1/envelopes/{id}
GET https://cygnable.com/api/v1/envelopes?external_ref=bail-4521
GET https://cygnable.com/api/v1/envelopes/{id}/final → PDF signé et scellé (application/pdf)
GET https://cygnable.com/api/v1/envelopes/{id}/certificate → certificat de signature seul
POST https://cygnable.com/api/v1/envelopes/{id}/cancel{
"id": "cm…", "object": "envelope", "status": "sent", // draft | sent | completed | declined | cancelled | expired
"document": { "pages": 4, "sha256": "…" },
"final": { "sha256": "…", "seal": "PAdES-B-T", "opentimestamps": "pending", "bitcoin_block": null,
"pdf_url": "…", "certificate_url": "…" },
"signers": [ { "id": "cm…", "order": 1, "status": "signed", "signed_at": "2026-09-24T08:12:03Z" }, … ]
}Webhooks
Déclarez une URL https dans votre compte. Événements : signer.signed, envelope.completed, envelope.declined, envelope.cancelled, envelope.expired. Réessais pendant 48 h si vous ne répondez pas en 2xx.
X-Signature: t=1790000000,v1=5f2c…
// v1 = HMAC-SHA256(secret, t + "." + corps brut), en hexadécimal.
// Comparez en temps constant et refusez un t de plus de 5 minutes.// Node.js
const [t, v1] = req.headers['x-signature'].split(',').map(p => p.split('=')[1]);
const attendu = crypto.createHmac('sha256', SECRET).update(t + '.' + corpsBrut).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(attendu), Buffer.from(v1)) && Date.now() / 1000 - t < 300;Preuve et vérification
Le PDF final porte un cachet PAdES (horodaté RFC 3161 quand l’autorité répond) émis par un certificat de KIPDEV SAS, non délivré par une autorité de certification : il prouve l’intégrité, pas l’identité de l’éditeur. Son empreinte est ancrée dans Bitcoin via OpenTimestamps ; le reçu .ots se télécharge depuis la page de vérification.
Preuve visible : sous chaque page du PDF final, une bande ajoutée (la page est agrandie, rien n’est recouvert) porte un QR code vers https://cygnable.com/v/<id>, la référence de l’enveloppe, la date, le début de l’empreinte du document d’origine et « page X/N ». Cette page publique donne l’état de la signature (date, signataires en initiales, cachet, ancrage), jamais le contenu, et compare un fichier déposé, dans le navigateur. La bande est posée avant le cachet : elle est couverte par l’empreinte finale.
Signer par e-mail
Sans API ni interface : écrivez à signer@cygnable.com depuis l’adresse de votre compte, le PDF en pièce jointe, les signataires en copie ou une ligne par personne dans le corps (Nom <e-mail> 06…). Le message doit porter une signature DKIM de votre domaine (c’est le cas de Gmail, Outlook et de la plupart des messageries professionnelles). Rien ne part tout de suite : vous recevez « Confirmez l’envoi », et les signataires ne sont invités qu’après votre clic. Sans ancre {{signature:1}} dans le PDF, une page « Signatures » est ajoutée à la fin.
Limites
- PDF de 15 Mo et 150 pages au plus, non protégé par mot de passe, sans page pivotée.
- 10 signataires par enveloppe ; 5 codes SMS par signataire ; liens valables 30 jours ; enveloppe expirée après 30 jours.
- 120 requêtes par heure et par compte.