Разработка интеграции Битрикс24 с Kaiten

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка интеграции Битрикс24 с Kaiten
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Разработка интеграции Битрикс24 с Kaiten

Kaiten — российский инструмент управления проектами с Kanban-досками, спринтами и временными треками. Компании используют его вместо Jira после ухода западных инструментов. Проблема та же, что и с любым PM-инструментом в связке с CRM: менеджеры в Битрикс24, команда в Kaiten, синхронизации нет — статусы расходятся, задачи дублируются.

Kaiten REST API

Kaiten предоставляет REST API, документация доступна на https://kaiten.io/api/. Аутентификация — Bearer-токен (Authorization: Bearer {token}). Токен создаётся в профиле пользователя или через OAuth для организации.

Ключевые эндпоинты:

Метод URL Назначение
GET /api/latest/cards Список карточек
POST /api/latest/cards Создать карточку
PATCH /api/latest/cards/{id} Обновить карточку
GET /api/latest/boards Список досок
GET /api/latest/columns Колонки доски
POST /api/latest/cards/{id}/comments Добавить комментарий

Kaiten поддерживает Webhooks — настраиваются в интерфейсе (Настройки → Вебхуки). Событие срабатывает при изменении карточки и отправляет POST на указанный URL с JSON-телом.

Класс-клиент для Kaiten API

namespace Local\KaitenIntegration;

class KaitenApiClient
{
    private string $baseUrl;
    private string $token;

    public function __construct(string $baseUrl, string $token)
    {
        $this->baseUrl = rtrim($baseUrl, '/');
        $this->token   = $token;
    }

    public function createCard(array $data): array
    {
        return $this->request('POST', '/api/latest/cards', $data);
    }

    public function updateCard(int $cardId, array $data): array
    {
        return $this->request('PATCH', "/api/latest/cards/{$cardId}", $data);
    }

    public function addComment(int $cardId, string $text): array
    {
        return $this->request('POST', "/api/latest/cards/{$cardId}/comments", ['text' => $text]);
    }

    private function request(string $method, string $path, array $data = []): array
    {
        $ch = curl_init($this->baseUrl . $path);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST  => $method,
            CURLOPT_HTTPHEADER     => [
                'Authorization: Bearer ' . $this->token,
                'Content-Type: application/json',
            ],
            CURLOPT_POSTFIELDS     => $method !== 'GET' ? json_encode($data) : null,
        ]);
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode >= 400) {
            throw new \RuntimeException("Kaiten API error {$httpCode}: {$response}");
        }

        return json_decode($response, true) ?? [];
    }
}

Таблица маппинга и синхронизации

CREATE TABLE b_local_kaiten_task_map (
    ID           SERIAL PRIMARY KEY,
    BITRIX_TASK_ID   INTEGER NOT NULL,
    KAITEN_CARD_ID   INTEGER NOT NULL,
    LAST_SYNC_AT     TIMESTAMP,
    SYNC_LOCK        VARCHAR(36) DEFAULT NULL,
    UNIQUE(BITRIX_TASK_ID),
    UNIQUE(KAITEN_CARD_ID)
);

Синхронизация задач Битрикс24 → Kaiten

При изменении задачи в Битрикс24 (событие OnTaskUpdate) обновляем карточку в Kaiten:

public static function onTaskUpdate(int $taskId, array $arFields): void
{
    $map = KaitenTaskMapTable::getByBitrixId($taskId);
    if (!$map || $map['SYNC_LOCK'] !== null) {
        return;
    }

    KaitenTaskMapTable::update($map['ID'], ['SYNC_LOCK' => uniqid()]);

    try {
        $client = self::getClient();
        $kaitenData = [];

        if (isset($arFields['TITLE'])) {
            $kaitenData['title'] = $arFields['TITLE'];
        }
        if (isset($arFields['DESCRIPTION'])) {
            $kaitenData['description'] = strip_tags($arFields['DESCRIPTION']);
        }
        if (isset($arFields['DEADLINE'])) {
            $kaitenData['due_date'] = date('Y-m-d', strtotime($arFields['DEADLINE']));
        }
        if (isset($arFields['STATUS'])) {
            // Переместить карточку в нужную колонку
            $columnId = StatusMapper::b24StatusToKaitenColumn($arFields['STATUS']);
            $kaitenData['column_id'] = $columnId;
        }

        if (!empty($kaitenData)) {
            $client->updateCard($map['KAITEN_CARD_ID'], $kaitenData);
        }

        KaitenTaskMapTable::update($map['ID'], [
            'SYNC_LOCK'    => null,
            'LAST_SYNC_AT' => new \Bitrix\Main\Type\DateTime(),
        ]);
    } catch (\Exception $e) {
        KaitenTaskMapTable::update($map['ID'], ['SYNC_LOCK' => null]);
        \Bitrix\Main\Diag\Debug::addToLog('KaitenSync: ' . $e->getMessage());
    }
}

Webhook из Kaiten → Битрикс24

Kaiten отправляет webhook при любом изменении карточки. Структура payload:

{
  "event": "card.updated",
  "data": {
    "id": 12345,
    "title": "Новое название задачи",
    "column_id": 678,
    "assignees": [{"id": 99, "username": "[email protected]"}]
  }
}

Обработчик webhook:

// /local/kaiten/webhook/index.php

$body    = file_get_contents('php://input');
$payload = json_decode($body, true);

// Валидация HMAC (если настроен secret в Kaiten)
$signature = $_SERVER['HTTP_X_KAITEN_SIGNATURE'] ?? '';
$expected  = hash_hmac('sha256', $body, KAITEN_WEBHOOK_SECRET);
if (!hash_equals($expected, $signature)) {
    http_response_code(403);
    exit;
}

$event    = $payload['event'] ?? '';
$cardId   = $payload['data']['id'] ?? null;
$columnId = $payload['data']['column_id'] ?? null;

if ($event !== 'card.updated' || !$cardId) {
    http_response_code(200);
    exit;
}

$map = KaitenTaskMapTable::getByKaitenId($cardId);
if (!$map || $map['SYNC_LOCK'] !== null) {
    http_response_code(200);
    exit;
}

KaitenTaskMapTable::update($map['ID'], ['SYNC_LOCK' => uniqid()]);

// Обновить статус задачи Битрикс24
if ($columnId) {
    $b24Status = StatusMapper::kaitenColumnToB24Status($columnId);
    $task = new \CTasks();
    $task->Update($map['BITRIX_TASK_ID'], ['STATUS' => $b24Status], false);
}

KaitenTaskMapTable::update($map['ID'], ['SYNC_LOCK' => null]);
http_response_code(200);

Маппинг колонок Kaiten → статусы Битрикс24

В Kaiten вместо статусов — колонки с ID. Маппинг хранится в настройках модуля:

Kaiten column_id Название колонки Битрикс24 STATUS
101 Бэклог 1 (Новая)
102 В работе 3 (В работе)
103 На ревью 4 (Ждёт контроля)
104 Готово 5 (Завершена)

ID колонок получаем через GET /api/latest/boards/{boardId}/columns и храним в b_option.

Создание карточки из сделки CRM

Полезный сценарий: при переходе сделки на стадию «Разработка» — автоматически создать карточку в Kaiten на нужной доске. Реализуется через бизнес-процесс или через OnCrmDealUpdate:

if ($arFields['STAGE_ID'] === 'DEVELOPMENT') {
    $client  = KaitenApiClientFactory::create();
    $card    = $client->createCard([
        'title'    => 'Deal #' . $dealId . ': ' . $arFields['TITLE'],
        'board_id' => KAITEN_DEV_BOARD_ID,
        'column_id' => KAITEN_BACKLOG_COLUMN_ID,
        'description' => $arFields['COMMENTS'],
    ]);
    \CCrmDeal::Update($dealId, ['UF_KAITEN_CARD_ID' => $card['id']], false);
}

Сроки разработки

Вариант Состав Срок
Односторонняя (Битрикс24 → Kaiten) Создание и обновление карточек 3–5 дней
Двусторонняя синхронизация Статусы, комментарии, маппинг пользователей 7–10 дней
С автосозданием из CRM Воронка → создание карточки, отчёты 10–14 дней