Skip to content

Работа через REST API ​

Всё, что делается в интерфейсе, платформа умеет делать и запросом: подключить источник, собрать датасет, построить виджет, получить данные. Часть возможностей существует только здесь — перечень в разделе Ограничения.

Эта страница — про общие правила: куда обращаться, как авторизоваться, как устроены ответы и ошибки. Разбор отдельных подсистем — по ссылкам в конце.

Адрес и описание ​

Единого адреса у платформы нет: она ставится в контуре организации, поэтому база — это адрес вашей установки плюс /api. Дальше в примерах он записан как http://<адрес>.

Машиночитаемое описание всех методов платформа отдаёт сама, в формате OpenAPI 3:

bash
curl -s http://<адрес>/api/v3/api-docs > openapi.json

В текущей версии это 140 путей и 202 операции. Файл годится и для генератора клиента, и для импорта в Postman или Insomnia — отдельного SDK платформа не поставляет.

Авторизация ​

Все методы, кроме входа, требуют заголовок Authorization: Bearer <токен>. Токенов два вида, и они решают разные задачи.

Токен сеанса: вход логином и паролем ​

bash
curl -s -X POST http://<адрес>/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"reader","password":"…"}'

Ответ:

json
{
  "data": {
    "token": "eyJhbGciOi…",
    "refresh_token": "0f2c…",
    "token_type": "Bearer",
    "expires_in": 900
  },
  "success": true
}

expires_in — 900 секунд, то есть пятнадцать минут. Дальше либо новый вход, либо продление через POST /api/auth/refresh с телом {"refresh_token": "…"}. POST /api/auth/logout отзывает все обновляющие токены пользователя.

Дальше в примерах токен подставляется из переменной T — положите в неё своё значение, чтобы команды можно было копировать как есть:

bash
T="eyJhbGciOi…"

Права попадают в токен в момент выдачи

Токен несёт список групп пользователя таким, каким он был при входе. Добавили человека в группу — его текущий токен об этом не узнает, и запрос по-прежнему ответит 403 Доступ запрещён. Нужен новый вход. То же касается интерфейса: пользователь должен выйти и войти заново, иначе новые права не появятся.

Постоянный токен: для интеграций ​

Токен сеанса живёт четверть часа и для скрипта в расписании неудобен. Для постоянного доступа заводится API-токен — тот же, что выдаётся AI-агенту:

bash
curl -s -X POST http://<адрес>/api/mcp-tokens \
  -H "Authorization: Bearer $T" -H "Content-Type: application/json" \
  -d '{"name":"выгрузка в хранилище","description":"ночной скрипт"}'

В ответе придёт строка вида dwmcp_… — она показывается один раз, сохраните её сразу.

Выпуск разрешён не всем: нужен подходящий тип учётной записи, членство в группе доступа и включённый администратором рубильник — условия перечислены в разделе Кому разрешено. Если чего-то не хватает, запрос отвечает «Выпуск и работа MCP-токенов отключены администратором платформы» или отказом по правам.

Этот токен работает не только для AI-агента

Несмотря на название, dwmcp_… принимается любым методом REST API — платформа различает вид токена по префиксу. Проверено: список виджетов и запрос данных виджета этим токеном отрабатывают штатно. Действует он от имени владельца и с его правами, приостанавливается и отзывается в профиле — выпуск и управление токенами.

Формат ответа ​

Успешный и неуспешный ответы имеют одинаковую оболочку — по полю success их и различают:

json
{ "data": { … }, "success": true }
{ "error": { "code": 404, "message": "Виджет не найден (id 999999)",
             "timestamp": "2026-08-27T00:12:03Z" }, "success": false }

Сообщение в message человекочитаемое и на русском — его можно показывать пользователю скрипта как есть. Ошибки валидации добавляют объект errors с разбором по полям:

json
{ "error": { "code": 422, "errors": { "parameters[0].primitiveType": "must not be blank" },
             "message": "Ошибка валидации" }, "success": false }
КодКогда приходит
400Тело разобрано, но запрос невыполним: «Сравнить можно только с соседней стадией», «К стадии можно привязать только командное пространство»
401Токена нет, он истёк или подпись не сходится
403Прав не хватает — роли, типа учётной записи или членства в группе
404Объекта с таким идентификатором нет или он в другом пространстве
422Ошибка валидации тела: в errors перечислены поля
500Сбой на стороне платформы. Стоит воспроизвести и передать разработке — в ответе подробностей нет, они в журнале сервиса

Списки: страницы, фильтры, поиск ​

Списочные методы (/api/widget, /api/dataset, /api/data-source, /api/dashboard) устроены одинаково:

bash
curl -s -H "Authorization: Bearer $T" \
  "http://<адрес>/api/widget?page=1&size=20&sort=name,asc&query=выручка"
json
{ "data": { "content": [ … ],
            "page": { "size": 20, "number": 1, "total_elements": 50, "total_pages": 3 } },
  "success": true }

Нумерация страниц списков начинается с нуля: в примере page=1 — вторая страница. У данных виджета нумерация своя, с единицы. Кроме page, size и sort списки принимают отбор:

ПараметрЧто делает
queryПоиск по названию
typeОтбор по типу объекта — например, тип виджета или тип источника
authorИдентификатор автора
workspaceIdПространство, в котором искать
createdAtFrom, createdAtToДиапазон по дате создания
updatedAtFrom, updatedAtToТо же по дате изменения

Из чего состоит API ​

ГруппаПутейО чём
Источники17Подключения, проверка связи, метаданные, объекты, данные, SQL-запросы, журнал обращений
Датасеты17Состав, схема, связи, значения полей, зависимости, настройки извлечения, RLS и CLS
Пользователи и группы12Учётные записи, членство, атрибуты для RLS, пароль
Вход и провайдеры12Логин, продление, SSO (7) и настройка внешних провайдеров (5)
Конвейеры7Развёртывание объектов между пространствами — Конвейеры развёртывания
Администрирование6Типы источников, драйверы, AI-провайдер
Публичные ссылки11Выпуск и отзыв ссылок на дашборд, страница зрителя — публикация по ссылке
Дашборды5Список, реквизиты, схема, данные
Пространства и перенос5Пространства, участники и роли, перенос объектов из личного в общее
API-токены5Выпуск, приостановка, отзыв
Виджеты4Список, реквизиты, данные — POST /api/widget/{id}/data
Уведомления4Список, счётчик непрочитанных, отметка о прочтении
Доступ3Права на объект для пользователя и группы
Запуски ETL3Состояние запуска, история, отмена
AI-помощник4Проверка доступа, генерация формулы, SQL и кода виджета
Выгрузка в файл4Задание выгрузки, его состояние, файл, пределы — выгрузка в файл
Рассылки10Рассылки, пауза и запуск, оценка срезов, история и письма запуска — рассылки
Почтовые каналы3SMTP-каналы рассылок и тестовая отправка
Рендер4Служебные пути страницы, которую снимает выгрузка; клиенту не нужны
Файлы2Загрузка и удаление файла-источника
Служебное2Настройки установки и словарь интерфейса

Итого 140 путей: сумма по таблице.

Запись схемы датасета ​

Самый неочевидный метод API — PUT /api/dataset/{id}/schema. Он записывает всю схему датасета целиком: таблицы, поля, связи, иерархии, фильтры и параметры. Частичного обновления нет: что не прислали — то удалится.

Порядок работы всегда один: прочитать текущее состояние, изменить нужное, отправить обратно.

bash
# 1. читаем
curl -s -H "Authorization: Bearer $T" http://<адрес>/api/dataset/1413 > ds.json

# 2. правим блоки objects / fields / relations / hierarchies / filters / parameters

# 3. отправляем целиком
curl -s -X PUT -H "Authorization: Bearer $T" -H "Content-Type: application/json" \
  -d @ds-new.json http://<адрес>/api/dataset/1413/schema

Тело — шесть массивов:

json
{ "objects": [ … ], "fields": [ … ], "relations": [ … ],
  "hierarchies": [ … ], "filters": [ … ], "parameters": [ … ] }

Четыре правила, без которых запрос не пройдёт

  • Новым объектам и полям нужен временный отрицательный идентификатор, а ссылки на них делаются по нему же: поле нового объекта указывает "object_id": -1. Иначе — «Object id is required (use a negative temp id for new objects)».
  • У производных полей нельзя присылать formula: она собирается платформой из derivation. Иначе — «formula у производного поля генерируется из derivation и не принимается».
  • Тип поля не меняется: обычное поле нельзя превратить в вычисляемое и наоборот — «Field kind cannot change (calculated ↔ physical)». Нужно новое поле.
  • Ссылки на несуществующие идентификаторы (например, sort_by_field_id от другого датасета) отвечают «Поле датасета не найдено (id …)».

Параметр в теле задаётся так — обратите внимание, что default_value строковое, а область значений лежит в domain:

json
{ "name": "Скидка", "primitive_type": "number", "default_value": "10",
  "domain": { "kind": "range", "min": "0", "max": "50", "step": "1" }, "order": 0 }

kind бывает any, list (со списком values) и range. Что параметр делает при просмотре — Параметры.

Типовые операции ​

Примеры ниже сняты с работающей установки 27.08 — их можно повторить, подставив свой адрес и токен. Полный список полей у каждого метода — в openapi.json.

Подключить источник и проверить связь:

bash
curl -s -X POST http://<адрес>/api/data-source/check \
  -H "Authorization: Bearer $T" -H "Content-Type: application/json" \
  -d '{"type":"clickhouse","settings":{"host":"clickhouse","port":8123,"http_port":8123,
       "username":"reader","password":"…","db":"sales","use_ssh":false}}'

curl -s -X POST http://<адрес>/api/data-source \
  -H "Authorization: Bearer $T" -H "Content-Type: application/json" \
  -d '{"name":"Продажи","type":"clickhouse","settings":{ … }}'

Создать датасет поверх источника (workspace_id — пространство, live: true — прямой запрос):

bash
curl -s -X POST http://<адрес>/api/dataset \
  -H "Authorization: Bearer $T" -H "Content-Type: application/json" \
  -d '{"name":"Продажи: витрина","workspace_id":5,"live":true,"data_source_ids":[1363]}'

Дальше в датасет пишется схема — Запись схемы датасета.

Создать виджет: полки задаются массивами rows (категории), series, columns (меры); у каждого поля — sql с выражением и свой id, на который ссылается сортировка.

bash
curl -s -X POST http://<адрес>/api/widget \
  -H "Authorization: Bearer $T" -H "Content-Type: application/json" \
  -d '{ "name":"Топ городов","type":"bar","dataset_id":1413,
        "rows":[{"id":"r1","alias":"Город","field":"city","table":"customers",
                 "sql":"[customers.city]","settings":{}}],
        "columns":[{"id":"c1","alias":"Выручка","field":"amount","table":"orders",
                    "sql":"SUM([orders.amount])","settings":{}}],
        "series":[],"filters":[],"sorts":[{"field_id":"c1","direction":"desc"}] }'

Вычисляемые поля датасета нужно передавать самому

Если на полке стоит вычисляемое поле датасета (ссылка без точки — [unit_price], а не [orders.amount]), в теле запроса должен быть блок calculated_fields с его определением:

json
"calculated_fields": [
  { "id": "135267", "name": "unit_price", "alias": "Цена за единицу",
    "primitive_type": "float", "sql": "[orders.amount] / [orders.quantity]" }
]

Платформа не подставляет определения из датасета сама: без этого блока и создание, и выборка отвечают «Определение вычисляемого поля не найдено: …». Идентификатор, имя и формулу берут из GET /api/dataset/{id}, из блока fields — это те поля, у которых заполнено formula, а object_id пустой.

Получить данные виджета — тем же телом, что и при создании, плюс при необходимости фильтры и значения параметров:

bash
curl -s -X POST http://<адрес>/api/widget/1531/data \
  -H "Authorization: Bearer $T" -H "Content-Type: application/json" \
  -d '{ "type":"bar", "rows":[ … ], "columns":[ … ], "series":[], "sorts":[],
        "filters":[{"sql":"[customers.city]","op":"in","values":["Казань"],
                    "value_type":"string"}],
        "parameters":{"Скидка":50} }'

Ответ — плоские строки, где ключи совпадают с id полей на полках:

json
{ "data": { "kind": "flat",
            "rows": [ { "r1": "Казань", "c1": 40708500.0 } ],
            "page": { "page": 1, "pageSize": 20, "hasMore": false } },
  "success": true }

У показателя (KPI) форма ответа другая — "kind": "kpi" и объект row вместо массива.

Условия отбора складываются по «И»

Фильтры из тела запроса платформа соединяет с сохранёнными фильтрами виджета — все условия действуют одновременно. Взаимоисключающие условия по одному полю дают пустой результат: это тот же механизм, что и у фильтров дашборда.

Выпустить публичную ссылку на дашборд: реестр ссылок — GET|POST /api/dashboard/{id}/share-links, правка и отзыв — PUT|DELETE /api/dashboard/{id}/share-links/{linkId}, приостановка и возобновление — .../suspend и .../activate, смена адреса — .../rotate. Сторона зрителя живёт под /api/public/link/{token}: сама ссылка, /dashboard, /widget/{id}, /widget/{id}/data, /dataset/{id}/field-values и /unlock для ссылки с паролем. Ответ /unlock даёт подтверждение, которое дальше передаётся заголовком X-Share-Grant. Разбор — Публикация по ссылке.

Запустить синхронизацию и следить за ней: запуски датасета — /api/datasets/{id}/extracts, состояние и история конкретного запуска — /api/etl-jobs/{jobId} и /api/etl-jobs/{jobId}/history, отмена — /api/etl-jobs/{jobId}/cancel. Что происходит внутри — Синхронизация и ETL, шаги запуска — журнал запуска.

Что доступно только через API ​

Разовая подстановка параметра, просмотр от имени другого пользователя и пределы выгрузки в интерфейсе не представлены — они делаются только запросом. Полный перечень с ссылками на разборы, а заодно список значений, которые задаются только настройками установки, — ограничения текущей версии.

Что дальше ​