Fibery is a flexible workspace: databases, Kanban boards, roadmaps, documents - all in one place with a customizable data schema. Unlike Notion (documents with databases) or Linear (rigid structure), Fibery lets you build arbitrary relations between entities. For B2B SaaS and product companies that use Fibery for development management and Kommo for sales, the integration enables: creating a Fibery entity when a deal is closed, passing client data and deal amount, and linking to the relevant project or product.
Fibery API uses a Bearer token (Personal Access Token). The API is REST + GraphQL. REST operations: POST /api/commands with the fibery.entity/create command to create a new entity. The app schema defines the available types and fields.
Fibery App is a set of related data types (Client, Project, Task…). Each Fibery type has a unique namespace name (appName/typeName). Before writing the integration, you need to look up the exact type names from your workspace schema.
Retrieving the Fibery Schema
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()
Implementation: Creating a Fibery Entity on 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
Updating an Existing Entity
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},
},
}],
)
To support updates, store the fibery_entity_id in a custom Kommo field (same approach as with other integrations). When the deal is updated again - check the field and update the existing entity rather than creating a new one.
Fibery Relations: Linking a Client to a 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}],
},
}],
)
Link the created Client to an existing Project (for example, a product in your Fibery workspace):
project_id = os.environ.get("FIBERY_DEFAULT_PROJECT_ID", "")
if project_id:
create_relation(entity_id, project_id, "Sales/Projects", FIBERY_CLIENT_TYPE)
Retrieving Fibery Data into 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 {}
Who This Is For
Product companies and agencies that use Fibery as their primary workspace for development and client management. Especially useful when Fibery stores information about your product, features, and client requests - and every new client from Kommo should automatically appear in that context.
A similar integration for software project managers: Kommo + Shortcut.
Frequently Asked Questions
How do I get a Personal Access Token in Fibery?
Go to Fibery Settings -> API -> Personal Access Tokens -> Create Token. The token does not expire automatically. Each integration should use a separate token. For team integrations, it is better to create a dedicated bot user in Fibery.
How do I handle Fibery Rich Text fields (documents)?
Fibery Rich Text is stored in Prosemirror JSON format. To write text via the API, pass Markdown (some fields support Markdown import) or use the Fibery Document format: {"type": "doc", "content": [{"type": "paragraph", "content": [{"type": "text", "text": "..."}]}]}.
Does Fibery support webhooks for notifying external systems?
As of 2026, Fibery provides webhooks in experimental mode. A more reliable approach is polling via the Fibery API on a schedule (every 5 minutes): query entities where updatedAt > lastCheck. For production integrations this is preferable until the webhook API stabilizes.
Summary
Kommo + Fibery - a flexible workspace connected to your CRM without Zapier:
- Bearer Token,
POST /api/commandswithfibery.entity/create - Generate the UUID locally and pass it in
fibery/id - Retrieve type names via
fibery.schema/queryonce before building the integration - Relations:
fibery.entity/add-collection-itemsto link Client -> Project - A custom Kommo field stores the Fibery entity ID for subsequent updates
If you need an integration between Kommo and Fibery or another workspace tool - describe the task to the Exceltic.dev team.