Fibery - гибкий workspace: базы данных, Kanban, дорожные карты, документы - всё в одном, с настраиваемой схемой данных. В отличие от Notion (документы с базами) или Linear (жёсткая структура), Fibery позволяет строить произвольные связи между сущностями. Для B2B SaaS и продуктовых компаний, использующих Fibery для управления разработкой и Kommo для продаж, интеграция позволяет: создавать Fibery-сущность при закрытии сделки, передавать данные клиента и сумму, связывать с нужным проектом или продуктом.
Fibery API использует Bearer token (Personal Access Token). API - REST + GraphQL. REST-операции: POST /api/commands с fibery.entity/create командой для создания новой сущности. Схема приложения определяет доступные типы (Types) и поля.
Fibery App - набор связанных типов данных (Client, Project, Task…). Каждый Fibery тип имеет уникальное имя пространства (appName/typeName). Перед написанием интеграции нужно узнать точные имена типов из схемы своего workspace.
Получение схемы Fibery
import requests, os
FIBERY_TOKEN = os.environ["FIBERY_TOKEN"]
FIBERY_ACCOUNT = os.environ["FIBERY_ACCOUNT"] # yourworkspace.fibery.io
FIBERY_BASE = f"https://{FIBERY_ACCOUNT}/api"
FIBERY_HDR = {
"Authorization": f"Token {FIBERY_TOKEN}",
"Content-Type": "application/json",
}
def get_schema():
r = requests.post(
f"{FIBERY_BASE}/commands",
headers=FIBERY_HDR,
json=[{"command": "fibery.schema/query"}],
)
for type_info in r.json()[0].get("result", {}).get("fibery/types", []):
name = type_info.get("fibery/name", "")
if not name.startswith("fibery/"): # пропустить системные типы
print(f"Type: {name}")
for field in type_info.get("fibery/fields", []):
print(f" Field: {field.get('fibery/name')} ({field.get('fibery/type', {}).get('fibery/name', '')})")
# Запустить один раз для получения имён типов
get_schema()
Реализация: создание сущности в Fibery при Closed Won
from flask import Flask, request, jsonify
import uuid
app = Flask(__name__)
KOMMO_SUBDOMAIN = os.environ["KOMMO_SUBDOMAIN"]
KOMMO_TOKEN = os.environ["KOMMO_ACCESS_TOKEN"]
CLOSED_WON_ID = int(os.environ["KOMMO_CLOSED_WON_ID"])
# Имена типов из схемы вашего Fibery workspace
FIBERY_CLIENT_TYPE = os.environ.get("FIBERY_CLIENT_TYPE", "Sales/Client")
KOMMO_BASE = f"https://{KOMMO_SUBDOMAIN}.kommo.com/api/v4"
KOMMO_HDR = {"Authorization": f"Bearer {KOMMO_TOKEN}", "Content-Type": "application/json"}
def get_lead_contact(lead_id: int) -> tuple[dict, dict]:
r = requests.get(
f"{KOMMO_BASE}/leads/{lead_id}",
headers=KOMMO_HDR,
params={"with": "contacts"},
)
lead = r.json()
contacts = lead.get("_embedded", {}).get("contacts", [])
contact = {}
if contacts:
rc = requests.get(
f"{KOMMO_BASE}/contacts/{contacts[0]['id']}",
headers=KOMMO_HDR,
params={"with": "custom_fields_values"},
)
contact = rc.json()
return lead, contact
def get_email(contact: dict) -> str:
for cf in contact.get("custom_fields_values", []) or []:
if cf.get("field_code") == "EMAIL":
vals = cf.get("values", [])
if vals:
return vals[0].get("value", "")
return ""
def create_fibery_entity(type_name: str, fields: dict) -> str:
entity_id = str(uuid.uuid4())
r = requests.post(
f"{FIBERY_BASE}/commands",
headers=FIBERY_HDR,
json=[{
"command": "fibery.entity/create",
"args": {
"type": type_name,
"entity": {"fibery/id": entity_id, **fields},
},
}],
)
r.raise_for_status()
result = r.json()
if isinstance(result, list) and result:
return result[0].get("result", {}).get("fibery/id", entity_id)
return entity_id
def add_note(lead_id: int, text: str):
requests.post(
f"{KOMMO_BASE}/notes",
headers=KOMMO_HDR,
json=[{
"entity_id": lead_id,
"entity_type": "leads",
"note_type": "common",
"params": {"text": text},
}],
)
@app.route("/webhooks/kommo", methods=["POST"])
def kommo_webhook():
data = request.json or {}
for lead_data in data.get("leads", {}).get("status", []):
lead_id = lead_data.get("id")
new_status = lead_data.get("status_id")
if new_status != CLOSED_WON_ID:
continue
lead, contact = get_lead_contact(lead_id)
client_name = contact.get("name", f"Lead #{lead_id}")
deal_amount = float(lead.get("price") or 0)
email = get_email(contact)
# Поля зависят от схемы вашего Fibery workspace
# Ниже - пример для типа "Sales/Client"
fibery_fields = {
"Sales/Name": client_name,
"Sales/Email": email,
"Sales/DealAmount": deal_amount,
"Sales/KommoLeadId": str(lead_id),
"Sales/DealName": lead.get("name", ""),
}
entity_id = create_fibery_entity(FIBERY_CLIENT_TYPE, fibery_fields)
add_note(
lead_id,
f"Fibery: создана сущность {FIBERY_CLIENT_TYPE} (ID: {entity_id}) для клиента {client_name}.",
)
return jsonify({"status": "ok"}), 200
Обновление существующей сущности
def update_fibery_entity(entity_id: str, type_name: str, fields: dict):
requests.post(
f"{FIBERY_BASE}/commands",
headers=FIBERY_HDR,
json=[{
"command": "fibery.entity/update",
"args": {
"type": type_name,
"entity": {"fibery/id": entity_id, **fields},
},
}],
)
Для обновления сохраните fibery_entity_id в кастомном поле Kommo (аналогично другим интеграциям). При повторных изменениях сделки - проверяйте поле и обновляйте сущность, а не создавайте новую.
Фибери Relations: связать Client с Project
def create_relation(entity_id: str, related_entity_id: str,
relation_field: str, entity_type: str):
requests.post(
f"{FIBERY_BASE}/commands",
headers=FIBERY_HDR,
json=[{
"command": "fibery.entity/add-collection-items",
"args": {
"type": entity_type,
"field": relation_field,
"entity": {"fibery/id": entity_id},
"items": [{"fibery/id": related_entity_id}],
},
}],
)
Связать созданного Client с существующим Project (например, продукт в вашем Fibery):
project_id = os.environ.get("FIBERY_DEFAULT_PROJECT_ID", "")
if project_id:
create_relation(entity_id, project_id, "Sales/Projects", FIBERY_CLIENT_TYPE)
Получение данных из Fibery в Kommo
def get_fibery_entity(entity_id: str, type_name: str, fields: list[str]) -> dict:
r = requests.post(
f"{FIBERY_BASE}/commands",
headers=FIBERY_HDR,
json=[{
"command": "fibery.entity/query",
"args": {
"query": {
"q/from": type_name,
"q/select": ["fibery/id"] + fields,
"q/where": ["=", ["fibery/id"], "$id"],
"q/limit": 1,
},
"params": {"$id": entity_id},
},
}],
)
result = r.json()
if isinstance(result, list) and result:
items = result[0].get("result", [])
return items[0] if items else {}
return {}
Для кого актуально
Продуктовые компании и агентства, использующие Fibery как основной workspace для разработки и управления клиентами. Особенно полезно когда в Fibery хранится информация о продукте, фичах, клиентских запросах - и каждый новый клиент из Kommo должен автоматически появляться в этом контексте.
Аналогичная интеграция для software PM: Kommo + Shortcut.
Часто задаваемые вопросы
Как получить Personal Access Token в Fibery?
Fibery Settings -> API -> Personal Access Tokens -> Create Token. Токен не истекает автоматически. Каждая интеграция должна использовать отдельный токен. Для team-интеграций лучше создать отдельного bot-пользователя в Fibery.
Как обрабатывать Fibery Rich Text поля (документы)?
Fibery Rich Text хранится в формате Prosemirror JSON. Для записи текста через API передавайте Markdown (некоторые поля поддерживают Markdown-импорт) или используйте формат Fibery Document: {"type": "doc", "content": [{"type": "paragraph", "content": [{"type": "text", "text": "..."}]}]}.
Поддерживает ли Fibery webhooks для уведомления внешних систем?
В 2026 году Fibery предоставляет webhooks в экспериментальном режиме. Более надёжный подход - polling через Fibery API по расписанию (каждые 5 минут): запрашивать сущности с updatedAt > lastCheck. Для production интеграций это предпочтительнее до стабилизации webhook API.
Итог
Kommo + Fibery - гибкий workspace из CRM без Zapier:
- Bearer Token,
POST /api/commandsсfibery.entity/create - UUID генерировать локально и передавать в
fibery/id - Имена типов получить через
fibery.schema/queryодин раз перед интеграцией - Relations:
fibery.entity/add-collection-itemsдля связи Client -> Project - Кастомное поле Kommo хранит Fibery entity ID для последующих обновлений
Если нужна интеграция Kommo с Fibery или другим workspace-инструментом - опишите задачу команде Exceltic.dev.