Yousign is an EU-native electronic signature platform: eIDAS-compliant (EU Regulation on trusted electronic services), Qualified Electronic Signatures (QES) for documents requiring the highest legal standing, servers in Europe, GDPR-compliant. Unlike DocuSign or Adobe Sign, Yousign was built for the EU market — qualified e-signatures under French and German law, notarial documents, banking agreements. There is no native integration with Kommo — below we cover the correct architecture using the Yousign API v3.
Yousign vs DocuSign vs Adobe Sign for EU teams
| Parameter | Yousign | DocuSign | Adobe Sign |
|---|---|---|---|
| Jurisdiction | EU-native (eIDAS) | US (eIDAS via partner) | US (eIDAS via partner) |
| Qualified e-signature | Yes (QES) | Via TSP partner | Via TSP partner |
| Servers | EU (France, GDPR) | US + EU PoP | US + EU PoP |
| Price | from €25/month | from $15/user/month | from $15/user/month |
| API | REST v3 (modern) | REST (complex) | REST |
| Best for | EU teams with legal requirements | Global companies | Global companies |
Yousign is chosen by EU companies where electronic signatures must comply with national legislation (France, Germany, Netherlands) and where data must not leave the EU.
What gets synchronised
Kommo -> Yousign:
— Won (or a custom “Signing” stage) -> create a Signature Request from a template with the contact’s data
— Contact name or email change -> update the signer’s data
Yousign -> Kommo:
— request.activated -> Note: “Document sent for signing”
— request.completed -> Note: “Document signed by all parties” + move to Won stage
— request.expired -> Note + Task: “Signature request expired — resend”
— request.declined -> Note: “Signer declined the document”
Yousign API v3: creating a Signature Request
Base URL: https://api.yousign.app/v3. Authentication: Authorization: Bearer {api_key} (from Yousign -> Settings -> API -> Create API Key).
import requests
YS_API_KEY = "your_yousign_api_key"
YS_BASE = "https://api.yousign.app/v3"
YS_HEADERS = {
"Authorization": f"Bearer {YS_API_KEY}",
"Content-Type": "application/json",
}
def upload_document(file_path: str, file_name: str) -> str:
# Upload a PDF document and receive a document_id
with open(file_path, "rb") as f:
resp = requests.post(
f"{YS_BASE}/documents",
headers={"Authorization": f"Bearer {YS_API_KEY}"},
files={"file": (file_name, f, "application/pdf")},
data={"nature": "signable_document"},
)
resp.raise_for_status()
return resp.json().get("id")
def create_signature_request(document_id: str, signer_name: str,
signer_email: str, signer_phone: str = "") -> dict:
payload = {
"name": f"Contract - {signer_name}",
"delivery_mode": "email",
"signers": [
{
"info": {
"first_name": signer_name.split()[0] if signer_name else "",
"last_name": " ".join(signer_name.split()[1:]) if len(signer_name.split()) > 1 else "",
"email": signer_email,
"phone_number": signer_phone or None,
"locale": "fr",
},
"signature_level": "electronic_signature",
"signature_authentication_mode": "no_otp",
}
],
"documents": [{"document_id": document_id}],
"timezone": "Europe/Paris",
"expiration_date": None,
}
resp = requests.post(
f"{YS_BASE}/signature_requests",
headers=YS_HEADERS,
json=payload,
)
resp.raise_for_status()
return resp.json()
def activate_signature_request(request_id: str) -> dict:
# Send the signature request to the signers
resp = requests.post(
f"{YS_BASE}/signature_requests/{request_id}/activate",
headers=YS_HEADERS,
)
resp.raise_for_status()
return resp.json()
def on_kommo_deal_won(lead: dict, contact: dict):
signer_name = contact.get("name", "")
signer_email = get_contact_email(contact)
signer_phone = get_contact_phone(contact)
# PDF contract template pre-filled with deal/contact data
pdf_path = generate_contract_pdf(lead, contact)
doc_id = upload_document(pdf_path, f"contract_{lead['id']}.pdf")
sig_req = create_signature_request(doc_id, signer_name, signer_email, signer_phone)
req_id = sig_req.get("id")
activated = activate_signature_request(req_id)
save_to_kommo_deal(lead["id"], {"yousign_request_id": req_id})
create_kommo_note(
lead["id"],
f"Yousign: signature request sent - {signer_email} (request ID: {req_id})",
)
Webhook: Yousign -> Kommo
Yousign Subscriptions (webhooks) are configured via the API: POST /event_subscriptions.
def create_yousign_webhook(callback_url: str) -> dict:
payload = {
"url": callback_url,
"subscribed_events": [
"signature_request.activated",
"signature_request.completed",
"signature_request.expired",
"signer.declined",
],
}
resp = requests.post(
f"{YS_BASE}/event_subscriptions",
headers=YS_HEADERS,
json=payload,
)
resp.raise_for_status()
return resp.json()
@app.route("/webhooks/yousign", methods=["POST"])
def yousign_webhook():
payload = request.json
event_name = payload.get("event_name", "")
request_id = payload.get("data", {}).get("signature_request", {}).get("id", "")
lead_id = find_kommo_deal_by_custom_field("yousign_request_id", request_id)
if not lead_id:
return "", 200
if event_name == "signature_request.activated":
create_kommo_note(lead_id, "Yousign: document sent for signing")
elif event_name == "signature_request.completed":
create_kommo_note(lead_id, "Yousign: document signed by all parties")
move_kommo_deal_to_stage(lead_id, SIGNED_STAGE_ID)
download_and_attach_signed_doc(lead_id, request_id)
elif event_name == "signature_request.expired":
create_kommo_note(lead_id, "Yousign: signature deadline expired")
create_kommo_task(lead_id, "Yousign: resend document for signing")
elif event_name == "signer.declined":
signer_email = payload.get("data", {}).get("signer", {}).get("info", {}).get("email", "")
create_kommo_note(lead_id,
f"Yousign: signer {signer_email} declined the document")
return "", 200
def download_and_attach_signed_doc(lead_id: int, request_id: str):
# Download the signed PDF and save the URL in Kommo
resp = requests.get(
f"{YS_BASE}/signature_requests/{request_id}/documents/download",
headers=YS_HEADERS,
)
if resp.ok:
# Save to S3 / Google Cloud Storage, get URL
doc_url = save_signed_pdf_to_storage(resp.content, f"signed_{request_id}.pdf")
create_kommo_note(lead_id, f"Yousign: signed document -> {doc_url}")
Qualified signature (QES): when it is needed
Yousign supports three signature levels in accordance with eIDAS:
— SES (Simple Electronic Signature) — email link, sufficient for most B2B contracts
— AES (Advanced Electronic Signature) — OTP via SMS + identity verification
— QES (Qualified Electronic Signature) — highest legal standing, video identification or eID required
For the Kommo integration, use the signature_level field: "electronic_signature" (SES), "advanced_electronic_signature" (AES), "qualified_electronic_signature" (QES). The choice depends on the jurisdiction and document type.
Real-world case
Law firm (France, 30 people, Kommo + Yousign):
- Before: Won -> the secretary manually opened Yousign, uploaded the PDF, entered the client’s email, and sent it. 10–15 minutes per document. Signing status was only visible in Yousign — nothing appeared in Kommo.
- After: Won -> automatic Signature Request created ->
request.completed-> Note + stage change. In parallel: the signed PDF is saved to cloud storage and the link is added to the Kommo note. - Additional: notarial agreements required AES (OTP via SMS) — the parameter
signature_authentication_mode: "otp_sms"was added for that document type.
Who this is relevant for
- EU companies where DocuSign does not meet jurisdiction or data storage requirements
- Legal, financial, and notarial firms requiring QES or AES
- Companies with clients in France, Germany, or the Netherlands — Yousign natively supports local legislation
- EU startups where data must not leave the EU (GDPR + data residency)
Frequently asked questions
Does Yousign support templates for auto-filling?
Yes. Yousign -> Templates lets you create a document with placeholders ({{first_name}}, {{company}}). When creating a Signature Request via API, you can use a template_id instead of uploading a PDF: POST /signature_requests with "template_id": "tmpl_xxx" and "variables": {"first_name": "...", "company": "..."}. Templates are created once in the Yousign UI and then populated via API.
How to verify the authenticity of a Yousign webhook?
Yousign signs webhooks via HMAC-SHA256: the header is X-Yousign-Signature-256. The verification key (webhook_secret) is set when creating the Event Subscription. Verification: hmac.new(secret.encode(), request.data, sha256).hexdigest() must match the header value.
Yousign API v2 vs v3 — is there outdated code out there?
Yousign v2 (api.yousign.com/v2) — legacy, deprecated in 2024. Yousign v3 (api.yousign.app/v3) — the current version, a different domain and different object structure. If you see examples using /v2 — they are outdated. All new integrations must use v3.
How to add a second signer from your company (bilateral signing)?
Add a second signer — your company’s employee with their email — to the signers array. Yousign sends the request to both parties. Signing order is controlled by the signing_order field: "sequential" (the client signs first, then your employee) or "parallel" (both sign simultaneously).
Summary
- API: Bearer token, base URL
https://api.yousign.app/v3(v3, not v2) - Flow: upload PDF -> create Signature Request -> activate -> webhook -> Note in Kommo
- Signature levels: SES (default), AES (OTP SMS), QES (maximum legal weight)
- Webhook verification:
X-Yousign-Signature-256HMAC-SHA256 request.completed-> download signed PDF -> save URL in Kommo Note
If you have an EU team with eIDAS-compliant signing requirements and want to automate signing from Kommo — describe your document types and required signature level. Exceltic.dev will set up the integration within 2–3 business days.