Kommo + Oneflow: автоматическая отправка контрактов из воронки продаж
Oneflow — шведская платформа управления жизненным циклом контрактов (CLM): создание, согласование, электронная подпись, хранение. В отличие от PandaDoc или DocuSign, Oneflow специализируется на интерактивных HTML-контрактах (не PDF) — клиент может редактировать отдельные поля прямо в браузере до подписания. GDPR-compliant, данные в EU. Без интеграции с Kommo менеджер создаёт контракт вручную. С интеграцией Won -> контракт с заполненными данными из сделки уходит клиенту за секунды.
Oneflow vs PandaDoc vs Docuseal для EU-команд
| Платформа | Формат | Хранение данных | EU-фокус | API |
|---|---|---|---|---|
| Oneflow | HTML-контракты | Швеция / EU | Да, шведский вендор | REST + webhooks |
| PandaDoc | PDF + rich content | US (AWS) | Частично | REST |
| Docuseal | Self-hosted или EU cloud | Да (self-hosted) | REST | |
| DocuSign | US | Нет EU-cloud | REST |
Oneflow выбирают EU-команды с требованиями к data residency и где контракты — не просто форма для подписи, а инструмент переговоров (встроенный чат, redlining, версии).
Что синхронизируется
Kommo -> Oneflow:
— Won -> создать контракт из шаблона с данными из сделки (имя, email, компания, сумма, тариф)
— Won -> установить участников (клиент -> внутренний подписант)
— Won -> отправить контракт на подписание
Oneflow -> Kommo:
— contract.signed (все подписали) -> Note + смена этапа «Контракт подписан»
— contract.participant_signed (один из участников подписал) -> Note
— contract.declined -> Note + задача: «Клиент отклонил контракт»
— contract.expired -> Note + задача: «Срок подписания истёк»
Oneflow API: ключевые запросы
Base URL: https://api.oneflow.com/v1.
Аутентификация: x-oneflow-api-token: {api_token} (персональный токен из настроек).
Дополнительно: x-oneflow-user-email: {email} — от имени какого пользователя действуем.
import requests
ONEFLOW_TOKEN = "your_api_token"
ONEFLOW_USER_EMAIL = "sales@yourcompany.com"
ONEFLOW_BASE_URL = "https://api.oneflow.com/v1"
HEADERS = {
"x-oneflow-api-token": ONEFLOW_TOKEN,
"x-oneflow-user-email": ONEFLOW_USER_EMAIL,
"Content-Type": "application/json",
}
def get_templates(workspace_id: str) -> list:
resp = requests.get(
f"{ONEFLOW_BASE_URL}/templates",
headers=HEADERS,
params={"workspace_id": workspace_id}
)
resp.raise_for_status()
return resp.json().get("data", [])
def create_contract(template_id: str, workspace_id: str,
name: str, parties: list) -> dict:
# parties: список участников-компаний/физлиц с ролями
payload = {
"template_id": template_id,
"workspace_id": workspace_id,
"name": name,
"parties": parties,
}
resp = requests.post(
f"{ONEFLOW_BASE_URL}/contracts",
headers=HEADERS,
json=payload
)
resp.raise_for_status()
return resp.json()
def update_contract_data_fields(contract_id: str, data_fields: list) -> None:
# Заполнить кастомные поля контракта (тариф, сумма, дата)
for field in data_fields:
resp = requests.patch(
f"{ONEFLOW_BASE_URL}/contracts/{contract_id}/data_fields/{field['id']}",
headers=HEADERS,
json={"value": field["value"]}
)
resp.raise_for_status()
def publish_contract(contract_id: str) -> dict:
# Отправить контракт участникам для подписания
resp = requests.post(
f"{ONEFLOW_BASE_URL}/contracts/{contract_id}/publish",
headers=HEADERS,
json={}
)
resp.raise_for_status()
return resp.json()
def on_deal_won(lead: dict, contact: dict):
email = get_contact_email(contact)
name = contact["name"]
company = get_custom_field(lead, COMPANY_FIELD_ID) or name
plan = get_custom_field(lead, PLAN_FIELD_ID) or "Growth"
amount = lead.get("price", 0)
from datetime import datetime
today = datetime.now().strftime("%d.%m.%Y")
# Структура участников: клиент + наша компания
parties = [
{
"type": "company",
"name": company,
"participants": [{
"name": name,
"email": email,
"signatory": True,
}]
},
{
"type": "company",
"name": "Your Company Name",
"participants": [{
"name": INTERNAL_SIGNER_NAME,
"email": INTERNAL_SIGNER_EMAIL,
"signatory": True,
}]
}
]
contract = create_contract(
template_id=ONEFLOW_TEMPLATE_ID,
workspace_id=ONEFLOW_WORKSPACE_ID,
name=f"Договор с {company} - {plan}",
parties=parties,
)
contract_id = contract["id"]
# Заполнить поля шаблона (id полей взять из Oneflow template editor)
data_fields = [
{"id": FIELD_PLAN_ID, "value": plan},
{"id": FIELD_AMOUNT_ID, "value": str(amount)},
{"id": FIELD_DATE_ID, "value": today},
{"id": FIELD_COMPANY_ID, "value": company},
]
update_contract_data_fields(contract_id, data_fields)
# Опубликовать (отправить участникам)
publish_contract(contract_id)
update_kommo_deal(lead["id"], {"oneflow_contract_id": str(contract_id)})
create_kommo_note(lead["id"],
f"Oneflow: контракт #{contract_id} отправлен на подпись -> {email}")
Обработка Oneflow Webhook:
from flask import Flask, request
app = Flask(__name__)
@app.route("/webhooks/oneflow", methods=["POST"])
def oneflow_webhook():
payload = request.json
event_type = payload.get("event_type")
contract_id = str(payload.get("contract_id", ""))
deal_id = find_deal_by_field("oneflow_contract_id", contract_id)
if not deal_id:
return "", 200
if event_type == "contract.signed":
update_kommo_deal(deal_id, {"stage_id": STAGE_CONTRACT_SIGNED})
create_kommo_note(deal_id, "Oneflow: все стороны подписали контракт")
elif event_type == "contract.participant_signed":
signer = payload.get("participant", {}).get("name", "")
create_kommo_note(deal_id, f"Oneflow: {signer} подписал контракт")
elif event_type == "contract.declined":
participant = payload.get("participant", {}).get("name", "")
create_kommo_note(deal_id,
f"Oneflow: {participant} отклонил контракт")
create_kommo_task(deal_id,
"Уточнить возражения - контракт отклонён в Oneflow")
elif event_type == "contract.expired":
create_kommo_note(deal_id, "Oneflow: срок подписания контракта истёк")
create_kommo_task(deal_id, "Отправить новую версию контракта")
return "", 200
Настройка Webhook в Oneflow: Settings -> Integrations -> Webhooks -> Add webhook. Указать URL и выбрать события.
Интерактивные HTML-контракты: ключевое отличие Oneflow
В Oneflow контракт — не PDF, а HTML-документ. Клиент может:
— Комментировать конкретные клаузы прямо в браузере
— Редактировать согласованные поля (если разрешено шаблоном)
— Видеть историю изменений
Для длинных B2B-переговоров это критично: вместо отправки 5 версий PDF — один живой документ с версионированием. После завершения переговоров — одна кнопка «Подписать».
Реальный кейс
IT-консалтинг (Швеция, 20–30 контрактов в месяц, Kommo + Oneflow):
- До: PandaDoc + ручное создание. Контракт уходил клиенту через 2–3 часа после Won. 40% контрактов возвращались с запросами на правки — начиналась email-переписка с PDF-версиями.
- После: Won -> контракт через Oneflow за 30 секунд. Клиент редактирует несогласные пункты прямо в браузере — email с версиями исчезла. Среднее время от Won до подписания: 1.3 дня (было 4.7 дня).
- Дополнительно: EU GDPR — все контракты хранятся на серверах в Швеции. Аргумент при работе с EU-клиентами с DPA-требованиями.
Для кого актуально
- EU-компании с GDPR-требованиями к хранению контрактных данных
- B2B с переговорным процессом: длинные контракты, редлайнинг, несколько клауз
- Агентства и консалтинг с 10+ контрактами в месяц
- Команды, уставшие от «отправь PDF, получи правки, отправь снова»
Часто задаваемые вопросы
Oneflow юридически значим в EU?
Да. Подписи через Oneflow соответствуют eIDAS как Simple Electronic Signature (SES). Для квалифицированной подписи (QES) — нужен дополнительный ID-провайдер. Для большинства B2B контрактов SES достаточно.
Где найти Template ID и Field ID в Oneflow?
Template ID: Oneflow Dashboard -> Templates -> нужный шаблон -> URL (/templates/{id}). Field ID: открыть шаблон в редакторе -> выбрать поле данных -> в правой панели виден ID. Или через GET /templates/{id} — возвращает все поля с ID.
Oneflow поддерживает несколько подписантов и порядок подписания?
Да. В participants можно указать signatory_order для каждого участника — контракт отправляется следующему только после подписи предыдущего. Параллельное подписание (без порядка) — по умолчанию.
Как получить подписанный PDF из Oneflow через API?
GET /contracts/{id}/pdf -> возвращает PDF с подписями. Удобно сохранить автоматически в облако или прикрепить к сделке в Kommo как файл.
Итого
- Oneflow API:
x-oneflow-api-token+x-oneflow-user-emailв заголовках - Создать контракт:
POST /contracts-> update data fields ->POST /contracts/{id}/publish - Webhook: события
contract.signed,contract.participant_signed,contract.declined - HTML-контракты: переговоры, редлайнинг, история версий — преимущество над PDF-based инструментами
- EU data residency: данные в Швеции, GDPR-compliant из коробки
Если вы используете Oneflow и Kommo и хотите автоматизировать создание контрактов при Won — опишите структуру шаблонов и порядок подписантов. Exceltic.dev настроит интеграцию.