Kommo + Docuseal: автоматическое подписание документов через open-source платформу
Docuseal — open-source платформа электронной подписи: self-hosted или cloud, без вендор-локина и с REST API. Для команд, которые хотят e-sign без $25+/пользователь/месяц за DocuSign или Adobe Sign, Docuseal — функциональная альтернатива с полным API-доступом. Без интеграции с Kommo менеджер создаёт submission вручную после Won. С интеграцией Won автоматически отправляет контракт из шаблона с заполненными данными сделки — клиент получает ссылку для подписания в минуту.
Open-source vs SaaS для e-sign
Docuseal self-hosted (Docker) даёт:
— Полный контроль данных — все документы на вашем сервере
— Неограниченное количество документов без тарифных лимитов
— EU GDPR compliance без передачи данных американским SaaS
— Единоразовые затраты на хостинг вместо $25–40/пользователь/месяц
Docuseal cloud (docuseal.co) — тот же API, без управления инфраструктурой. Для небольших команд удобнее.
Оба варианта используют одинаковый REST API. Для кастомной интеграции с Kommo это означает: один код, легко переключить между self-hosted и cloud.
Что синхронизируется
Kommo -> Docuseal:
— Won -> создать submission из шаблона с полями из сделки (имя, email, сумма, тариф)
— Won -> установить порядок подписантов (клиент -> внутренняя подпись)
— Автоматически отправить email с ссылкой на подпись
Docuseal -> Kommo:
— submission.completed -> Note: «Docuseal: документ подписан всеми сторонами» + смена этапа
— submission.declined -> Note + задача: «Клиент отклонил подписание»
— submission.expired -> Note + задача: «Срок подписания истёк»
— form.completed (один подписант завершил) -> Note: «{имя} подписал»
Архитектура
Kommo Webhook: сделка перешла в Won
↓ Backend
1. GET /api/v4/leads/{id} + contacts
-> email, имя, тариф, сумма
2. Docuseal API: POST /api/submissions
-> template_id, submitters с полями из сделки
3. Kommo: PATCH /leads/{id}
-> docuseal_submission_id = submission.id
4. Kommo: POST /leads/{id}/notes
-> «Docuseal: контракт отправлен на подпись {email}»
Docuseal Webhook: submission.completed
↓ Backend
1. Верификация X-Docuseal-Signature
2. Найти сделку по docuseal_submission_id
3. Kommo: PATCH /leads/{id} -> смена этапа «Контракт подписан»
4. Kommo: POST /notes -> «Docuseal: все подписи собраны»
Docuseal API: ключевые запросы
Base URL (cloud): https://api.docuseal.co.
Base URL (self-hosted): https://your-docuseal-domain.com.
Аутентификация: X-Auth-Token: {api_key} (взять в настройках аккаунта).
Создать submission из шаблона:
import requests
DOCUSEAL_API_KEY = "your_api_key"
DOCUSEAL_BASE_URL = "https://api.docuseal.co" # или self-hosted URL
headers = {
"X-Auth-Token": DOCUSEAL_API_KEY,
"Content-Type": "application/json"
}
def create_submission(template_id: int, submitters: list,
send_email: bool = True) -> dict:
resp = requests.post(
f"{DOCUSEAL_BASE_URL}/api/submissions",
headers=headers,
json={
"template_id": template_id,
"send_email": send_email,
"submitters": submitters
}
)
resp.raise_for_status()
return resp.json()
def on_deal_won(lead: dict, contact: dict):
email = get_contact_email(contact)
name = contact["name"]
plan = get_custom_field(lead, PLAN_FIELD_ID) or "Growth"
amount = lead.get("price", 0)
# submitters - порядок: сначала клиент, потом внутренняя подпись
submitters = [
{
"email": email,
"name": name,
"role": "Client",
"values": {
"client_name": name,
"client_email": email,
"plan": plan,
"contract_amount": str(amount),
"contract_date": datetime.now().strftime("%d.%m.%Y"),
}
},
{
"email": INTERNAL_SIGNER_EMAIL,
"name": INTERNAL_SIGNER_NAME,
"role": "Company",
}
]
submission = create_submission(DOCUSEAL_TEMPLATE_ID, submitters)
submission_id = submission[0]["submission_id"] # возвращает список submitters
update_kommo_deal(lead["id"], {"docuseal_submission_id": str(submission_id)})
create_kommo_note(lead["id"],
f"Docuseal: контракт #{submission_id} отправлен на подпись -> {email}")
Получить статус submission:
def get_submission_status(submission_id: int) -> dict:
resp = requests.get(
f"{DOCUSEAL_BASE_URL}/api/submissions/{submission_id}",
headers=headers
)
resp.raise_for_status()
return resp.json()
Обработка Docuseal Webhook:
import hmac, hashlib
from flask import Flask, request, abort
app = Flask(__name__)
DOCUSEAL_WEBHOOK_SECRET = "your_webhook_secret"
def verify_signature(payload: bytes, sig_header: str) -> bool:
expected = hmac.new(
DOCUSEAL_WEBHOOK_SECRET.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, sig_header)
@app.route("/webhooks/docuseal", methods=["POST"])
def docuseal_webhook():
sig = request.headers.get("X-Docuseal-Signature", "")
if not verify_signature(request.data, sig):
abort(403)
payload = request.json
event = payload.get("event_type")
submission_id = str(payload.get("data", {}).get("submission_id", ""))
deal_id = find_deal_by_field("docuseal_submission_id", submission_id)
if not deal_id:
return "", 200
if event == "submission.completed":
update_kommo_deal(deal_id, {"stage_id": STAGE_CONTRACT_SIGNED})
create_kommo_note(deal_id,
"Docuseal: все подписи собраны - документ оформлен")
elif event == "submission.declined":
create_kommo_note(deal_id, "Docuseal: клиент отклонил подписание")
create_kommo_task(deal_id, "Обсудить условия - Docuseal зафиксировал отказ")
elif event == "submission.expired":
create_kommo_note(deal_id, "Docuseal: срок подписания истёк")
create_kommo_task(deal_id, "Отправить новую ссылку на подписание")
elif event == "form.completed":
submitter_name = payload.get("data", {}).get("submitter", {}).get("name", "")
create_kommo_note(deal_id, f"Docuseal: {submitter_name} подписал")
return "", 200
Webhook настройка в Docuseal: Settings -> Webhooks -> Add Webhook. Указать URL и secret. События: submission.completed, submission.declined, submission.expired, form.completed.
Self-hosted: установка за 5 минут
# docker-compose.yml
version: '3'
services:
docuseal:
image: docuseal/docuseal:latest
ports:
- "3000:3000"
volumes:
- ./data:/data
environment:
- SECRET_KEY_BASE=your_secret_key
- DATABASE_URL=sqlite3:///data/docuseal.sqlite3
docker compose up -d -> Docuseal доступен на порту 3000. Для production: Nginx reverse proxy + SSL + PostgreSQL вместо SQLite.
Реальный кейс
Юридическая компания (EU, 50–70 контрактов в месяц, Kommo + Docuseal self-hosted):
- До: DocuSign $40/пользователь/месяц × 8 человек = $320/мес. Шаблоны настраивались вручную, данные из Kommo копировались. Задержка отправки 30–90 минут.
- После: Docuseal self-hosted на VPS €20/мес. Won -> контракт с заполненными данными за 8 секунд. Сохранение €3,620/год.
- Дополнительно: EU GDPR — все документы на собственном сервере, не передаются американским SaaS. Аргумент при работе с EU-клиентами.
Для кого актуально
- Команды с GDPR-требованиями к хранению документов (юридические, медицинские, финансовые)
- Те, кто хочет контролировать затраты — self-hosted убирает per-user-per-month плату
- Разработчики, которым нужен открытый API без закрытых ограничений
- 20+ контрактов в месяц — при меньшем объёме ручная работа ещё оправдана
Часто задаваемые вопросы
Docuseal vs DocuSign: реально ли для enterprise?
Docuseal покрывает 80% корпоративных use cases: шаблоны, порядок подписантов, аудит-лог, скачивание подписанного PDF. Не хватает: расширенного workflow (conditional routing), Salesforce-нативной интеграции, enterprise SSO (в roadmap). Для команд до 50 человек — достаточно.
Какие форматы шаблонов поддерживает Docuseal?
PDF с полями для заполнения. Можно создавать шаблоны прямо в Docuseal UI (drag-and-drop поля на PDF). API принимает template_id — ID шаблона из Docuseal. Один шаблон можно использовать многократно с разными данными через API.
Docuseal юридически значим в EU?
Да. Подписи через Docuseal соответствуют eIDAS (EU Electronic Signatures Regulation) как Simple Electronic Signature (SES). Для квалифицированной подписи (QES) нужен отдельный провайдер идентификации — Docuseal её не генерирует.
Как загружать шаблоны через API?
POST /api/templates с multipart/form-data — загрузить PDF-файл. Ответ содержит id шаблона для дальнейшего использования в submissions. Шаблоны можно создавать и через UI — API использует тот же ID.
Итого
- Docuseal:
X-Auth-Tokenв заголовке,https://api.docuseal.co(cloud) или self-hosted URL - Создать submission:
POST /api/submissionsсtemplate_idи массивомsubmitters submitters[].values— автозаполнение полей шаблона данными из Kommo- Webhook: HMAC-SHA256 через
X-Docuseal-Signature - Self-hosted: Docker, данные на вашем сервере, EU GDPR без вопросов
- Ключевые события:
submission.completed,submission.declined,form.completed
Если вы хотите автоматизировать подписание контрактов из Kommo через Docuseal — опишите структуру шаблонов и порядок подписантов. Exceltic.dev настроит интеграцию.