Операции записи в публичном API v2
Эндпоинты записи публичного API v2 создают, заменяют, изменяют и удаляют содержимое РПИ и объекты модели данных, а также управляют доступом к проектам, переносом версий и Git-подключениями. Базовый путь, аутентификация, пагинация и формат ошибок — те же, что у эндпоинтов чтения (страница Публичный API v2).
1 API записи — соглашения
Эндпоинты записи v2 создают, полностью заменяют, обновляют и удаляют сущности РПИ и модели данных. Каждая операция записи фиксируется в аудите (раздел 7 страницы API) и возвращает стандартный формат ошибок (раздел 4 страницы Публичный API v2); полный каталог кодов — в разделе 9.11. Соглашения ниже действуют для каждого эндпоинта раздела 2 и там не повторяются.
Семантика HTTP-методов:
| Метод | Значение |
|---|---|
POST (коллекция) |
Создать новый ресурс; возвращает созданный ресурс с кодом 201 Created |
POST (…/bulk) |
Массовое создание/обновление набора строк РПИ одним вызовом. Все строки применены — 201; часть строк отклонена — 207 Multi-Status с массивами succeeded и failed; ни одна не применена — 422 DF_API.BULK_REJECTED |
POST (состав, например …/fact-tables/{id}/measures) |
Назначить существующие элементы родителю; возвращает 201 со сводкой { timestamp, succeeded: [{ id }], failed: [{ index, id, error: { code, message, details } }] } (207, если часть элементов отклонена; уже назначенный элемент попадает в failed с кодом constraint_violation, несуществующий — resource_not_found; ни одного успешного — 422 DF_API.BULK_REJECTED). Добавление измерений в группу (…/dimension-groups/{id}/dimensions) отвечает 200 объектом группы, несуществующее измерение — 404 DF_API.RESOURCE_NOT_FOUND |
PUT |
Полная замена — обязательные поля должны присутствовать (иначе 400 DF_API.MISSING_REQUIRED_FIELD); любое не переданное опциональное поле сбрасывается к значению по умолчанию/пустому |
PATCH |
Частичное обновление — изменяются только переданные поля |
DELETE |
Удалить ресурс; возвращает 204 No Content |
Эффективный доступ. Запись в РПИ и модель данных требует, чтобы владелец API-ключа разрешался в эффективную роль в проекте разработчик или выше для целевого проекта (та же модель доступа на проект, что и в разделе 2.2 страницы API). Если у владельца нет доступа к проекту, API возвращает 404 DF_API.PROJECT_NOT_FOUND (факт существования не раскрывается); если доступ ниже разработчика (аналитик или наблюдатель) — 403 DF_API.WRITE_ACCESS_DENIED. Создание проекта требует, чтобы владелец ключа принадлежал компании.
Идемпотентность. Запрос POST может нести заголовок Idempotency-Key (UUID v4). Ключ имеет область (хэш API-ключа, HTTP-метод, путь, ключ) и хранится в течение 24 часов. Для повторного ключа завершённый ответ воспроизводится дословно; для ещё выполняющегося дубликата возвращается 409 DF_API.IDEMPOTENCY_IN_PROGRESS; для некорректного ключа — 400 DF_API.INVALID_IDEMPOTENCY_KEY. PUT, PATCH и DELETE заголовок не используют — их повтор приводит ресурс к тому же состоянию.
Валидация тела. Тела строгие: неизвестное поле отвечает 400 DF_API.VALIDATION_FAILED с details[].code = unknown_field; значение неверного типа — тем же кодом с invalid_value. Поля только для чтения id, timestamp, created_at, updated_at в телах записи допускаются (чтобы результат чтения можно было отправить обратно) и игнорируются — кроме id, который, если передан, должен совпадать с идентификатором в пути (400 DF_API.ID_MISMATCH).
Валидация и ссылочная целостность. Имена должны соответствовать допустимому шаблону и быть уникальными в своей области (409 DF_API.DUPLICATE_NAME). Формулы показателей парсятся, а их ссылки разрешаются: ошибка синтаксиса возвращает 422 DF_API.INVALID_FORMULA_SYNTAX, неизвестная ссылка — 422 DF_API.FORMULA_REFERENCE_NOT_FOUND, цикл — 422 DF_API.CIRCULAR_DEPENDENCY. Удаление элемента, на который ссылается формула другого элемента, измерения, входящего в группу измерений, или группы измерений, назначенной таблице фактов, возвращает 409 DF_API.CONSTRAINT_VIOLATION; показатель, только назначенный таблице фактов, удаляется вместе с назначением (204). Ответ каждой операции создания и обновления содержит созданный/обновлённый объект и поле timestamp (момент операции).
Поля-справочники РПИ. measure_type, dimension_type, fact_type, display_data_type, status, relevance, required, visibility и другие колонки-справочники принимают либо английскую, либо русскую подпись варианта (Base / Базовый, Number / Число); сравнение не учитывает регистр и пробелы по краям, а ответ возвращает подписи на языке запроса. Значение, не совпавшее ни с одним вариантом обязательного справочника (measure_type, dimension_type, fact_type), отвечает 400 DF_API.INVALID_ENUM_VALUE; для необязательных справочников несовпавшее значение отбрасывается. Колонки-флаги (relevance, required, visibility) принимают строки "true" / "false".
Поля версии. У версии есть только name, is_global и (при создании) опциональное clone_from_version. API записи версий не принимает поле description.
Объекты источника в запросах на запись. connected_source (измерения, факты), primary_key (группы измерений, связи) и foreign_key (связи) принимают объект из раздела 3.6 страницы API — как в одиночных запросах, так и в bulk. db и table обязательны; schema и column принимают пустую строку, null или отсутствие. Поле connection необязательное, и именно его наличие выбирает, какой из двух контрактов применяется:
connection |
Поведение |
|---|---|
| передано | Подключение ищется только по названию, точным совпадением (названия уникальны в пределах версии, и Prod — не то же самое, что prod). Проверяются db, table, column, а для связей — и само подключение; см. таблицу ниже |
| не передано | Прежнее поведение сохраняется без изменений: db разрешается нестрого — как идентификатор подключения, имя базы или название подключения, — и ничего не проверяется |
Проверки, выполняемые при переданном connection:
| Поле | Правило | Ошибка |
|---|---|---|
connection |
Должно называть подключение из версии проекта | DF_API.INVALID_SOURCE_CONNECTION |
db |
Обязательное, как и раньше; должно быть именем базы данных этого подключения, название подключения здесь больше не принимается | DF_API.INVALID_SOURCE_DB |
schema |
Необязательное, только для PostgreSQL; если передано и непусто — должно совпадать со схемой этого подключения | DF_API.INVALID_SOURCE_SCHEMA |
table |
Должна присутствовать в кэшированной схеме подключения | DF_API.INVALID_SOURCE_TABLE |
table (MS SQL) |
Можно передать либо как schema + короткое имя, либо одной строкой схема.таблица — в такой форме таблицу возвращают эндпоинты чтения. Короткое имя без схемы, когда таблица с таким именем существует в какой-то схеме, трактуется как отсутствие схемы, а не как неверная таблица |
DF_API.MISSING_REQUIRED_FIELD по полю …schema |
column |
Необязательное; если передано — должна присутствовать в этой таблице | DF_API.INVALID_SOURCE_COLUMN |
foreign_key.connection / primary_key.connection |
Должно совпадать с подключением, которое уже использует исходная таблица фактов / целевая группа измерений | DF_API.CONNECTION_MISMATCH |
foreign_key против primary_key |
Оба ключа одной связи должны указывать на одно подключение — джойн не может идти через две базы. При PATCH одного ключа сравнение идёт с сохранённым значением второго |
DF_API.CONNECTION_MISMATCH |
Три намеренных исключения:
schemaпроверяется только для PostgreSQL. Там схема — свойство подключения, поэтому значение, расходящееся с ним, требует того, чего API сохранить не может: выбрать другую схему означает указать другое подключение. MS SQL Server хранит схему внутриtable(dbo.orders), где её уже покрывает проверка таблицы, а в ClickHouse схем нет — для обоих поле игнорируется. Пустаяschemaничего не утверждает и считается непереданной.tableиcolumnсверяются с кэшированным снимком схемы — тем же списком, из которого строится выбор источника в интерфейсе продукта. Если снимок ни разу не обновлялся или не читается, проверка пропускается, а не проваливается: нечитаемый снимок не доказывает, что таблица указана неверно.CONNECTION_MISMATCHвозникает только тогда, когда подключение второй стороны известно. У таблицы фактов, созданной через API, нет собственной базовой таблицы, а у группы измерений нет первичного ключа до первой связи; в обоих случаях сравнивать не с чем, и запрос принимается.
Ошибки, общие для всех эндпоинтов записи. Помимо общих ошибок раздела 4 страницы API: 403 DF_API.WRITE_ACCESS_DENIED (роль ниже разработчика), 400 DF_API.VALIDATION_FAILED (тело не соответствует схеме), 400 DF_API.INVALID_IDEMPOTENCY_KEY и 409 DF_API.IDEMPOTENCY_IN_PROGRESS (POST с Idempotency-Key). Блоки «Ошибки» у отдельных эндпоинтов раздела 2 перечисляют только специфичное для эндпоинта.
2 API записи — эндпоинты
Каждый эндпоинт этого раздела подчиняется соглашениям раздела 1 (роль разработчика, идемпотентность, строгие тела, timestamp в каждом ответе создания/обновления, общие коды ошибок). {v} сокращает /df-api/v2/projects/{project_id}/versions/{version_id}.
Указатель:
| Группа | Эндпоинты | Разделы |
|---|---|---|
| Проекты и версии | POST /projects; PATCH, DELETE /projects/{project_id}; POST /projects/{project_id}/versions; PATCH, DELETE …/versions/{version_id} |
2.1–2.6 |
| Показатели | POST {v}/measures, POST {v}/measures/bulk, PUT, PATCH, DELETE {v}/measures/{measure_id} |
2.7–2.11 |
| Измерения | POST {v}/dimensions, POST {v}/dimensions/bulk, PUT, PATCH, DELETE {v}/dimensions/{dimension_id} |
2.12–2.16 |
| Факты | POST {v}/facts, POST {v}/facts/bulk, PUT, PATCH, DELETE {v}/facts/{fact_id} |
2.17–2.21 |
| Группы измерений | POST {v}/dimension-groups; PUT, PATCH, DELETE …/{dimension_group_id}; POST …/dimensions; PATCH, DELETE …/dimensions/{dimension_id} |
2.22–2.28 |
| Таблицы фактов | POST {v}/fact-tables; PUT, PATCH, DELETE …/{fact_table_id}; состав — POST / DELETE для measures, dimensions, facts, dimension-groups; verification-filters уровня таблицы фактов — POST, PUT, PATCH, DELETE |
2.29–2.44 |
| Фильтры верификации (уровень версии) | POST {v}/verification-filters; PUT, PATCH, DELETE …/{filter_id} |
2.45–2.48 |
| Связи | POST {v}/relationships; PUT, PATCH, DELETE …/{relationship_id} |
2.49–2.52 |
| Доступ к проектам | POST /projects/{projectId}/access, DELETE …/access/{userId}, PUT /projects/{projectId}/owner |
3 |
| Перенос версий | POST {v}/export/git, export/file, import/validate, import/preview, import/git, import/file |
4 |
| Git-подключения | POST /git-connections; PUT, DELETE /git-connections/{connection_id}; POST …/test |
5 |
2.1 Создать проект
Запрос
POST /df-api/v2/projects
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора (раздел 1) |
name |
тело | string | да | 1–128 символов; буквы, цифры, _, ., -, пробел; начинается с буквы или цифры |
description |
тело | string | нет | До 255 символов |
color |
тело | string | нет | Цвет в HEX, например #FF8000 |
{ "name": "Sales Analytics", "description": "Production sales warehouse", "color": "#2479BC" }
Детали
Владелец ключа должен принадлежать компании (иначе 403 DF_API.WRITE_ACCESS_DENIED); проект создаётся в этой компании, владелец ключа становится его владельцем, создаётся начальная версия с именем Version 1. Имя должно быть уникальным среди проектов компании.
Ответ
201 Created
{
"id": "12",
"name": "Sales Analytics",
"description": "Production sales warehouse",
"color": "#2479BC",
"created_at": "2026-05-05T08:30:00.000Z",
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор проекта |
name, description |
string / string | null | Как сохранено |
color |
string | null | Цвет в HEX |
created_at |
string | null | Дата создания |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.DUPLICATE_NAME |
409 | Проект с таким именем уже существует |
DF_API.WRITE_ACCESS_DENIED |
403 | У владельца ключа нет компании либо достигнут лимит проектов лицензии (внутренний ключ LICENSE.CREATE_PROJECT_ACCESS_DENIED не имеет отдельного публичного кода и приводится к общему 403) |
2.2 Обновить проект
Запрос
PATCH /df-api/v2/projects/{project_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
project_id |
путь | integer | да | Идентификатор проекта |
name |
тело | string | нет | Те же правила, что при создании |
description |
тело | string | нет | До 255 символов |
color |
тело | string | нет | Цвет в HEX |
Детали
Частичное обновление: изменяются только переданные поля. Требует роли «разработчик или выше» в проекте.
Ответ
200 OK
{
"id": "12",
"name": "Sales Analytics",
"description": "Production sales warehouse",
"color": "#2479BC",
"created_at": "2026-05-05T08:30:00.000Z",
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор проекта |
name, description |
string / string | null | Как сохранено |
color |
string | null | Цвет в HEX |
created_at |
string | null | Дата создания |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.DUPLICATE_NAME |
409 | Новое имя уже занято другим проектом |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
2.3 Удалить проект
Запрос
DELETE /df-api/v2/projects/{project_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
project_id |
путь | integer | да | Идентификатор проекта |
Детали
Удаляет проект со всеми версиями и содержимым. Снимок проекта before записывается в журнал аудита (раздел 7 страницы API).
Ответ
204 No Content
Ошибки. Только общие ошибки записи (раздел 1).
2.4 Создать версию
Запрос
POST /df-api/v2/projects/{project_id}/versions
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
project_id |
путь | integer | да | Идентификатор проекта |
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
name |
тело | string | да | 1–64 символа; буквы, цифры, _, ., -, пробел |
is_global |
тело | boolean | нет | Сделать новую версию опубликованной (глобальной) версией проекта |
clone_from_version |
тело | string | нет | Идентификатор версии, из которой копируется содержимое. Если не передан, содержимое копируется из текущей глобальной версии |
{ "name": "Q1 2027", "is_global": false, "clone_from_version": "33" }
Детали
У версии нет поля description. Создание версии учитывается в лимите версий лицензии.
Ответ
201 Created
{ "id": "34", "name": "Q1 2027", "is_global": false, "timestamp": "2026-05-05T08:30:00.120Z" }
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор версии |
name |
string | null | Имя версии |
is_global |
boolean | Является ли версия глобальной версией проекта |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.DUPLICATE_NAME |
409 | В проекте есть живая версия с таким именем |
DF_API.VERSION_NOT_FOUND |
404 | clone_from_version не существует в проекте |
DF_API.LICENSE_LIMIT_REACHED |
403 | Достигнут лимит версий лицензии |
DF_API.GLOBAL_VERSION_CONFLICT |
422 | is_global установить нельзя |
2.5 Обновить версию
Запрос
PATCH /df-api/v2/projects/{project_id}/versions/{version_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
project_id, version_id |
путь | integer | да | Идентификаторы |
name |
тело | string | нет | Те же правила, что при создании |
is_global |
тело | boolean | нет | true делает эту версию глобальной (прежняя глобальная версия теряет флаг) |
Ответ
200 OK
{ "id": "34", "name": "Q1 2027", "is_global": false, "timestamp": "2026-05-05T08:30:00.120Z" }
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор версии |
name |
string | null | Имя версии |
is_global |
boolean | Является ли версия глобальной версией проекта |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.DUPLICATE_NAME |
409 | Новое имя уже занято другой живой версией |
DF_API.GLOBAL_VERSION_CONFLICT |
422 | is_global установить нельзя — конфликт с другой глобальной версией |
2.6 Удалить версию
Запрос
DELETE /df-api/v2/projects/{project_id}/versions/{version_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
project_id, version_id |
путь | integer | да | Идентификаторы |
Детали
Удаляет версию со всем содержимым (мягкое удаление, подлежит очистке по сроку хранения). Текущую глобальную версию удалить нельзя.
Ответ
204 No Content
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.GLOBAL_VERSION_CONFLICT |
422 | Версия является глобальной версией проекта |
2.7 Создать показатель
Запрос
POST {v}/measures
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
measure_name |
тело | string | да | Имя показателя; уникально среди показателей версии |
measure_type |
тело | string | да | Подпись справочника «Тип показателя»: Base / Calculated (или русская подпись) |
group, block |
тело | string | нет | Группирующие колонки РПИ |
measure_description |
тело | string | нет | До 255 символов |
original_source_type, original_source, original_object |
тело | string | нет | Колонки происхождения (свободный текст) |
display_data_type |
тело | string | нет | Подпись справочника «Отображаемый тип данных» (Number, Text, Date, …) |
restrictions |
тело | string | нет | Колонка ограничений |
formula |
тело | string | нет | Формула расчётного показателя; ссылки вида [Имя показателя] |
report_for_verification, comment, responsible_for_data, variation |
тело | string | нет | Текстовые колонки |
status |
тело | string | нет | Подпись справочника «Статус» |
relevance, required, visibility |
тело | "true" | "false" |
нет | Колонки-флаги |
{ "measure_name": "Total revenue", "measure_type": "base", "group": "Revenue", "display_data_type": "Number" }
Детали
Формула парсится, её ссылки разрешаются в существующие показатели версии (раздел 1). Ответ повторяет строку GET {v}/measures без row_number: сначала id, затем все записываемые колонки (незаполненные — null), последним — timestamp; подписи справочников возвращаются на языке запроса.
Ответ
201 Created
{
"id": "1000",
"group": "Revenue",
"block": null,
"measure_name": "Total revenue",
"measure_description": null,
"original_source_type": null,
"original_source": null,
"original_object": null,
"display_data_type": "Number",
"measure_type": "Base",
"restrictions": null,
"formula": null,
"report_for_verification": null,
"comment": null,
"status": null,
"relevance": null,
"required": null,
"visibility": null,
"responsible_for_data": null,
"variation": null,
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор нового показателя — {measure_id} остальных эндпоинтов |
group, block |
string | null | Группирующие колонки РПИ |
measure_name |
string | Имя показателя |
measure_description |
string | null | Описание |
original_source_type, original_source, original_object |
string | null | Колонки происхождения; свободный текст |
display_data_type |
string | null | Локализованная подпись типа данных (Number, Text, Date, …) |
measure_type |
string | Локализованная подпись: Base или Calculated |
restrictions |
string | null | Колонка ограничений |
formula |
string | null | Формула расчётного показателя со ссылками вида [Имя] |
report_for_verification, comment, responsible_for_data, variation |
string | null | Текстовые колонки |
status |
string | null | Локализованная подпись справочника «Статус» |
relevance, required, visibility |
boolean | null | Колонки-флаги; в ответах записи — булевы, null, если не заданы |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.DUPLICATE_NAME |
409 | Показатель с таким именем уже есть в версии |
DF_API.INVALID_ENUM_VALUE |
400 | measure_type не совпал ни с одним вариантом |
DF_API.INVALID_FORMULA_SYNTAX |
422 | Формула не разобрана |
DF_API.FORMULA_REFERENCE_NOT_FOUND |
422 | Формула ссылается на неизвестный элемент |
DF_API.CIRCULAR_DEPENDENCY |
422 | Формула образует цикл |
DF_API.INVALID_PARAMETER_TYPE |
422 | Измерение, переданное в периодную функцию, не привязано к колонке даты/времени |
2.8 Массовое создание/обновление показателей
Запрос
POST {v}/measures/bulk
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
measures |
тело | array | да | Не менее одного элемента |
measures[].id |
тело | string | нет | Передан — существующий показатель обновляется (частично, как PATCH); отсутствует — показатель создаётся |
measures[].measure_name |
тело | string | нет | Имя показателя; уникально среди показателей версии |
measures[].measure_type |
тело | string | нет | Подпись справочника «Тип показателя»: Base / Calculated (или русская подпись) |
measures[].group, measures[].block |
тело | string | нет | Группирующие колонки РПИ |
measures[].measure_description |
тело | string | нет | До 255 символов |
measures[].original_source_type, measures[].original_source, measures[].original_object |
тело | string | нет | Колонки происхождения (свободный текст) |
measures[].display_data_type |
тело | string | нет | Подпись справочника «Отображаемый тип данных» (Number, Text, Date, …) |
measures[].restrictions |
тело | string | нет | Колонка ограничений |
measures[].formula |
тело | string | нет | Формула расчётного показателя; ссылки вида [Имя показателя] |
measures[].report_for_verification, measures[].comment, measures[].responsible_for_data, measures[].variation |
тело | string | нет | Текстовые колонки |
measures[].status |
тело | string | нет | Подпись справочника «Статус» |
measures[].relevance, measures[].required, measures[].visibility |
тело | "true" | "false" |
нет | Колонки-флаги |
{
"measures": [
{ "measure_name": "Total revenue", "measure_type": "base", "group": "Revenue" },
{ "id": "1000", "measure_description": "Gross revenue across all channels" }
]
}
Детали
Элементы обрабатываются по порядку, каждый в своей транзакции: сбойный элемент ничего не оставляет и не останавливает остальные. failed[].index — позиция элемента в запросе. На весь запрос пишется одна сводная запись аудита.
Ответ
201 Created, если применены все элементы; 207 Multi-Status, если часть элементов отклонена:
{
"timestamp": "2026-05-05T08:30:00.120Z",
"succeeded": [
{ "id": "1000", "measure_name": "Total revenue", "measure_type": "Base", "…": "…" }
],
"failed": [
{
"index": 1,
"error": { "code": "duplicate_name", "message": "Показатель с таким именем уже существует", "details": [{ "field": "measure_name", "code": "invalid_value" }] }
}
]
}
| Поле | Тип | Описание |
|---|---|---|
succeeded[] |
array | Объекты показателей (как в ответе одиночного создания, без timestamp) |
failed[].index |
integer | Позиция отклонённого элемента в measures |
failed[].error |
object | code, message, details из раздела 4 страницы Публичный API v2 |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.VALIDATION_FAILED |
400 | measures пуст или элемент некорректен |
DF_API.BULK_REJECTED |
422 | Ни один элемент не применён; details[] адресует каждый элемент (measures.<index>) |
| Коды по элементам | в failed[] |
duplicate_name, missing_required_field, invalid_enum_value, resource_not_found (неизвестный id), invalid_formula_syntax, formula_reference_not_found, circular_dependency, invalid_parameter_type |
2.9 Заменить показатель
Запрос
PUT {v}/measures/{measure_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
measure_id |
путь | integer | да | Идентификатор показателя |
measure_name |
тело | string | да | Имя показателя; уникально среди показателей версии |
measure_type |
тело | string | да | Подпись справочника «Тип показателя»: Base / Calculated (или русская подпись) |
group, block |
тело | string | нет | Группирующие колонки РПИ |
measure_description |
тело | string | нет | До 255 символов |
original_source_type, original_source, original_object |
тело | string | нет | Колонки происхождения (свободный текст) |
display_data_type |
тело | string | нет | Подпись справочника «Отображаемый тип данных» (Number, Text, Date, …) |
restrictions |
тело | string | нет | Колонка ограничений |
formula |
тело | string | нет | Формула расчётного показателя; ссылки вида [Имя показателя] |
report_for_verification, comment, responsible_for_data, variation |
тело | string | нет | Текстовые колонки |
status |
тело | string | нет | Подпись справочника «Статус» |
relevance, required, visibility |
тело | "true" | "false" |
нет | Колонки-флаги |
Детали
measure_name и measure_type обязательны; каждая непереданная опциональная колонка сбрасывается в пустое значение.
Ответ
200 OK
{
"id": "1000",
"group": "Revenue",
"block": null,
"measure_name": "Total revenue",
"measure_description": null,
"original_source_type": null,
"original_source": null,
"original_object": null,
"display_data_type": "Number",
"measure_type": "Base",
"restrictions": null,
"formula": null,
"report_for_verification": null,
"comment": null,
"status": null,
"relevance": null,
"required": null,
"visibility": null,
"responsible_for_data": null,
"variation": null,
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор нового показателя — {measure_id} остальных эндпоинтов |
group, block |
string | null | Группирующие колонки РПИ |
measure_name |
string | Имя показателя |
measure_description |
string | null | Описание |
original_source_type, original_source, original_object |
string | null | Колонки происхождения; свободный текст |
display_data_type |
string | null | Локализованная подпись типа данных (Number, Text, Date, …) |
measure_type |
string | Локализованная подпись: Base или Calculated |
restrictions |
string | null | Колонка ограничений |
formula |
string | null | Формула расчётного показателя со ссылками вида [Имя] |
report_for_verification, comment, responsible_for_data, variation |
string | null | Текстовые колонки |
status |
string | null | Локализованная подпись справочника «Статус» |
relevance, required, visibility |
boolean | null | Колонки-флаги; в ответах записи — булевы, null, если не заданы |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Показатель не существует в версии |
DF_API.MISSING_REQUIRED_FIELD |
400 | Отсутствует measure_name или measure_type |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
DF_API.DUPLICATE_NAME |
409 | Показатель с таким именем уже есть в версии |
DF_API.INVALID_ENUM_VALUE |
400 | measure_type не совпал ни с одним вариантом |
DF_API.INVALID_FORMULA_SYNTAX |
422 | Формула не разобрана |
DF_API.FORMULA_REFERENCE_NOT_FOUND |
422 | Формула ссылается на неизвестный элемент |
DF_API.CIRCULAR_DEPENDENCY |
422 | Формула образует цикл |
DF_API.INVALID_PARAMETER_TYPE |
422 | Измерение, переданное в периодную функцию, не привязано к колонке даты/времени |
2.10 Обновить показатель
Запрос
PATCH {v}/measures/{measure_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
measure_id |
путь | integer | да | Идентификатор показателя |
measure_name |
тело | string | нет | Имя показателя; уникально среди показателей версии |
measure_type |
тело | string | нет | Подпись справочника «Тип показателя»: Base / Calculated (или русская подпись) |
group, block |
тело | string | нет | Группирующие колонки РПИ |
measure_description |
тело | string | нет | До 255 символов |
original_source_type, original_source, original_object |
тело | string | нет | Колонки происхождения (свободный текст) |
display_data_type |
тело | string | нет | Подпись справочника «Отображаемый тип данных» (Number, Text, Date, …) |
restrictions |
тело | string | нет | Колонка ограничений |
formula |
тело | string | нет | Формула расчётного показателя; ссылки вида [Имя показателя] |
report_for_verification, comment, responsible_for_data, variation |
тело | string | нет | Текстовые колонки |
status |
тело | string | нет | Подпись справочника «Статус» |
relevance, required, visibility |
тело | "true" | "false" |
нет | Колонки-флаги |
Детали
Изменяются только переданные поля.
Ответ
200 OK
{
"id": "1000",
"group": "Revenue",
"block": null,
"measure_name": "Total revenue",
"measure_description": null,
"original_source_type": null,
"original_source": null,
"original_object": null,
"display_data_type": "Number",
"measure_type": "Base",
"restrictions": null,
"formula": null,
"report_for_verification": null,
"comment": null,
"status": null,
"relevance": null,
"required": null,
"visibility": null,
"responsible_for_data": null,
"variation": null,
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор нового показателя — {measure_id} остальных эндпоинтов |
group, block |
string | null | Группирующие колонки РПИ |
measure_name |
string | Имя показателя |
measure_description |
string | null | Описание |
original_source_type, original_source, original_object |
string | null | Колонки происхождения; свободный текст |
display_data_type |
string | null | Локализованная подпись типа данных (Number, Text, Date, …) |
measure_type |
string | Локализованная подпись: Base или Calculated |
restrictions |
string | null | Колонка ограничений |
formula |
string | null | Формула расчётного показателя со ссылками вида [Имя] |
report_for_verification, comment, responsible_for_data, variation |
string | null | Текстовые колонки |
status |
string | null | Локализованная подпись справочника «Статус» |
relevance, required, visibility |
boolean | null | Колонки-флаги; в ответах записи — булевы, null, если не заданы |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Показатель не существует в версии |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
DF_API.DUPLICATE_NAME |
409 | Показатель с таким именем уже есть в версии |
DF_API.INVALID_ENUM_VALUE |
400 | measure_type не совпал ни с одним вариантом |
DF_API.INVALID_FORMULA_SYNTAX |
422 | Формула не разобрана |
DF_API.FORMULA_REFERENCE_NOT_FOUND |
422 | Формула ссылается на неизвестный элемент |
DF_API.CIRCULAR_DEPENDENCY |
422 | Формула образует цикл |
DF_API.INVALID_PARAMETER_TYPE |
422 | Измерение, переданное в периодную функцию, не привязано к колонке даты/времени |
2.11 Удалить показатель
Запрос
DELETE {v}/measures/{measure_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
measure_id |
путь | integer | да | Идентификатор показателя |
Детали
Показатель, на который ссылается формула другого элемента, удалить нельзя. Показатель, только назначенный таблице фактов, удаляется вместе с назначением.
Ответ
204 No Content
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Показатель не существует в версии |
DF_API.CONSTRAINT_VIOLATION |
409 | На показатель ссылается формула |
2.12 Создать измерение
Запрос
POST {v}/dimensions
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
dimension_name |
тело | string | да | Имя измерения; уникально среди измерений версии |
dimension_type |
тело | string | да | Подпись справочника «Тип измерения»: Primary / Derived |
group, block |
тело | string | нет | Группирующие колонки РПИ |
dimension_description |
тело | string | нет | До 255 символов |
original_source_type, original_source, original_object |
тело | string | нет | Колонки происхождения |
dimension_group |
тело | string | нет | Имя существующей группы измерений; измерение становится её членом |
display_data_type |
тело | string | нет | Подпись справочника «Отображаемый тип данных» |
source_data_type |
тело | string | нет | Принимается и игнорируется — вычисляется из connected_source |
formula |
тело | string | нет | Формула производного измерения |
connected_source |
тело | object | нет | Объект источника (раздел 3.6 страницы API): connection (необязательно), db (обязательно), schema, table (обязательно), column |
comment, value_options, responsible_for_data |
тело | string | нет | Текстовые колонки |
status |
тело | string | нет | Подпись справочника «Статус» |
relevance, required, visibility |
тело | "true" | "false" |
нет | Колонки-флаги |
{
"dimension_name": "Region",
"dimension_type": "primary",
"dimension_group": "Geography",
"display_data_type": "Text",
"connected_source": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_geography", "column": "region_name" }
}
Детали
connected_source проверяется по правилам раздела 1, если передан connection. Указание dimension_group добавляет измерение в эту группу.
Ответ
201 Created
{
"id": "2000",
"group": "Customer",
"block": "Profile",
"dimension_name": "Customer name",
"dimension_description": "Full customer name",
"original_source_type": null,
"original_source": null,
"original_object": null,
"dimension_group": "Customers",
"display_data_type": "Text",
"source_data_type": "VARCHAR(255)",
"dimension_type": "Primary",
"formula": null,
"connected_source": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_customer", "column": "customer_name" },
"comment": null,
"value_options": null,
"status": "Active",
"relevance": null,
"required": null,
"visibility": null,
"responsible_for_data": null,
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор нового измерения — {dimension_id} остальных эндпоинтов |
group, block |
string | null | Группирующие колонки РПИ |
dimension_name, dimension_description |
string / string | null | Имя и описание |
original_source_type, original_source, original_object |
string | null | Колонки происхождения; свободный текст |
dimension_group |
string | null | Имя группы измерений, в которую входит измерение |
display_data_type |
string | null | Локализованная подпись типа данных |
source_data_type |
string | null | Физический тип колонки, полученный из закешированной схемы подключения |
dimension_type |
string | Локализованная подпись: Primary или Derived |
formula |
string | null | Формула производного измерения |
connected_source |
object | null | Объект источника { db, schema, table, column } (раздел 3.6 страницы API) |
comment, responsible_for_data |
string | null | Текстовые колонки |
value_options |
string | null | Колонка допустимых значений |
status |
string | null | Локализованная подпись справочника «Статус» |
relevance, required, visibility |
boolean | null | Колонки-флаги; в ответах записи — булевы, null, если не заданы |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.DUPLICATE_NAME |
409 | Измерение с таким именем уже есть в версии |
DF_API.INVALID_ENUM_VALUE |
400 | dimension_type не совпал ни с одним вариантом |
DF_API.INVALID_SOURCE_*, DF_API.MISSING_REQUIRED_FIELD |
400 | Проверка connected_source (раздел 1) |
DF_API.INVALID_FORMULA_SYNTAX |
422 | Формула не разобрана |
DF_API.FORMULA_REFERENCE_NOT_FOUND |
422 | Формула ссылается на неизвестный элемент |
DF_API.CIRCULAR_DEPENDENCY |
422 | Формула образует цикл |
DF_API.INVALID_PARAMETER_TYPE |
422 | Измерение, переданное в периодную функцию, не привязано к колонке даты/времени |
2.13 Массовое создание/обновление измерений
Запрос
POST {v}/dimensions/bulk
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
dimensions |
тело | array | да | Не менее одного элемента |
dimensions[].dimension_name |
тело | string | нет | Имя измерения; уникально среди измерений версии |
dimensions[].dimension_type |
тело | string | нет | Подпись справочника «Тип измерения»: Primary / Derived |
dimensions[].group, dimensions[].block |
тело | string | нет | Группирующие колонки РПИ |
dimensions[].dimension_description |
тело | string | нет | До 255 символов |
dimensions[].original_source_type, dimensions[].original_source, dimensions[].original_object |
тело | string | нет | Колонки происхождения |
dimensions[].dimension_group |
тело | string | нет | Имя существующей группы измерений; измерение становится её членом |
dimensions[].display_data_type |
тело | string | нет | Подпись справочника «Отображаемый тип данных» |
dimensions[].source_data_type |
тело | string | нет | Принимается и игнорируется — вычисляется из connected_source |
dimensions[].formula |
тело | string | нет | Формула производного измерения |
dimensions[].connected_source |
тело | object | нет | Объект источника (раздел 3.6 страницы API): connection (необязательно), db (обязательно), schema, table (обязательно), column |
dimensions[].comment, dimensions[].value_options, dimensions[].responsible_for_data |
тело | string | нет | Текстовые колонки |
dimensions[].status |
тело | string | нет | Подпись справочника «Статус» |
dimensions[].relevance, dimensions[].required, dimensions[].visibility |
тело | "true" | "false" |
нет | Колонки-флаги |
{
"dimensions": [
{ "dimension_name": "Region", "dimension_type": "primary", "dimension_group": "Geography" },
{ "id": "2000", "dimension_description": "Регион продаж" }
]
}
Детали
Элементы обрабатываются по порядку, каждый в своей транзакции: сбойный элемент ничего не оставляет и не останавливает остальные. failed[].index — позиция элемента в запросе. На весь запрос пишется одна сводная запись аудита.
Ответ
201 Created, если применены все элементы; 207 Multi-Status, если часть элементов отклонена:
{
"timestamp": "2026-05-05T08:30:00.120Z",
"succeeded": [
{ "id": "2000", "dimension_name": "Region", "dimension_type": "Primary", "…": "…" }
],
"failed": [
{
"index": 1,
"error": { "code": "duplicate_name", "message": "Измерение с таким именем уже существует", "details": [{ "field": "dimension_name", "code": "invalid_value" }] }
}
]
}
| Поле | Тип | Описание |
|---|---|---|
succeeded[] |
array | Объекты измерений (как в ответе одиночного создания, без timestamp) |
failed[].index |
integer | Позиция отклонённого элемента в dimensions |
failed[].error |
object | code, message, details из раздела 4 страницы Публичный API v2 |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.VALIDATION_FAILED |
400 | dimensions пуст или элемент некорректен |
DF_API.BULK_REJECTED |
422 | Ни один элемент не применён; details[] адресует каждый элемент (dimensions.<index>) |
| Коды по элементам | в failed[] |
duplicate_name, missing_required_field, invalid_enum_value, resource_not_found (неизвестный id), invalid_formula_syntax, formula_reference_not_found, circular_dependency, invalid_parameter_type |
DF_API.INVALID_SOURCE_*, DF_API.MISSING_REQUIRED_FIELD |
в failed[] |
Проверка connected_source элемента (раздел 1) |
2.14 Заменить измерение
Запрос
PUT {v}/dimensions/{dimension_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
dimension_id |
путь | integer | да | Идентификатор измерения |
dimension_name |
тело | string | да | Имя измерения; уникально среди измерений версии |
dimension_type |
тело | string | да | Подпись справочника «Тип измерения»: Primary / Derived |
group, block |
тело | string | нет | Группирующие колонки РПИ |
dimension_description |
тело | string | нет | До 255 символов |
original_source_type, original_source, original_object |
тело | string | нет | Колонки происхождения |
dimension_group |
тело | string | нет | Имя существующей группы измерений; измерение становится её членом |
display_data_type |
тело | string | нет | Подпись справочника «Отображаемый тип данных» |
source_data_type |
тело | string | нет | Принимается и игнорируется — вычисляется из connected_source |
formula |
тело | string | нет | Формула производного измерения |
connected_source |
тело | object | нет | Объект источника (раздел 3.6 страницы API): connection (необязательно), db (обязательно), schema, table (обязательно), column |
comment, value_options, responsible_for_data |
тело | string | нет | Текстовые колонки |
status |
тело | string | нет | Подпись справочника «Статус» |
relevance, required, visibility |
тело | "true" | "false" |
нет | Колонки-флаги |
Детали
dimension_name и dimension_type обязательны; каждая непереданная опциональная колонка сбрасывается. Непереданный dimension_group исключает измерение из его группы.
Ответ
200 OK
{
"id": "2000",
"group": "Customer",
"block": "Profile",
"dimension_name": "Customer name",
"dimension_description": "Full customer name",
"original_source_type": null,
"original_source": null,
"original_object": null,
"dimension_group": "Customers",
"display_data_type": "Text",
"source_data_type": "VARCHAR(255)",
"dimension_type": "Primary",
"formula": null,
"connected_source": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_customer", "column": "customer_name" },
"comment": null,
"value_options": null,
"status": "Active",
"relevance": null,
"required": null,
"visibility": null,
"responsible_for_data": null,
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор нового измерения — {dimension_id} остальных эндпоинтов |
group, block |
string | null | Группирующие колонки РПИ |
dimension_name, dimension_description |
string / string | null | Имя и описание |
original_source_type, original_source, original_object |
string | null | Колонки происхождения; свободный текст |
dimension_group |
string | null | Имя группы измерений, в которую входит измерение |
display_data_type |
string | null | Локализованная подпись типа данных |
source_data_type |
string | null | Физический тип колонки, полученный из закешированной схемы подключения |
dimension_type |
string | Локализованная подпись: Primary или Derived |
formula |
string | null | Формула производного измерения |
connected_source |
object | null | Объект источника { db, schema, table, column } (раздел 3.6 страницы API) |
comment, responsible_for_data |
string | null | Текстовые колонки |
value_options |
string | null | Колонка допустимых значений |
status |
string | null | Локализованная подпись справочника «Статус» |
relevance, required, visibility |
boolean | null | Колонки-флаги; в ответах записи — булевы, null, если не заданы |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Измерение не существует в версии |
DF_API.MISSING_REQUIRED_FIELD |
400 | Отсутствует dimension_name или dimension_type |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
DF_API.DUPLICATE_NAME |
409 | Измерение с таким именем уже есть в версии |
DF_API.INVALID_ENUM_VALUE |
400 | dimension_type не совпал ни с одним вариантом |
DF_API.INVALID_SOURCE_*, DF_API.MISSING_REQUIRED_FIELD |
400 | Проверка connected_source (раздел 1) |
DF_API.INVALID_FORMULA_SYNTAX |
422 | Формула не разобрана |
DF_API.FORMULA_REFERENCE_NOT_FOUND |
422 | Формула ссылается на неизвестный элемент |
DF_API.CIRCULAR_DEPENDENCY |
422 | Формула образует цикл |
DF_API.INVALID_PARAMETER_TYPE |
422 | Измерение, переданное в периодную функцию, не привязано к колонке даты/времени |
2.15 Обновить измерение
Запрос
PATCH {v}/dimensions/{dimension_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
dimension_id |
путь | integer | да | Идентификатор измерения |
dimension_name |
тело | string | нет | Имя измерения; уникально среди измерений версии |
dimension_type |
тело | string | нет | Подпись справочника «Тип измерения»: Primary / Derived |
group, block |
тело | string | нет | Группирующие колонки РПИ |
dimension_description |
тело | string | нет | До 255 символов |
original_source_type, original_source, original_object |
тело | string | нет | Колонки происхождения |
dimension_group |
тело | string | нет | Имя существующей группы измерений; измерение становится её членом |
display_data_type |
тело | string | нет | Подпись справочника «Отображаемый тип данных» |
source_data_type |
тело | string | нет | Принимается и игнорируется — вычисляется из connected_source |
formula |
тело | string | нет | Формула производного измерения |
connected_source |
тело | object | нет | Объект источника (раздел 3.6 страницы API): connection (необязательно), db (обязательно), schema, table (обязательно), column |
comment, value_options, responsible_for_data |
тело | string | нет | Текстовые колонки |
status |
тело | string | нет | Подпись справочника «Статус» |
relevance, required, visibility |
тело | "true" | "false" |
нет | Колонки-флаги |
Детали
Изменяются только переданные поля.
Ответ
200 OK
{
"id": "2000",
"group": "Customer",
"block": "Profile",
"dimension_name": "Customer name",
"dimension_description": "Full customer name",
"original_source_type": null,
"original_source": null,
"original_object": null,
"dimension_group": "Customers",
"display_data_type": "Text",
"source_data_type": "VARCHAR(255)",
"dimension_type": "Primary",
"formula": null,
"connected_source": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_customer", "column": "customer_name" },
"comment": null,
"value_options": null,
"status": "Active",
"relevance": null,
"required": null,
"visibility": null,
"responsible_for_data": null,
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор нового измерения — {dimension_id} остальных эндпоинтов |
group, block |
string | null | Группирующие колонки РПИ |
dimension_name, dimension_description |
string / string | null | Имя и описание |
original_source_type, original_source, original_object |
string | null | Колонки происхождения; свободный текст |
dimension_group |
string | null | Имя группы измерений, в которую входит измерение |
display_data_type |
string | null | Локализованная подпись типа данных |
source_data_type |
string | null | Физический тип колонки, полученный из закешированной схемы подключения |
dimension_type |
string | Локализованная подпись: Primary или Derived |
formula |
string | null | Формула производного измерения |
connected_source |
object | null | Объект источника { db, schema, table, column } (раздел 3.6 страницы API) |
comment, responsible_for_data |
string | null | Текстовые колонки |
value_options |
string | null | Колонка допустимых значений |
status |
string | null | Локализованная подпись справочника «Статус» |
relevance, required, visibility |
boolean | null | Колонки-флаги; в ответах записи — булевы, null, если не заданы |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Измерение не существует в версии |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
DF_API.DUPLICATE_NAME |
409 | Измерение с таким именем уже есть в версии |
DF_API.INVALID_ENUM_VALUE |
400 | dimension_type не совпал ни с одним вариантом |
DF_API.INVALID_SOURCE_*, DF_API.MISSING_REQUIRED_FIELD |
400 | Проверка connected_source (раздел 1) |
DF_API.INVALID_FORMULA_SYNTAX |
422 | Формула не разобрана |
DF_API.FORMULA_REFERENCE_NOT_FOUND |
422 | Формула ссылается на неизвестный элемент |
DF_API.CIRCULAR_DEPENDENCY |
422 | Формула образует цикл |
DF_API.INVALID_PARAMETER_TYPE |
422 | Измерение, переданное в периодную функцию, не привязано к колонке даты/времени |
2.16 Удалить измерение
Запрос
DELETE {v}/dimensions/{dimension_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
dimension_id |
путь | integer | да | Идентификатор измерения |
Детали
Измерение, входящее в группу измерений или используемое в формуле, удалить нельзя — сначала исключите его из группы (DELETE {v}/dimension-groups/{dimension_group_id}/dimensions/{dimension_id}).
Ответ
204 No Content
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Измерение не существует в версии |
DF_API.CONSTRAINT_VIOLATION |
409 | Измерение входит в группу измерений или на него ссылается формула |
2.17 Создать факт
Запрос
POST {v}/facts
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
fact_name |
тело | string | да | Имя факта; уникально среди фактов версии |
fact_type |
тело | string | да | Подпись справочника «Тип факта»: Primary / Derived |
group, block |
тело | string | нет | Группирующие колонки РПИ |
fact_description |
тело | string | нет | До 255 символов |
original_source_type, original_source, original_object |
тело | string | нет | Колонки происхождения |
source_data_type |
тело | string | нет | Принимается и игнорируется — вычисляется из connected_source |
formula |
тело | string | нет | Формула производного факта |
connected_source |
тело | object | нет | Объект источника (раздел 3.6 страницы API) |
report_for_verification, comment, responsible_for_data |
тело | string | нет | Текстовые колонки |
status |
тело | string | нет | Подпись справочника «Статус» |
relevance, required, visibility |
тело | "true" | "false" |
нет | Колонки-флаги |
{
"fact_name": "Order line",
"fact_type": "primary",
"connected_source": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "fact_order_line", "column": "amount" }
}
Ответ
201 Created
{
"id": "3000",
"group": "Sales",
"block": "Orders",
"fact_name": "Order line",
"fact_description": "An individual line item on a sales order",
"original_source_type": null,
"original_source": null,
"original_object": null,
"source_data_type": "DECIMAL(18,2)",
"fact_type": "Primary",
"formula": null,
"connected_source": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "fact_order_line", "column": "amount" },
"report_for_verification": null,
"comment": null,
"status": null,
"relevance": null,
"required": null,
"visibility": null,
"responsible_for_data": null,
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор нового факта — {fact_id} остальных эндпоинтов |
group, block |
string | null | Группирующие колонки РПИ |
fact_name, fact_description |
string / string | null | Имя и описание |
original_source_type, original_source, original_object |
string | null | Колонки происхождения; свободный текст |
source_data_type |
string | null | Физический тип колонки, полученный из закешированной схемы подключения |
fact_type |
string | Локализованная подпись: Primary или Derived |
formula |
string | null | Формула производного факта |
connected_source |
object | null | Объект источника { db, schema, table, column } (раздел 3.6 страницы API) |
report_for_verification, comment, responsible_for_data |
string | null | Текстовые колонки |
status |
string | null | Локализованная подпись справочника «Статус» |
relevance, required, visibility |
boolean | null | Колонки-флаги; в ответах записи — булевы, null, если не заданы |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.DUPLICATE_NAME |
409 | Факт с таким именем уже есть в версии |
DF_API.INVALID_ENUM_VALUE |
400 | fact_type не совпал ни с одним вариантом |
DF_API.INVALID_SOURCE_*, DF_API.MISSING_REQUIRED_FIELD |
400 | Проверка connected_source (раздел 1) |
DF_API.INVALID_FORMULA_SYNTAX |
422 | Формула не разобрана |
DF_API.FORMULA_REFERENCE_NOT_FOUND |
422 | Формула ссылается на неизвестный элемент |
DF_API.CIRCULAR_DEPENDENCY |
422 | Формула образует цикл |
DF_API.INVALID_PARAMETER_TYPE |
422 | Измерение, переданное в периодную функцию, не привязано к колонке даты/времени |
2.18 Массовое создание/обновление фактов
Запрос
POST {v}/facts/bulk
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
facts |
тело | array | да | Не менее одного элемента |
facts[].fact_name |
тело | string | нет | Имя факта; уникально среди фактов версии |
facts[].fact_type |
тело | string | нет | Подпись справочника «Тип факта»: Primary / Derived |
facts[].group, facts[].block |
тело | string | нет | Группирующие колонки РПИ |
facts[].fact_description |
тело | string | нет | До 255 символов |
facts[].original_source_type, facts[].original_source, facts[].original_object |
тело | string | нет | Колонки происхождения |
facts[].source_data_type |
тело | string | нет | Принимается и игнорируется — вычисляется из connected_source |
facts[].formula |
тело | string | нет | Формула производного факта |
facts[].connected_source |
тело | object | нет | Объект источника (раздел 3.6 страницы API) |
facts[].report_for_verification, facts[].comment, facts[].responsible_for_data |
тело | string | нет | Текстовые колонки |
facts[].status |
тело | string | нет | Подпись справочника «Статус» |
facts[].relevance, facts[].required, facts[].visibility |
тело | "true" | "false" |
нет | Колонки-флаги |
{
"facts": [
{ "fact_name": "Order line", "fact_type": "primary" },
{ "id": "3000", "fact_description": "Отдельная строка заказа" }
]
}
Детали
Элементы обрабатываются по порядку, каждый в своей транзакции: сбойный элемент ничего не оставляет и не останавливает остальные. failed[].index — позиция элемента в запросе. На весь запрос пишется одна сводная запись аудита.
Ответ
201 Created, если применены все элементы; 207 Multi-Status, если часть элементов отклонена:
{
"timestamp": "2026-05-05T08:30:00.120Z",
"succeeded": [
{ "id": "3000", "fact_name": "Order line", "fact_type": "Primary", "…": "…" }
],
"failed": [
{
"index": 1,
"error": { "code": "duplicate_name", "message": "Факт с таким именем уже существует", "details": [{ "field": "fact_name", "code": "invalid_value" }] }
}
]
}
| Поле | Тип | Описание |
|---|---|---|
succeeded[] |
array | Объекты фактов (как в ответе одиночного создания, без timestamp) |
failed[].index |
integer | Позиция отклонённого элемента в facts |
failed[].error |
object | code, message, details из раздела 4 страницы Публичный API v2 |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.VALIDATION_FAILED |
400 | facts пуст или элемент некорректен |
DF_API.BULK_REJECTED |
422 | Ни один элемент не применён; details[] адресует каждый элемент (facts.<index>) |
| Коды по элементам | в failed[] |
duplicate_name, missing_required_field, invalid_enum_value, resource_not_found (неизвестный id), invalid_formula_syntax, formula_reference_not_found, circular_dependency, invalid_parameter_type |
DF_API.INVALID_SOURCE_*, DF_API.MISSING_REQUIRED_FIELD |
в failed[] |
Проверка connected_source элемента (раздел 1) |
2.19 Заменить факт
Запрос
PUT {v}/facts/{fact_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_id |
путь | integer | да | Идентификатор факта |
fact_name |
тело | string | да | Имя факта; уникально среди фактов версии |
fact_type |
тело | string | да | Подпись справочника «Тип факта»: Primary / Derived |
group, block |
тело | string | нет | Группирующие колонки РПИ |
fact_description |
тело | string | нет | До 255 символов |
original_source_type, original_source, original_object |
тело | string | нет | Колонки происхождения |
source_data_type |
тело | string | нет | Принимается и игнорируется — вычисляется из connected_source |
formula |
тело | string | нет | Формула производного факта |
connected_source |
тело | object | нет | Объект источника (раздел 3.6 страницы API) |
report_for_verification, comment, responsible_for_data |
тело | string | нет | Текстовые колонки |
status |
тело | string | нет | Подпись справочника «Статус» |
relevance, required, visibility |
тело | "true" | "false" |
нет | Колонки-флаги |
Детали
fact_name и fact_type обязательны; каждая непереданная опциональная колонка сбрасывается в пустое значение.
Ответ
200 OK
{
"id": "3000",
"group": "Sales",
"block": "Orders",
"fact_name": "Order line",
"fact_description": "An individual line item on a sales order",
"original_source_type": null,
"original_source": null,
"original_object": null,
"source_data_type": "DECIMAL(18,2)",
"fact_type": "Primary",
"formula": null,
"connected_source": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "fact_order_line", "column": "amount" },
"report_for_verification": null,
"comment": null,
"status": null,
"relevance": null,
"required": null,
"visibility": null,
"responsible_for_data": null,
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор нового факта — {fact_id} остальных эндпоинтов |
group, block |
string | null | Группирующие колонки РПИ |
fact_name, fact_description |
string / string | null | Имя и описание |
original_source_type, original_source, original_object |
string | null | Колонки происхождения; свободный текст |
source_data_type |
string | null | Физический тип колонки, полученный из закешированной схемы подключения |
fact_type |
string | Локализованная подпись: Primary или Derived |
formula |
string | null | Формула производного факта |
connected_source |
object | null | Объект источника { db, schema, table, column } (раздел 3.6 страницы API) |
report_for_verification, comment, responsible_for_data |
string | null | Текстовые колонки |
status |
string | null | Локализованная подпись справочника «Статус» |
relevance, required, visibility |
boolean | null | Колонки-флаги; в ответах записи — булевы, null, если не заданы |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Факт не существует в версии |
DF_API.MISSING_REQUIRED_FIELD |
400 | Отсутствует fact_name или fact_type |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
DF_API.DUPLICATE_NAME |
409 | Факт с таким именем уже есть в версии |
DF_API.INVALID_ENUM_VALUE |
400 | fact_type не совпал ни с одним вариантом |
DF_API.INVALID_SOURCE_*, DF_API.MISSING_REQUIRED_FIELD |
400 | Проверка connected_source (раздел 1) |
DF_API.INVALID_FORMULA_SYNTAX |
422 | Формула не разобрана |
DF_API.FORMULA_REFERENCE_NOT_FOUND |
422 | Формула ссылается на неизвестный элемент |
DF_API.CIRCULAR_DEPENDENCY |
422 | Формула образует цикл |
DF_API.INVALID_PARAMETER_TYPE |
422 | Измерение, переданное в периодную функцию, не привязано к колонке даты/времени |
2.20 Обновить факт
Запрос
PATCH {v}/facts/{fact_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_id |
путь | integer | да | Идентификатор факта |
fact_name |
тело | string | нет | Имя факта; уникально среди фактов версии |
fact_type |
тело | string | нет | Подпись справочника «Тип факта»: Primary / Derived |
group, block |
тело | string | нет | Группирующие колонки РПИ |
fact_description |
тело | string | нет | До 255 символов |
original_source_type, original_source, original_object |
тело | string | нет | Колонки происхождения |
source_data_type |
тело | string | нет | Принимается и игнорируется — вычисляется из connected_source |
formula |
тело | string | нет | Формула производного факта |
connected_source |
тело | object | нет | Объект источника (раздел 3.6 страницы API) |
report_for_verification, comment, responsible_for_data |
тело | string | нет | Текстовые колонки |
status |
тело | string | нет | Подпись справочника «Статус» |
relevance, required, visibility |
тело | "true" | "false" |
нет | Колонки-флаги |
Детали
Изменяются только переданные поля.
Ответ
200 OK
{
"id": "3000",
"group": "Sales",
"block": "Orders",
"fact_name": "Order line",
"fact_description": "An individual line item on a sales order",
"original_source_type": null,
"original_source": null,
"original_object": null,
"source_data_type": "DECIMAL(18,2)",
"fact_type": "Primary",
"formula": null,
"connected_source": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "fact_order_line", "column": "amount" },
"report_for_verification": null,
"comment": null,
"status": null,
"relevance": null,
"required": null,
"visibility": null,
"responsible_for_data": null,
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор нового факта — {fact_id} остальных эндпоинтов |
group, block |
string | null | Группирующие колонки РПИ |
fact_name, fact_description |
string / string | null | Имя и описание |
original_source_type, original_source, original_object |
string | null | Колонки происхождения; свободный текст |
source_data_type |
string | null | Физический тип колонки, полученный из закешированной схемы подключения |
fact_type |
string | Локализованная подпись: Primary или Derived |
formula |
string | null | Формула производного факта |
connected_source |
object | null | Объект источника { db, schema, table, column } (раздел 3.6 страницы API) |
report_for_verification, comment, responsible_for_data |
string | null | Текстовые колонки |
status |
string | null | Локализованная подпись справочника «Статус» |
relevance, required, visibility |
boolean | null | Колонки-флаги; в ответах записи — булевы, null, если не заданы |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Факт не существует в версии |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
DF_API.DUPLICATE_NAME |
409 | Факт с таким именем уже есть в версии |
DF_API.INVALID_ENUM_VALUE |
400 | fact_type не совпал ни с одним вариантом |
DF_API.INVALID_SOURCE_*, DF_API.MISSING_REQUIRED_FIELD |
400 | Проверка connected_source (раздел 1) |
DF_API.INVALID_FORMULA_SYNTAX |
422 | Формула не разобрана |
DF_API.FORMULA_REFERENCE_NOT_FOUND |
422 | Формула ссылается на неизвестный элемент |
DF_API.CIRCULAR_DEPENDENCY |
422 | Формула образует цикл |
DF_API.INVALID_PARAMETER_TYPE |
422 | Измерение, переданное в периодную функцию, не привязано к колонке даты/времени |
2.21 Удалить факт
Запрос
DELETE {v}/facts/{fact_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_id |
путь | integer | да | Идентификатор факта |
Ответ
204 No Content
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Факт не существует в версии |
DF_API.CONSTRAINT_VIOLATION |
409 | На факт ссылается формула |
2.22 Создать группу измерений
Запрос
POST {v}/dimension-groups
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
name |
тело | string | да | 1–64 символа; буквы, цифры, пробел, ., -, _; начинается с буквы или цифры; уникально среди групп версии |
description |
тело | string | нет | До 255 символов |
primary_key |
тело | object | да | Объект источника ключа группы (раздел 3.6 страницы API): connection (необязательно), db, table обязательны, schema, column необязательны |
dimensions |
тело | array | нет | Начальный состав: { "id": "<id измерения>", "level": <целое ≥ 1> }; уровни должны быть уникальны |
{
"name": "Geography",
"description": "Geographic regions and countries",
"primary_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_geography", "column": "region_id" },
"dimensions": [ { "id": "722", "level": 1 }, { "id": "723", "level": 2 } ]
}
Детали
level — уровень иерархии члена внутри группы, сохраняется как есть (без перенумерации).
Ответ
201 Created
{
"id": "9",
"name": "Geography",
"description": "Geographic regions and countries",
"primary_key": {
"connection": "Production PostgreSQL",
"db": "analytics_db",
"schema": "public",
"table": "dim_geography",
"column": "region_id"
},
"dimensions": [
{ "id": "722", "name": "Region", "description": "Sales region", "level": 1, "display_data_type": "Text", "physical_column": "region_name" }
],
"related_fact_tables": [
{ "fact_table_id": "11", "fact_table_name": "fact_sales", "foreign_key_column": "region_id" }
],
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
dimensions[] |
array | Члены группы с id, name, description, level, display_data_type, physical_column |
related_fact_tables[] |
array | fact_table_id, fact_table_name, foreign_key_column |
id, name, description |
string / string / string | null | Идентификация |
primary_key |
object | null | Объект источника с connection (раздел 3.6 страницы API); null, если у группы ещё нет ключа |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.DUPLICATE_NAME |
409 | Группа с таким именем уже есть в версии |
DF_API.DUPLICATE_LEVEL |
409 | Два члена имеют одинаковый level |
DF_API.RESOURCE_NOT_FOUND |
404 | id члена не является измерением версии |
DF_API.INVALID_SOURCE_* |
400 | Проверка primary_key (раздел 1) |
2.23 Заменить группу измерений
Запрос
PUT {v}/dimension-groups/{dimension_group_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
dimension_group_id |
путь | integer | да | Идентификатор группы |
name |
тело | string | да | Как при создании |
primary_key |
тело | object | да | Как при создании |
description |
тело | string | нет | Не передано — сбрасывается в пустое |
Детали
Заменяет только метаданные группы; состав управляется эндпоинтами …/dimension-groups/{dimension_group_id}/dimensions и не затрагивается.
Ответ
200 OK
{
"id": "9",
"name": "Geography",
"description": "Geographic regions and countries",
"primary_key": {
"connection": "Production PostgreSQL",
"db": "analytics_db",
"schema": "public",
"table": "dim_geography",
"column": "region_id"
},
"dimensions": [
{ "id": "722", "name": "Region", "description": "Sales region", "level": 1, "display_data_type": "Text", "physical_column": "region_name" }
],
"related_fact_tables": [
{ "fact_table_id": "11", "fact_table_name": "fact_sales", "foreign_key_column": "region_id" }
],
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
dimensions[] |
array | Члены группы с id, name, description, level, display_data_type, physical_column |
related_fact_tables[] |
array | fact_table_id, fact_table_name, foreign_key_column |
id, name, description |
string / string / string | null | Идентификация |
primary_key |
object | null | Объект источника с connection (раздел 3.6 страницы API); null, если у группы ещё нет ключа |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.DIMENSION_GROUP_NOT_FOUND |
404 | Группа не существует в версии |
DF_API.MISSING_REQUIRED_FIELD |
400 | Отсутствует name или primary_key |
DF_API.DUPLICATE_NAME |
409 | Новое имя занято другой группой |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
2.24 Обновить группу измерений
Запрос
PATCH {v}/dimension-groups/{dimension_group_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
dimension_group_id |
путь | integer | да | Идентификатор группы измерений |
name |
тело | string | нет | Как при создании |
primary_key |
тело | object | нет | Как при создании |
description |
тело | string | нет | Не передано — сбрасывается в пустое |
Детали
Изменяются только переданные поля; состав группы не затрагивается.
Ответ
200 OK
{
"id": "9",
"name": "Geography",
"description": "Geographic regions and countries",
"primary_key": {
"connection": "Production PostgreSQL",
"db": "analytics_db",
"schema": "public",
"table": "dim_geography",
"column": "region_id"
},
"dimensions": [
{ "id": "722", "name": "Region", "description": "Sales region", "level": 1, "display_data_type": "Text", "physical_column": "region_name" }
],
"related_fact_tables": [
{ "fact_table_id": "11", "fact_table_name": "fact_sales", "foreign_key_column": "region_id" }
],
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
dimensions[] |
array | Члены группы с id, name, description, level, display_data_type, physical_column |
related_fact_tables[] |
array | fact_table_id, fact_table_name, foreign_key_column |
id, name, description |
string / string / string | null | Идентификация |
primary_key |
object | null | Объект источника с connection (раздел 3.6 страницы API); null, если у группы ещё нет ключа |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.DIMENSION_GROUP_NOT_FOUND |
404 | Группа не существует в версии |
DF_API.DUPLICATE_NAME |
409 | Новое имя занято другой группой |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
2.25 Удалить группу измерений
Запрос
DELETE {v}/dimension-groups/{dimension_group_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
dimension_group_id |
путь | integer | да | Идентификатор группы измерений |
Детали
Группу, назначенную какой-либо таблице фактов — просто назначенную или соединённую связью, — удалить нельзя; сначала снимите назначение (DELETE {v}/fact-tables/{fact_table_id}/dimension-groups/{dimension_group_id}).
Ответ
204 No Content
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.DIMENSION_GROUP_NOT_FOUND |
404 | Группа не существует в версии |
DF_API.CONSTRAINT_VIOLATION |
409 | Группа назначена таблице фактов |
2.26 Добавить измерения в группу
Запрос
POST {v}/dimension-groups/{dimension_group_id}/dimensions
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
dimension_group_id |
путь | integer | да | Идентификатор группы |
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
dimensions |
тело | array | да | Не менее одного { "id": "<id измерения>", "level": <целое ≥ 1> } |
{ "dimensions": [ { "id": "724", "level": 3 } ] }
Детали
Существующие члены группы остаются на местах; перечисленный член, уже входящий в группу, получает новый level. Уровни должны оставаться уникальными во всей группе. В отличие от эндпоинтов состава таблиц фактов, этот вызов выполняется целиком или не выполняется вовсе и отвечает 200 объектом группы (без сводки succeeded / failed).
Ответ
200 OK
{
"id": "9",
"name": "Geography",
"description": "Geographic regions and countries",
"primary_key": {
"connection": "Production PostgreSQL",
"db": "analytics_db",
"schema": "public",
"table": "dim_geography",
"column": "region_id"
},
"dimensions": [
{ "id": "722", "name": "Region", "description": "Sales region", "level": 1, "display_data_type": "Text", "physical_column": "region_name" }
],
"related_fact_tables": [
{ "fact_table_id": "11", "fact_table_name": "fact_sales", "foreign_key_column": "region_id" }
],
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
dimensions[] |
array | Члены группы с id, name, description, level, display_data_type, physical_column |
related_fact_tables[] |
array | fact_table_id, fact_table_name, foreign_key_column |
id, name, description |
string / string / string | null | Идентификация |
primary_key |
object | null | Объект источника с connection (раздел 3.6 страницы API); null, если у группы ещё нет ключа |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.DIMENSION_GROUP_NOT_FOUND |
404 | Группа не существует в версии |
DF_API.RESOURCE_NOT_FOUND |
404 | id измерения не существует в версии |
DF_API.DUPLICATE_LEVEL |
409 | Два члена получили бы одинаковый level |
2.27 Изменить уровень иерархии члена
Запрос
PATCH {v}/dimension-groups/{dimension_group_id}/dimensions/{dimension_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
dimension_group_id, dimension_id |
путь | integer | да | Идентификаторы |
level |
тело | integer ≥ 1 | да | Новый уровень иерархии |
Ответ
200 OK
{
"id": "9",
"name": "Geography",
"description": "Geographic regions and countries",
"primary_key": {
"connection": "Production PostgreSQL",
"db": "analytics_db",
"schema": "public",
"table": "dim_geography",
"column": "region_id"
},
"dimensions": [
{ "id": "722", "name": "Region", "description": "Sales region", "level": 1, "display_data_type": "Text", "physical_column": "region_name" }
],
"related_fact_tables": [
{ "fact_table_id": "11", "fact_table_name": "fact_sales", "foreign_key_column": "region_id" }
],
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
dimensions[] |
array | Члены группы с id, name, description, level, display_data_type, physical_column |
related_fact_tables[] |
array | fact_table_id, fact_table_name, foreign_key_column |
id, name, description |
string / string / string | null | Идентификация |
primary_key |
object | null | Объект источника с connection (раздел 3.6 страницы API); null, если у группы ещё нет ключа |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Измерение не является членом группы |
DF_API.DUPLICATE_LEVEL |
409 | Другой член уже имеет этот level |
2.28 Исключить измерение из группы
Запрос
DELETE {v}/dimension-groups/{dimension_group_id}/dimensions/{dimension_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
dimension_group_id |
путь | integer | да | Идентификатор группы измерений |
dimension_id |
путь | integer | да | Идентификатор измерения |
Ответ
204 No Content
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Измерение не является членом группы (повторное удаление не является тихой no-op операцией) |
2.29 Создать таблицу фактов
Запрос
POST {v}/fact-tables
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
name |
тело | string | да | 1–64 символа; буквы, цифры, _, ., -, пробел; начинается с буквы или цифры; уникально среди таблиц фактов версии |
description |
тело | string | нет | До 255 символов |
owner |
тело | string | нет | Принимается и игнорируется — владельцем становится владелец ключа |
{ "name": "fact_sales", "description": "Primary sales facts" }
Детали
У таблицы фактов, созданной через API, нет собственной базовой физической таблицы; элементы присоединяются эндпоинтами состава (POST {v}/fact-tables/{fact_table_id}/measures, …/dimensions, …/facts, …/dimension-groups).
Ответ
201 Created
{
"id": "11",
"name": "fact_sales",
"description": "Primary sales facts",
"owner": "Pavel Shalavin",
"created_at": "2026-05-05T08:30:00.000Z",
"measures": [],
"dimensions": [],
"facts": [],
"dimension_groups": [],
"verification_filters": [],
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
measures[].display_data_type |
string | null | Локализованная подпись типа данных |
measures[].measure_type |
string | null | base или calculated |
dimensions[].dimension_type |
string | null | primary или derived |
dimensions[].formula |
string | null | Формула производного измерения |
facts[].fact_type |
string | null | primary, derived или constant |
measures[].dependencies |
array | null | Присутствует и заполняется только при include_dependencies=true; узел содержит id, name, type, formula и рекурсивный массив dependencies |
dimensions[].is_from_dimension_group |
boolean | true — измерение унаследовано из связанной группы; false — задано прямо в таблице фактов |
dimensions[].dimension_group_id |
string | null | Группа, из которой унаследовано измерение |
…physical_column |
string | null | Колонка исходной таблицы, привязанная к элементу |
dimension_groups[].primary_key, foreign_key |
object | null | Объекты источника соединения (раздел 3.6 страницы API) |
verification_filters[].is_valid |
boolean | false, если выражение фильтра не разрешается (отсутствующая ссылка, ошибка синтаксиса); invalid_reason несёт локализованное объяснение |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.DUPLICATE_NAME |
409 | Таблица фактов с таким именем уже есть в версии |
2.30 Заменить таблицу фактов
Запрос
PUT {v}/fact-tables/{fact_table_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
name |
тело | string | да | 1–64 символа; буквы, цифры, _, ., -, пробел; начинается с буквы или цифры; уникально среди таблиц фактов версии |
description |
тело | string | нет | До 255 символов |
owner |
тело | string | нет | Принимается и игнорируется — владельцем становится владелец ключа |
Детали
name обязателен; непереданный description сбрасывается в пустое значение. Назначения элементов не затрагиваются.
Ответ
200 OK
{
"id": "11",
"name": "fact_sales",
"description": "Primary sales facts",
"owner": "Pavel Shalavin",
"created_at": "2026-04-15T08:30:00Z",
"measures": [
{ "id": "501", "name": "Total revenue", "description": "Gross revenue", "formula": "SUM([Amount])", "display_data_type": "Number", "measure_type": "base", "dependencies": null }
],
"dimensions": [
{ "id": "801", "name": "Sale date", "description": "Calendar date of the sale", "display_data_type": "Date", "dimension_type": "primary", "formula": null, "physical_column": "sale_date", "is_from_dimension_group": false, "dimension_group_id": null }
],
"facts": [
{ "id": "611", "name": "Order line", "description": null, "fact_type": "primary", "formula": null, "physical_column": "amount" }
],
"dimension_groups": [
{
"id": "9", "name": "Geography", "description": "Geographic regions and countries",
"primary_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_geography", "column": "region_id" },
"foreign_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "fact_sales", "column": "region_id" }
}
],
"verification_filters": [
{ "id": "301", "name": "Valid sales only", "description": "Excludes test and cancelled orders", "conditions": "[Status] != 'cancelled'", "is_valid": true, "invalid_reason": null }
],
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
measures[].display_data_type |
string | null | Локализованная подпись типа данных |
measures[].measure_type |
string | null | base или calculated |
dimensions[].dimension_type |
string | null | primary или derived |
dimensions[].formula |
string | null | Формула производного измерения |
facts[].fact_type |
string | null | primary, derived или constant |
measures[].dependencies |
array | null | Присутствует и заполняется только при include_dependencies=true; узел содержит id, name, type, formula и рекурсивный массив dependencies |
dimensions[].is_from_dimension_group |
boolean | true — измерение унаследовано из связанной группы; false — задано прямо в таблице фактов |
dimensions[].dimension_group_id |
string | null | Группа, из которой унаследовано измерение |
…physical_column |
string | null | Колонка исходной таблицы, привязанная к элементу |
dimension_groups[].primary_key, foreign_key |
object | null | Объекты источника соединения (раздел 3.6 страницы API) |
verification_filters[].is_valid |
boolean | false, если выражение фильтра не разрешается (отсутствующая ссылка, ошибка синтаксиса); invalid_reason несёт локализованное объяснение |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.MISSING_REQUIRED_FIELD |
400 | Отсутствует name |
DF_API.DUPLICATE_NAME |
409 | Новое имя занято другой таблицей фактов |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
2.31 Обновить таблицу фактов
Запрос
PATCH {v}/fact-tables/{fact_table_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
name |
тело | string | нет | 1–64 символа; буквы, цифры, _, ., -, пробел; начинается с буквы или цифры; уникально среди таблиц фактов версии |
description |
тело | string | нет | До 255 символов |
owner |
тело | string | нет | Принимается и игнорируется — владельцем становится владелец ключа |
Детали
Изменяются только переданные поля.
Ответ
200 OK
{
"id": "11",
"name": "fact_sales",
"description": "Primary sales facts",
"owner": "Pavel Shalavin",
"created_at": "2026-04-15T08:30:00Z",
"measures": [
{ "id": "501", "name": "Total revenue", "description": "Gross revenue", "formula": "SUM([Amount])", "display_data_type": "Number", "measure_type": "base", "dependencies": null }
],
"dimensions": [
{ "id": "801", "name": "Sale date", "description": "Calendar date of the sale", "display_data_type": "Date", "dimension_type": "primary", "formula": null, "physical_column": "sale_date", "is_from_dimension_group": false, "dimension_group_id": null }
],
"facts": [
{ "id": "611", "name": "Order line", "description": null, "fact_type": "primary", "formula": null, "physical_column": "amount" }
],
"dimension_groups": [
{
"id": "9", "name": "Geography", "description": "Geographic regions and countries",
"primary_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_geography", "column": "region_id" },
"foreign_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "fact_sales", "column": "region_id" }
}
],
"verification_filters": [
{ "id": "301", "name": "Valid sales only", "description": "Excludes test and cancelled orders", "conditions": "[Status] != 'cancelled'", "is_valid": true, "invalid_reason": null }
],
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
measures[].display_data_type |
string | null | Локализованная подпись типа данных |
measures[].measure_type |
string | null | base или calculated |
dimensions[].dimension_type |
string | null | primary или derived |
dimensions[].formula |
string | null | Формула производного измерения |
facts[].fact_type |
string | null | primary, derived или constant |
measures[].dependencies |
array | null | Присутствует и заполняется только при include_dependencies=true; узел содержит id, name, type, formula и рекурсивный массив dependencies |
dimensions[].is_from_dimension_group |
boolean | true — измерение унаследовано из связанной группы; false — задано прямо в таблице фактов |
dimensions[].dimension_group_id |
string | null | Группа, из которой унаследовано измерение |
…physical_column |
string | null | Колонка исходной таблицы, привязанная к элементу |
dimension_groups[].primary_key, foreign_key |
object | null | Объекты источника соединения (раздел 3.6 страницы API) |
verification_filters[].is_valid |
boolean | false, если выражение фильтра не разрешается (отсутствующая ссылка, ошибка синтаксиса); invalid_reason несёт локализованное объяснение |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.DUPLICATE_NAME |
409 | Новое имя занято другой таблицей фактов |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
2.32 Удалить таблицу фактов
Запрос
DELETE {v}/fact-tables/{fact_table_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
Детали
Таблицу фактов с активной связью (группой измерений, соединённой внешним ключом) удалить нельзя — сначала удалите связи (DELETE {v}/relationships/{relationship_id}). Простые назначения (показатели, измерения, факты, группы без ключа, фильтры верификации) удаляются вместе с таблицей атомарно.
Ответ
204 No Content
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.CONSTRAINT_VIOLATION |
409 | У таблицы фактов есть активные связи |
2.33 Назначить показатели таблице фактов
Запрос
POST {v}/fact-tables/{fact_table_id}/measures
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
measure_ids |
тело | array of string | да | Не менее одного идентификатора показателя |
{ "measure_ids": ["501", "502"] }
Детали
Идентификаторы делятся на назначаемые и отклонённые в порядке запроса; назначаемые присоединяются, остальные попадают в failed[] — запрос не отклоняется целиком, пока применён хотя бы один идентификатор. Уже назначенный идентификатор попадает в failed[] с constraint_violation, идентификатор, не являющийся показателем версии, — с resource_not_found.
Ответ
201 Created, если применены все идентификаторы; 207 Multi-Status, если часть отклонена:
{
"timestamp": "2026-05-05T08:30:00.120Z",
"succeeded": [ { "id": "501" } ],
"failed": [
{ "index": 1, "id": "502", "error": { "code": "constraint_violation", "message": "Элемент уже назначен", "details": [] } }
]
}
| Поле | Тип | Описание |
|---|---|---|
succeeded[].id |
string | Применённые идентификаторы |
failed[].index, id |
integer / string | Позиция и значение отклонённого идентификатора |
failed[].error |
object | code, message, details (пустой — элемент уже адресован через index / id) |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.VALIDATION_FAILED |
400 | measure_ids пуст или некорректен |
DF_API.BULK_REJECTED |
422 | Ни один идентификатор не применён; details[] адресует measure_ids.<index> |
2.34 Снять назначение показателя с таблицы фактов
Запрос
DELETE {v}/fact-tables/{fact_table_id}/measures/{measure_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
measure_id |
путь | integer | да | Идентификатор показателя |
Детали
Снимается только назначение; показатель остаётся в РПИ.
Ответ
204 No Content
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.RESOURCE_NOT_FOUND |
404 | Показатель не назначен таблице фактов |
2.35 Назначить измерения таблице фактов
Запрос
POST {v}/fact-tables/{fact_table_id}/dimensions
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
dimension_ids |
тело | array of string | да | Не менее одного идентификатора измерения |
{ "dimension_ids": ["801", "802"] }
Детали
Идентификаторы делятся на назначаемые и отклонённые в порядке запроса; назначаемые присоединяются, остальные попадают в failed[] — запрос не отклоняется целиком, пока применён хотя бы один идентификатор. Уже назначенный идентификатор попадает в failed[] с constraint_violation, идентификатор, не являющийся измерением версии, — с resource_not_found. Измерение, входящее в группу измерений, отклоняется с constraint_violation — оно попадает в таблицу фактов через свою группу.
Ответ
201 Created, если применены все идентификаторы; 207 Multi-Status, если часть отклонена:
{
"timestamp": "2026-05-05T08:30:00.120Z",
"succeeded": [ { "id": "501" } ],
"failed": [
{ "index": 1, "id": "502", "error": { "code": "constraint_violation", "message": "Элемент уже назначен", "details": [] } }
]
}
| Поле | Тип | Описание |
|---|---|---|
succeeded[].id |
string | Применённые идентификаторы |
failed[].index, id |
integer / string | Позиция и значение отклонённого идентификатора |
failed[].error |
object | code, message, details (пустой — элемент уже адресован через index / id) |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.VALIDATION_FAILED |
400 | dimension_ids пуст или некорректен |
DF_API.BULK_REJECTED |
422 | Ни один идентификатор не применён; details[] адресует dimension_ids.<index> |
2.36 Снять назначение измерения с таблицы фактов
Запрос
DELETE {v}/fact-tables/{fact_table_id}/dimensions/{dimension_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
dimension_id |
путь | integer | да | Идентификатор измерения |
Ответ
204 No Content
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.RESOURCE_NOT_FOUND |
404 | Измерение не назначено таблице фактов |
2.37 Назначить факты таблице фактов
Запрос
POST {v}/fact-tables/{fact_table_id}/facts
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
fact_ids |
тело | array of string | да | Не менее одного идентификатора факта |
{ "fact_ids": ["611", "612"] }
Детали
Идентификаторы делятся на назначаемые и отклонённые в порядке запроса; назначаемые присоединяются, остальные попадают в failed[] — запрос не отклоняется целиком, пока применён хотя бы один идентификатор. Уже назначенный идентификатор попадает в failed[] с constraint_violation, идентификатор, не являющийся фактом версии, — с resource_not_found.
Ответ
201 Created, если применены все идентификаторы; 207 Multi-Status, если часть отклонена:
{
"timestamp": "2026-05-05T08:30:00.120Z",
"succeeded": [ { "id": "501" } ],
"failed": [
{ "index": 1, "id": "502", "error": { "code": "constraint_violation", "message": "Элемент уже назначен", "details": [] } }
]
}
| Поле | Тип | Описание |
|---|---|---|
succeeded[].id |
string | Применённые идентификаторы |
failed[].index, id |
integer / string | Позиция и значение отклонённого идентификатора |
failed[].error |
object | code, message, details (пустой — элемент уже адресован через index / id) |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.VALIDATION_FAILED |
400 | fact_ids пуст или некорректен |
DF_API.BULK_REJECTED |
422 | Ни один идентификатор не применён; details[] адресует fact_ids.<index> |
2.38 Снять назначение факта с таблицы фактов
Запрос
DELETE {v}/fact-tables/{fact_table_id}/facts/{fact_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
fact_id |
путь | integer | да | Идентификатор факта |
Ответ
204 No Content
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.RESOURCE_NOT_FOUND |
404 | Факт не назначен таблице фактов |
2.39 Назначить группы измерений таблице фактов
Запрос
POST {v}/fact-tables/{fact_table_id}/dimension-groups
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
dimension_group_ids |
тело | array of string | да | Не менее одного идентификатора группы измерений |
{ "dimension_group_ids": ["9", "10"] }
Детали
Идентификаторы делятся на назначаемые и отклонённые в порядке запроса; назначаемые присоединяются, остальные попадают в failed[] — запрос не отклоняется целиком, пока применён хотя бы один идентификатор. Уже назначенный идентификатор попадает в failed[] с constraint_violation, идентификатор, не являющийся группой измерений версии, — с resource_not_found. Назначение группы делает её измерения доступными таблице фактов (is_from_dimension_group: true в деталях таблицы фактов). Назначение не несёт внешнего ключа, пока для него не создана связь (POST {v}/relationships).
Ответ
201 Created, если применены все идентификаторы; 207 Multi-Status, если часть отклонена:
{
"timestamp": "2026-05-05T08:30:00.120Z",
"succeeded": [ { "id": "501" } ],
"failed": [
{ "index": 1, "id": "502", "error": { "code": "constraint_violation", "message": "Элемент уже назначен", "details": [] } }
]
}
| Поле | Тип | Описание |
|---|---|---|
succeeded[].id |
string | Применённые идентификаторы |
failed[].index, id |
integer / string | Позиция и значение отклонённого идентификатора |
failed[].error |
object | code, message, details (пустой — элемент уже адресован через index / id) |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.VALIDATION_FAILED |
400 | dimension_group_ids пуст или некорректен |
DF_API.BULK_REJECTED |
422 | Ни один идентификатор не применён; details[] адресует dimension_group_ids.<index> |
2.40 Снять назначение группы измерений с таблицы фактов
Запрос
DELETE {v}/fact-tables/{fact_table_id}/dimension-groups/{dimension_group_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
dimension_group_id |
путь | integer | да | Идентификатор группы измерений |
Детали
Группу, соединённую активной связью, снять нельзя — сначала удалите связь (DELETE {v}/relationships/{relationship_id}).
Ответ
204 No Content
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.RESOURCE_NOT_FOUND |
404 | Группа не назначена таблице фактов |
DF_API.CONSTRAINT_VIOLATION |
409 | Группа соединена связью |
2.41 Создать фильтр верификации таблицы фактов
Запрос
POST {v}/fact-tables/{fact_table_id}/verification-filters
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
name |
тело | string | да | 1–64 символа; уникально среди фильтров таблицы фактов |
description |
тело | string | нет | До 255 символов |
conditions |
тело | string | да | Выражение фильтра; ссылки на элементы вида [Имя элемента] |
{ "name": "Valid sales only", "description": "Excludes test and cancelled orders", "conditions": "[Status] != 'cancelled'" }
Детали
Ссылки на элементы в conditions — записанные как [Имя элемента] или как голые имена элементов вне строковых литералов — при записи разрешаются в элементы версии и в ответах отображаются как [Имя]; имя, не совпавшее ни с одним элементом, остаётся как есть, и эндпоинты чтения сообщают о нём через is_valid: false в деталях таблицы фактов.
Ответ
201 Created
{
"id": "301",
"name": "Valid sales only",
"description": "Excludes test and cancelled orders",
"conditions": "[Status] != 'cancelled'",
"created_at": "2026-05-05T08:30:00.000Z",
"updated_at": "2026-05-05T08:30:00.000Z",
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор фильтра |
name, description, conditions |
string / string | null / string | null | Как сохранено |
created_at, updated_at |
string | null | Временные метки фильтра |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.DUPLICATE_NAME |
409 | Фильтр с таким именем уже есть у таблицы фактов |
2.42 Заменить фильтр верификации таблицы фактов
Запрос
PUT {v}/fact-tables/{fact_table_id}/verification-filters/{filter_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
filter_id |
путь | integer | да | Идентификатор фильтра |
name |
тело | string | да | 1–64 символа; уникально среди фильтров таблицы фактов |
description |
тело | string | нет | До 255 символов |
conditions |
тело | string | да | Выражение фильтра; ссылки на элементы вида [Имя элемента] |
Детали
name и conditions обязательны; непереданный description сбрасывается в null. Ссылки на элементы в conditions разрешаются и отображаются как [Имя].
Ответ
200 OK
{
"id": "301",
"name": "Valid sales only",
"description": "Excludes test and cancelled orders",
"conditions": "[Status] != 'cancelled'",
"created_at": "2026-05-05T08:30:00.000Z",
"updated_at": "2026-05-05T08:30:00.000Z",
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор фильтра |
name, description, conditions |
string / string | null / string | null | Как сохранено |
created_at, updated_at |
string | null | Временные метки фильтра |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.RESOURCE_NOT_FOUND |
404 | Фильтр не принадлежит таблице фактов |
DF_API.MISSING_REQUIRED_FIELD |
400 | Отсутствует name или conditions |
DF_API.DUPLICATE_NAME |
409 | Новое имя занято другим фильтром таблицы фактов |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
2.43 Обновить фильтр верификации таблицы фактов
Запрос
PATCH {v}/fact-tables/{fact_table_id}/verification-filters/{filter_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
filter_id |
путь | integer | да | Идентификатор фильтра |
name |
тело | string | нет | 1–64 символа; уникально среди фильтров таблицы фактов |
description |
тело | string | нет | До 255 символов |
conditions |
тело | string | нет | Выражение фильтра; ссылки на элементы вида [Имя элемента] |
Детали
Изменяются только переданные поля.
Ответ
200 OK
{
"id": "301",
"name": "Valid sales only",
"description": "Excludes test and cancelled orders",
"conditions": "[Status] != 'cancelled'",
"created_at": "2026-05-05T08:30:00.000Z",
"updated_at": "2026-05-05T08:30:00.000Z",
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор фильтра |
name, description, conditions |
string / string | null / string | null | Как сохранено |
created_at, updated_at |
string | null | Временные метки фильтра |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | Таблица фактов не существует в версии |
DF_API.RESOURCE_NOT_FOUND |
404 | Фильтр не принадлежит таблице фактов |
DF_API.DUPLICATE_NAME |
409 | Новое имя занято другим фильтром таблицы фактов |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
2.44 Удалить фильтр верификации таблицы фактов
Запрос
DELETE {v}/fact-tables/{fact_table_id}/verification-filters/{filter_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
fact_table_id |
путь | integer | да | Идентификатор таблицы фактов |
filter_id |
путь | integer | да | Идентификатор фильтра |
Ответ
204 No Content
Ошибки. 404 DF_API.FACT_TABLE_NOT_FOUND, 404 DF_API.RESOURCE_NOT_FOUND.
2.45 Создать фильтр верификации уровня версии
Запрос
POST {v}/verification-filters
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
name |
тело | string | да | 1–64 символа; уникально среди глобальных фильтров версии |
description |
тело | string | нет | До 255 символов |
conditions |
тело | string | да | Выражение фильтра |
Детали
Фильтр уровня версии («глобальный») не привязан ни к одной таблице фактов и применяется к глобальным показателям. Ссылки на элементы в conditions — записанные как [Имя элемента] или как голые имена элементов вне строковых литералов — при записи разрешаются в элементы версии и в ответах отображаются как [Имя]; имя, не совпавшее ни с одним элементом, остаётся как есть, и эндпоинты чтения сообщают о нём через is_valid: false в деталях таблицы фактов.
Ответ
201 Created
{
"id": "301",
"name": "Valid sales only",
"description": "Excludes test and cancelled orders",
"conditions": "[Status] != 'cancelled'",
"created_at": "2026-05-05T08:30:00.000Z",
"updated_at": "2026-05-05T08:30:00.000Z",
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор фильтра |
name, description, conditions |
string / string | null / string | null | Как сохранено |
created_at, updated_at |
string | null | Временные метки фильтра |
timestamp |
string | Момент операции |
Ошибки. 409 DF_API.DUPLICATE_NAME.
2.46 Заменить фильтр верификации уровня версии
Запрос
PUT {v}/verification-filters/{filter_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
filter_id |
путь | integer | да | Идентификатор фильтра |
name |
тело | string | да | 1–64 символа; уникально среди глобальных фильтров версии |
description |
тело | string | нет | До 255 символов |
conditions |
тело | string | да | Выражение фильтра |
Детали
name и conditions обязательны; непереданный description сбрасывается в null.
Ответ
200 OK
{
"id": "301",
"name": "Valid sales only",
"description": "Excludes test and cancelled orders",
"conditions": "[Status] != 'cancelled'",
"created_at": "2026-05-05T08:30:00.000Z",
"updated_at": "2026-05-05T08:30:00.000Z",
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор фильтра |
name, description, conditions |
string / string | null / string | null | Как сохранено |
created_at, updated_at |
string | null | Временные метки фильтра |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Фильтр не существует в версии |
DF_API.MISSING_REQUIRED_FIELD |
400 | Отсутствует name или conditions |
DF_API.DUPLICATE_NAME |
409 | Новое имя занято другим глобальным фильтром версии |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
2.47 Обновить фильтр верификации уровня версии
Запрос
PATCH {v}/verification-filters/{filter_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
filter_id |
путь | integer | да | Идентификатор фильтра |
name |
тело | string | нет | 1–64 символа; уникально среди глобальных фильтров версии |
description |
тело | string | нет | До 255 символов |
conditions |
тело | string | нет | Выражение фильтра |
Детали
Изменяются только переданные поля.
Ответ
200 OK
{
"id": "301",
"name": "Valid sales only",
"description": "Excludes test and cancelled orders",
"conditions": "[Status] != 'cancelled'",
"created_at": "2026-05-05T08:30:00.000Z",
"updated_at": "2026-05-05T08:30:00.000Z",
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор фильтра |
name, description, conditions |
string / string | null / string | null | Как сохранено |
created_at, updated_at |
string | null | Временные метки фильтра |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Фильтр не существует в версии |
DF_API.DUPLICATE_NAME |
409 | Новое имя занято другим глобальным фильтром версии |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
2.48 Удалить фильтр верификации уровня версии
Запрос
DELETE {v}/verification-filters/{filter_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
filter_id |
путь | integer | да | Идентификатор фильтра |
Ответ
204 No Content
Ошибки. 404 DF_API.RESOURCE_NOT_FOUND.
2.49 Создать связь
Запрос
POST {v}/relationships
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
source_fact_table_id |
тело | string | да | Таблица фактов с внешним ключом |
target_dimension_group_id |
тело | string | да | Группа измерений с первичным ключом |
foreign_key |
тело | object | да | Объект источника на стороне таблицы фактов (раздел 3.6 страницы API) |
primary_key |
тело | object | да | Объект источника на стороне группы измерений; становится первичным ключом группы |
relationship_type |
тело | string | да | Должно быть many_to_one |
{
"source_fact_table_id": "11",
"target_dimension_group_id": "9",
"foreign_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "fact_sales", "column": "region_id" },
"primary_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_geography", "column": "region_id" },
"relationship_type": "many_to_one"
}
Детали
Если группа ещё не назначена таблице фактов, назначение создаётся вместе со связью. Оба ключа проверяются (раздел 1): при переданном connection каждый ключ должен называть подключение, которое уже использует его сторона, и оба ключа должны называть одно подключение.
Ответ
201 Created
{
"id": "1101",
"source_fact_table": { "id": "11", "name": "fact_sales", "description": "Primary sales facts" },
"target_dimension_group": {
"id": "9", "name": "Geography", "description": "Geographic regions and countries",
"primary_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_geography", "column": "region_id" }
},
"foreign_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "fact_sales", "column": "region_id" },
"primary_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_geography", "column": "region_id" },
"relationship_type": "many_to_one",
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор связи |
source_fact_table, target_dimension_group |
object | Обе стороны с description; сторона группы повторяет свой primary_key |
foreign_key, primary_key |
object | null | Объекты источника с connection; null, если маппинг неполный |
relationship_type |
string | Слаг many_to_one (единственная кратность, поддерживаемая моделью) |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.FACT_TABLE_NOT_FOUND |
404 | source_fact_table_id не существует в версии |
DF_API.RESOURCE_NOT_FOUND |
404 | target_dimension_group_id не существует в версии |
DF_API.INVALID_RELATIONSHIP_TYPE |
400 | relationship_type отличается от many_to_one |
DF_API.DUPLICATE_RELATIONSHIP |
409 | Связь между этой таблицей фактов и группой уже существует |
DF_API.INVALID_SOURCE_*, DF_API.CONNECTION_MISMATCH |
400 | Проверка ключей (раздел 1) |
2.50 Заменить связь
Запрос
PUT {v}/relationships/{relationship_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
relationship_id |
путь | integer | да | Идентификатор связи |
foreign_key |
тело | object | да | Новый внешний ключ |
primary_key |
тело | object | да | Новый первичный ключ группы |
Детали
Изменить можно только координаты ключей; таблица фактов и группа фиксированы. Оба ключа проверяются до записи любого из них.
Ответ
200 OK
{
"id": "1101",
"source_fact_table": { "id": "11", "name": "fact_sales", "description": "Primary sales facts" },
"target_dimension_group": {
"id": "9", "name": "Geography", "description": "Geographic regions and countries",
"primary_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_geography", "column": "region_id" }
},
"foreign_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "fact_sales", "column": "region_id" },
"primary_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_geography", "column": "region_id" },
"relationship_type": "many_to_one",
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор связи |
source_fact_table, target_dimension_group |
object | Обе стороны с description; сторона группы повторяет свой primary_key |
foreign_key, primary_key |
object | null | Объекты источника с connection; null, если маппинг неполный |
relationship_type |
string | Слаг many_to_one (единственная кратность, поддерживаемая моделью) |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RELATIONSHIP_NOT_FOUND |
404 | Связь не существует в версии |
DF_API.MISSING_REQUIRED_FIELD |
400 | Отсутствует foreign_key или primary_key |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
DF_API.INVALID_SOURCE_*, DF_API.CONNECTION_MISMATCH |
400 | Проверка ключей |
2.51 Обновить связь
Запрос
PATCH {v}/relationships/{relationship_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
relationship_id |
путь | integer | да | Идентификатор связи |
foreign_key |
тело | object | нет | Новый внешний ключ |
primary_key |
тело | object | нет | Новый первичный ключ группы |
Детали
Непереданный ключ сохраняет своё значение и используется для проверки единства подключения с переданным.
Ответ
200 OK
{
"id": "1101",
"source_fact_table": { "id": "11", "name": "fact_sales", "description": "Primary sales facts" },
"target_dimension_group": {
"id": "9", "name": "Geography", "description": "Geographic regions and countries",
"primary_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_geography", "column": "region_id" }
},
"foreign_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "fact_sales", "column": "region_id" },
"primary_key": { "connection": "Production PostgreSQL", "db": "analytics_db", "schema": "public", "table": "dim_geography", "column": "region_id" },
"relationship_type": "many_to_one",
"timestamp": "2026-05-05T08:30:00.120Z"
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор связи |
source_fact_table, target_dimension_group |
object | Обе стороны с description; сторона группы повторяет свой primary_key |
foreign_key, primary_key |
object | null | Объекты источника с connection; null, если маппинг неполный |
relationship_type |
string | Слаг many_to_one (единственная кратность, поддерживаемая моделью) |
timestamp |
string | Момент операции |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RELATIONSHIP_NOT_FOUND |
404 | Связь не существует в версии |
DF_API.ID_MISMATCH |
400 | id в теле отличается от пути |
DF_API.INVALID_SOURCE_*, DF_API.CONNECTION_MISMATCH |
400 | Проверка ключей |
2.52 Удалить связь
Запрос
DELETE {v}/relationships/{relationship_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
relationship_id |
путь | integer | да | Идентификатор связи |
Детали
Удаление связи очищает только внешний ключ; группа измерений остаётся назначенной таблице фактов (снять назначение — DELETE {v}/fact-tables/{fact_table_id}/dimension-groups/{dimension_group_id}).
Ответ
204 No Content
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RELATIONSHIP_NOT_FOUND |
404 | Связь не существует в версии |
3 Управление доступом к проектам
Эти эндпоинты управляют интерактивным доступом к проекту, который затем наследуют API-ключи (раздел 2.2 страницы API). В отличие от эндпоинтов записи РПИ и модели данных (разделы 1–2, требующих эффективной роли в проекте «разработчик или выше»), эндпоинты управления доступом требуют, чтобы вызывающий (владелец API-ключа) был владельцем проекта или администратором компании/суперадминистратором; иначе запрос отклоняется с 403 DF_API.WRITE_ACCESS_DENIED. Идентификаторы в пути — projectId и userId (camelCase, как во внутреннем API).
| Метод | Путь | Раздел |
|---|---|---|
GET |
/projects/{projectId}/access |
3.1 |
POST |
/projects/{projectId}/access |
3.2 |
DELETE |
/projects/{projectId}/access/{userId} |
3.3 |
PUT |
/projects/{projectId}/owner |
3.4 |
Внутренние ключи этих проверок (PROJECT.INVALID_ACCESS_LEVEL, PROJECT.ACCESS_LEVEL_NOT_ASSIGNABLE, PROJECT.CANNOT_ELEVATE_ACCESS, PROJECT.INVALID_OWNER, PROJECT.ACCESS_DENIED, USER.NOT_FOUND) наружу не выходят: как и любой ключ вне каталога DF_API.*, они приводятся к общему коду по HTTP-статусу (раздел 4 страницы Публичный API v2); локализованная причина остаётся в message.
3.1 Получить конфигурацию доступа
Запрос
GET /df-api/v2/projects/{projectId}/access
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
projectId |
путь | integer | да | Идентификатор проекта |
language |
query | ru | en |
нет | Язык подписей ролей |
Детали
Возвращает владельца проекта вместе с каждым пользователем, имеющим явный доступ. Подписи ролей локализуются так же, как в таблице «Пользователи проекта» в приложении. Внутренние поля isAdmin и ownerStatus не раскрываются. Ответ — просто массив (без пагинации).
Ответ
200 OK
[
{
"id": 7,
"first_name": "Pavel",
"last_name": "Shalavin",
"email": "pavel@example.com",
"isOwner": true,
"globalRole": "Администратор",
"projectRole": "Разработчик"
}
]
| Поле | Тип | Описание |
|---|---|---|
id |
integer | Идентификатор пользователя |
first_name, last_name, email |
string | Идентификация пользователя |
isOwner |
boolean | true для владельца проекта |
globalRole |
string | null | Локализованная подпись глобальной роли или null, если не определяется |
projectRole |
string | null | Локализованная подпись роли в проекте или null, если явная роль в проекте отсутствует |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.WRITE_ACCESS_DENIED |
403 | Вызывающий не является владельцем или администратором |
DF_API.PROJECT_NOT_FOUND |
404 | Проект не существует или не виден |
3.2 Добавить или обновить доступ
Запрос
POST /df-api/v2/projects/{projectId}/access
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
projectId |
путь | integer | да | Идентификатор проекта |
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
userId |
тело | integer | да | Целевой пользователь; должен существовать и принадлежать компании проекта |
accessLevel |
тело | string | да | developer, analyst или viewer (project_manager наследуется владельцем и не назначается) |
{ "userId": 12, "accessLevel": "developer" }
Детали
Если у пользователя уже есть доступ, уровень обновляется; иначе доступ предоставляется. Назначение подчиняется правилу «только понижение» — уровень доступа выше глобальной роли пользователя отклоняется.
Ответ
201 Created
{ "success": true }
| Поле | Тип | Описание |
|---|---|---|
success |
boolean | При успехе всегда true |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.INVALID_PARAMETER |
400 | accessLevel отсутствует или не равен developer / analyst / viewer; запрошенный уровень превышает глобальную роль целевого пользователя |
DF_API.RESOURCE_NOT_FOUND |
404 | Целевой пользователь не существует или вне компании проекта |
DF_API.WRITE_ACCESS_DENIED |
403 | Вызывающий не является владельцем или администратором |
3.3 Удалить доступ
Запрос
DELETE /df-api/v2/projects/{projectId}/access/{userId}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
projectId, userId |
путь | integer | да | Идентификаторы |
Детали
Удаляет явный доступ целевого пользователя. Пользователь должен существовать.
Ответ
200 OK
{ "success": true }
| Поле | Тип | Описание |
|---|---|---|
success |
boolean | При успехе всегда true |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Целевой пользователь не существует |
DF_API.WRITE_ACCESS_DENIED |
403 | Вызывающий не является владельцем или администратором |
3.4 Передать владение
Запрос
PUT /df-api/v2/projects/{projectId}/owner
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
projectId |
путь | integer | да | Идентификатор проекта |
newOwnerId |
тело | integer | да | Новый владелец; должен существовать, принадлежать компании проекта и иметь роль, допустимую для владения (PROJECT_MANAGER, COMPANY_ADMIN или SUPER_ADMIN) |
{ "newOwnerId": 12 }
Ответ
200 OK
{ "success": true }
| Поле | Тип | Описание |
|---|---|---|
success |
boolean | При успехе всегда true |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.RESOURCE_NOT_FOUND |
404 | Новый владелец не существует или вне компании проекта |
DF_API.INVALID_PARAMETER |
400 | Роль нового владельца не допускает владения |
DF_API.WRITE_ACCESS_DENIED |
403 | Вызывающий не является владельцем или администратором |
4 Перенос версий: экспорт и импорт (df-api/v2)
Движок экспорта/импорта версий проекта доступен через публичный API — это позволяет CI/CD-конвейеру выгружать конфигурацию в Git и разворачивать её между средами без участия браузера.
| Метод | Путь | Роль | Раздел |
|---|---|---|---|
POST |
{v}/export/git |
Аналитик или выше | 4.1 |
POST |
{v}/export/file |
Аналитик или выше | 4.2 |
POST |
{v}/import/validate |
Аналитик или выше | 4.3 |
POST |
{v}/import/preview |
Аналитик или выше | 4.4 |
POST |
{v}/import/git |
Разработчик или выше | 4.5 |
POST |
{v}/import/file |
Разработчик или выше | 4.6 |
Роль — эффективная роль владельца ключа в проекте (раздел 2.2 страницы API); недостаточная роль отвечает 403 DF_API.WRITE_ACCESS_DENIED. Экспорт и сухие прогоны требуют роли «аналитик или выше» (строже внутреннего API, где экспорт доступен и наблюдателю), импорт — «разработчик или выше». Все шесть эндпоинтов при успехе отвечают 200 OK.
Учётные данные Git передаются либо в объекте authentication в открытом виде поверх TLS (CI-клиент не может собрать браузерный шифрованный конверт), либо ссылкой connection_id на сохранённое Git-подключение (раздел 5):
| Поле | Метод | Описание |
|---|---|---|
authentication.method |
— | pat, ssh или password |
authentication.token |
pat |
Personal Access Token |
authentication.private_key, authentication.passphrase |
ssh |
Приватный SSH-ключ и его парольная фраза (опционально) |
authentication.username, authentication.password |
password |
Логин и пароль |
Целевой репозиторий всегда задаётся полем repository_url запроса (внутренний хост отклоняется); сохранённое подключение отдаёт только учётные данные, и они принимаются только для хоста самого подключения. Подключение с выключенными allow_branch_override / allow_path_override отклоняет запрос, ветка или путь которого отличаются от сохранённых. Отсутствующий path в запросе через подключение означает сохранённый путь. Учётные данные, вписанные в repository_url, вычищаются из ответа, аудита и сохранённого подключения.
Ограничение облачной установки. Multipart-эндпоинты (import/file, файловая ветка import/validate / import/preview) работают только в on-premises-установке; в облаке AWS Lambda-обвязка не передаёт бинарные тела, а синхронные clone/push крупных репозиториев могут не укладываться в лимит 29 секунд шлюза.
Общие ошибки группы, помимо общих ошибок раздела 4 страницы API: 422 DF_API.GIT_CONNECTION_FAILED (репозиторий недостижим, учётные данные отклонены, небезопасный транспорт), 400 DF_API.INVALID_PARAMETER (неизвестная ветка или коммит, повреждённый архив, отсутствие или несколько корней проекта в дереве), 422 DF_API.UNPROCESSABLE_ENTITY (превышены лимиты размера или числа файлов, некорректный источник импорта), 404 DF_API.CONNECTION_NOT_FOUND (connection_id не называет видимое Git-подключение).
4.1 Экспорт в Git
Запрос
POST {v}/export/git
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Повторный ключ возвращает исходный ответ |
repository_url |
тело | string | да | URL целевого репозитория (до 2000 символов, без пробелов) |
branch |
тело | string | да | Целевая ветка (создаётся, если отсутствует) |
path |
тело | string | нет | Путь внутри репозитория; / или не передан — корень |
commit_message |
тело | string | да | 1–500 символов |
connection_id |
тело | string | одно из | Сохранённое Git-подключение, предоставляющее учётные данные |
authentication |
тело | object | одно из | Учётные данные (таблица выше) |
options.include_rmd, include_fact_tables, include_data_marts, include_connections |
тело | boolean | нет | Какие разделы попадают в выгрузку. По умолчанию true |
options.include_history |
тело | boolean | нет | Включить историю изменений ячеек РПИ. По умолчанию false |
options.encrypt_sensitive |
тело | boolean | нет | По умолчанию true; единственное отклоняемое значение — false: пароли подключений в открытом виде не выгружаются никогда (400) |
options.add_gitattributes |
тело | boolean | нет | Положить в дерево .gitattributes. По умолчанию true |
options.save_connection, options.connection_name |
тело | boolean, string | нет | Сохранить переданные в authentication учётные данные как новое личное подключение с указанным именем (видно создателю и администраторам; расшаривание — решение администратора) |
{
"repository_url": "https://gitlab.example.com/analytics/dataforge-config.git",
"branch": "main",
"path": "/sales",
"commit_message": "Export from DataForge, pipeline 4711",
"authentication": { "method": "pat", "token": "<personal-access-token>" },
"options": { "include_history": false }
}
Детали
Экспорт детерминирован: повторный экспорт неизменённой версии даёт байт-в-байт то же дерево, поэтому повторный экспорт не создаёт коммит и отвечает commit_hash: null (ветка никогда не перезаписывается — изменения ложатся обычными коммитами поверх её истории). Цепочка «экспорт → импорт новой версией → повторный экспорт» воспроизводит дерево без единого отличия.
Ответ
200 OK
{
"success": true,
"commit_hash": "3f2a9c1e7b0d4a6f8c2e1b9d7a5c3e1f0b8d6a4c",
"repository_url": "https://gitlab.example.com/analytics/dataforge-config.git",
"branch": "main",
"path": "/sales",
"files_created": 128,
"timestamp": "2026-05-05T08:30:00.120Z",
"connection_id": null
}
| Поле | Тип | Описание |
|---|---|---|
success |
boolean | При 200 всегда true |
commit_hash |
string | null | Хеш созданного коммита; null, если дерево не изменилось |
repository_url, branch, path |
string | Куда легло дерево; учётные данные из URL вычищены |
files_created |
integer | Количество файлов, записанных в дерево |
timestamp |
string | Момент операции |
connection_id |
string | null | Сохранённое подключение, которое использовалось или было создано (options.save_connection) |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.MISSING_REQUIRED_FIELD |
400 | Не передан ни connection_id, ни authentication; при save_connection отсутствует connection_name |
DF_API.INVALID_PARAMETER |
400 | encrypt_sensitive: false; подключение запретило переопределение ветки или пути; неизвестная ветка |
DF_API.GIT_PUSH_FAILED |
422 | Push отклонён: ветка изменилась во время экспорта или защищена |
| Общие ошибки группы | — | Выше |
4.2 Экспорт в файл
Запрос
POST {v}/export/file
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
options.include_rmd, include_fact_tables, include_data_marts, include_connections |
тело | boolean | нет | Какие разделы попадают в выгрузку. По умолчанию true |
options.include_history |
тело | boolean | нет | Включить историю изменений ячеек РПИ. По умолчанию false |
options.encrypt_sensitive |
тело | boolean | нет | По умолчанию true; единственное отклоняемое значение — false: пароли подключений в открытом виде не выгружаются никогда (400) |
options.encryption_password |
тело | string | нет | Обернуть архив в конверт AES-256-GCM с этим паролем |
options.use_system_key |
тело | boolean | нет | Обернуть архив системным ключом (при передаче обоих пароль имеет приоритет). По умолчанию false |
{ "options": { "include_connections": true, "encryption_password": "<password>" } }
Детали
Формирует архив .dfexport.zip в объектном хранилище и возвращает подписанную ссылку; срок её жизни задаётся установкой и сообщается в expires_at. Idempotency-Key намеренно не учитывается — закешированный ответ содержал бы протухшую ссылку.
Ответ
200 OK
{
"download_url": "https://storage.example.com/exports/…?signature=…",
"file_name": "Sales Analytics_Q4 2025.dfexport.zip",
"file_size": 48213,
"expires_at": "2026-05-05T09:30:00.000Z"
}
| Поле | Тип | Описание |
|---|---|---|
download_url |
string | Подписанная ссылка на архив |
file_name |
string | Рекомендуемое имя файла |
file_size |
integer | Размер в байтах |
expires_at |
string | Момент, когда ссылка перестаёт работать, ISO 8601 |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.INVALID_PARAMETER |
400 | encrypt_sensitive: false |
DF_API.UNPROCESSABLE_ENTITY |
422 | Экспорт превышает лимит размера |
4.3 Проверить источник импорта
Запрос
POST {v}/import/validate — JSON для git-источника, multipart/form-data для файла.
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
source_type |
тело | git | file |
да | Что несёт запрос |
repository_url, branch |
тело | string | git |
Репозиторий и ветка источника |
path, commit_hash |
тело | string | нет | Путь внутри репозитория; коммит (7–40 hex-символов), который закрепляется вместо вершины ветки |
connection_id / authentication |
тело | — | git |
Учётные данные (одно из двух) |
file |
multipart-часть | binary | file |
Архив .dfexport.zip, обычный или запечатанный |
encryption_password |
тело | string | нет | Пароль запечатанного архива |
conflict_strategy, options |
тело | — | нет | Принимаются с тем же смыслом, что в запросе импорта (smart_merge / overwrite / skip / manual; опции import_*, detect_merges, decrypt_sensitive, encryption_password), чтобы документированное тело импорта можно было отправить как есть; сухой прогон на них не реагирует. В multipart options — JSON-строка |
Детали
Проверяет источник, ничего не записывая. Версия из пути служит только точкой доступа. Idempotency-Key не учитывается (закешированный вердикт мог бы устареть).
Ответ
200 OK
{
"valid": false,
"errors": [
{ "level": "error", "code": "DUPLICATE_ID", "message": "Дублирующийся идентификатор элемента", "element": "measures/total_revenue.json", "element_type": "measure" }
],
"warnings": [
{ "level": "warning", "code": "REFERENCE_MISSING", "message": "Таблица фактов, на которую есть ссылка, отсутствует в выгрузке", "element": "data_marts/monthly.json", "element_type": "data_mart" }
],
"summary": { "measures": 42, "dimensions": 18, "facts": 6, "fact_tables": 3, "data_marts": 2 },
"schema_version": "1.0"
}
| Поле | Тип | Описание |
|---|---|---|
valid |
boolean | false, если errors[] непуст |
errors[], warnings[] |
array | Замечания с level, машинным code (REQUIRED_FILE_MISSING, DUPLICATE_ID, CIRCULAR_DEPENDENCY, REFERENCE_MISSING, …), message, element, element_type |
summary |
object | Счётчики элементов источника: measures, dimensions, facts, fact_tables, data_marts |
schema_version |
string | Версия формата выгрузки, найденная в источнике |
Ошибки. 400 DF_API.MISSING_REQUIRED_FIELD (отсутствует поле, обязательное для данного source_type); общие ошибки группы.
4.4 Предпросмотр импорта
Запрос
POST {v}/import/preview — JSON для git-источника, multipart/form-data для файла.
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
source_type |
тело | git | file |
нет | Что несёт запрос. Можно опустить — тогда определяется по самому запросу: multipart-загрузка — файл, всё остальное — ветка Git |
repository_url, branch |
тело | string | git |
Репозиторий и ветка источника |
path, commit_hash |
тело | string | нет | Путь внутри репозитория; коммит (7–40 hex-символов), который закрепляется вместо вершины ветки |
connection_id / authentication |
тело | — | git |
Учётные данные (одно из двух) |
file |
multipart-часть | binary | file |
Архив .dfexport.zip, обычный или запечатанный |
encryption_password |
тело | string | нет | Пароль запечатанного архива |
conflict_strategy, options |
тело | — | нет | Принимаются с тем же смыслом, что в запросе импорта (smart_merge / overwrite / skip / manual; опции import_*, detect_merges, decrypt_sensitive, encryption_password), чтобы документированное тело импорта можно было отправить как есть; сухой прогон на них не реагирует. В multipart options — JSON-строка |
Детали
Сравнивает источник с версией из пути и сообщает, что изменил бы импорт, ничего не записывая. Idempotency-Key не учитывается.
Ответ
200 OK
{
"preview_id": "0b1d2c3e-4f5a-6789-abcd-ef0123456789",
"summary": {
"measures": { "added": 3, "modified": 5, "deleted": 0, "total": 45 },
"dimensions": { "added": 0, "modified": 1, "deleted": 0, "total": 18 },
"facts": { "added": 0, "modified": 0, "deleted": 0, "total": 6 },
"fact_tables": { "added": 0, "modified": 1, "deleted": 0, "total": 3 },
"data_marts": { "added": 1, "modified": 0, "deleted": 0, "total": 3 }
},
"conflicts": [
{ "element_type": "measure", "element_id": "1000", "element_name": "Total revenue", "field": "formula", "current_value": "SUM([Amount])", "imported_value": "SUM([Net amount])" }
],
"conflict_resolution_required": true
}
| Поле | Тип | Описание |
|---|---|---|
preview_id |
string | Идентификатор этого предпросмотра |
summary.<раздел> |
object | added, modified, deleted, total по разделу |
conflicts[] |
array | Конфликты по полям: element_type, element_id, element_name, field, current_value, imported_value |
conflict_resolution_required |
boolean | true, если conflicts[] непуст |
Ошибки. 400 DF_API.MISSING_REQUIRED_FIELD (отсутствует поле, обязательное для данного source_type); общие ошибки группы.
4.5 Импорт из Git
Запрос
POST {v}/import/git
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Повтор запроса CI-раннером попадает в ту же версию с тем же import_id |
repository_url, branch |
тело | string | да | Репозиторий и ветка источника |
path |
тело | string | нет | Путь внутри репозитория |
commit_hash |
тело | string | нет | Закрепить конкретный коммит вместо вершины ветки |
connection_id / authentication |
тело | — | одно из | Учётные данные |
target.method |
тело | create | replace |
нет | create (по умолчанию) — новая версия (учитывается лимит версий лицензии); replace — полная замена версии, указанной в пути |
target.version_name |
тело | string | да | Имя результирующей версии в обоих режимах (имя новой версии либо новое имя заменяемой); до 64 символов, буквы/цифры/подчёркивание/пробел/точка/дефис |
conflict_strategy |
тело | string | нет | smart_merge (по умолчанию), overwrite, skip, manual |
options.import_rmd, import_fact_tables, import_data_marts, import_connections |
тело | boolean | нет | По умолчанию true; выключенный раздел остаётся как в текущей версии |
options.import_history |
тело | boolean | нет | Импортировать историю ячеек РПИ. По умолчанию false |
options.detect_merges |
тело | boolean | нет | Переносить merge-происхождение из манифеста. По умолчанию true |
options.decrypt_sensitive |
тело | boolean | нет | По умолчанию true; при false подключения импортируются без паролей со статусом «требует обновления» |
options.encryption_password |
тело | string | нет | Пароль запечатанного источника |
{
"repository_url": "https://gitlab.example.com/analytics/dataforge-config.git",
"branch": "main",
"path": "/sales",
"target": { "method": "create", "version_name": "staging_4711" },
"conflict_strategy": "smart_merge",
"authentication": { "method": "pat", "token": "<personal-access-token>" }
}
Детали
Версия из пути в обоих режимах служит базой сравнения для стратегии разрешения конфликтов. conflict_strategy действует поэлементно:
| Стратегия | Поведение |
|---|---|
smart_merge (по умолчанию) |
Добавления и изменения из источника применяются; элементы, существующие только в текущей версии, сохраняются |
overwrite |
Источник применяется дословно, включая удаления |
skip |
Конфликтующие элементы сохраняют текущие значения; добавления применяются, удаления — нет |
manual |
При наличии конфликтов ничего не записывается: ответ success: false со списком конфликтов |
Импорт выполняется одной транзакцией и создаёт результирующую версию с сохранением uuid элементов, поэтому повторные экспорты остаются сравнимыми в Git. Каждый импорт фиксируется в аудите со снимками before/after (раздел 7 страницы API).
Ответ
200 OK
{
"success": true,
"import_id": "7c0e4b2a-1d3f-4e5a-9b8c-6d7e8f9a0b1c",
"target_project_id": "12",
"target_version_id": "35",
"target_version_name": "staging_4711",
"summary": {
"measures": { "added": 3, "modified": 5, "deleted": 0, "total": 45 },
"dimensions": { "added": 0, "modified": 1, "deleted": 0, "total": 18 },
"facts": { "added": 0, "modified": 0, "deleted": 0, "total": 6 },
"fact_tables": { "added": 0, "modified": 1, "deleted": 0, "total": 3 },
"data_marts": { "added": 1, "modified": 0, "deleted": 0, "total": 3 }
},
"conflicts": [],
"conflict_resolution_required": false
}
| Поле | Тип | Описание |
|---|---|---|
success |
boolean | false только при стратегии manual и наличии конфликтов — ничего не записано |
import_id |
string | Идентификатор операции импорта; стабилен при идемпотентном повторе |
target_project_id, target_version_id, target_version_name |
string / string / string | null | Куда лёг импорт (идентификаторы — строками) |
summary.<раздел> |
object | added, modified, deleted, total по разделу |
conflicts[] |
array | Конфликты по полям: element_type, element_id, element_name, field, current_value, imported_value |
conflict_resolution_required |
boolean | true, если conflicts[] непуст |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.MISSING_REQUIRED_FIELD |
400 | Отсутствует target.version_name; не передан ни connection_id, ни authentication |
DF_API.DUPLICATE_NAME |
409 | target.version_name уже занято другой живой версией проекта |
DF_API.LICENSE_LIMIT_REACHED |
403 | target.method: create при достигнутом лимите версий лицензии |
DF_API.UNPROCESSABLE_ENTITY |
422 | Источник не прошёл проверку (errors[], которые сообщает эндпоинт проверки) или превышает лимиты |
| Общие ошибки группы | — | Выше |
4.6 Импорт из файла
Запрос
POST {v}/import/file — multipart/form-data.
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Повтор запроса CI-раннером попадает в ту же версию с тем же import_id |
file |
multipart-часть | binary | да | Архив .dfexport.zip, обычный или запечатанный |
target.method |
поле формы | create | replace |
нет | create (по умолчанию) — новая версия (учитывается лимит версий лицензии); replace — полная замена версии, указанной в пути |
target.version_name |
поле формы | string | да | Имя результирующей версии в обоих режимах (имя новой версии либо новое имя заменяемой); до 64 символов, буквы/цифры/подчёркивание/пробел/точка/дефис |
conflict_strategy |
поле формы | string | нет | smart_merge (по умолчанию), overwrite, skip, manual |
options |
поле формы | JSON-строка | нет | JSON-строка с опциями импорта: import_rmd, import_fact_tables, import_data_marts, import_connections (по умолчанию true; выключенный раздел остаётся как в текущей версии), import_history (false), detect_merges (true), decrypt_sensitive (true; при false подключения импортируются без паролей), encryption_password |
encryption_password |
поле формы | string | нет | Пароль запечатанного архива |
Детали
Только для on-premises-установок (ограничение облака выше).
Версия из пути в обоих режимах служит базой сравнения для стратегии разрешения конфликтов. conflict_strategy действует поэлементно:
| Стратегия | Поведение |
|---|---|
smart_merge (по умолчанию) |
Добавления и изменения из источника применяются; элементы, существующие только в текущей версии, сохраняются |
overwrite |
Источник применяется дословно, включая удаления |
skip |
Конфликтующие элементы сохраняют текущие значения; добавления применяются, удаления — нет |
manual |
При наличии конфликтов ничего не записывается: ответ success: false со списком конфликтов |
Импорт выполняется одной транзакцией и создаёт результирующую версию с сохранением uuid элементов, поэтому повторные экспорты остаются сравнимыми в Git. Каждый импорт фиксируется в аудите со снимками before/after (раздел 7 страницы API).
Ответ
200 OK
{
"success": true,
"import_id": "7c0e4b2a-1d3f-4e5a-9b8c-6d7e8f9a0b1c",
"target_project_id": "12",
"target_version_id": "35",
"target_version_name": "staging_4711",
"summary": {
"measures": { "added": 3, "modified": 5, "deleted": 0, "total": 45 },
"dimensions": { "added": 0, "modified": 1, "deleted": 0, "total": 18 },
"facts": { "added": 0, "modified": 0, "deleted": 0, "total": 6 },
"fact_tables": { "added": 0, "modified": 1, "deleted": 0, "total": 3 },
"data_marts": { "added": 1, "modified": 0, "deleted": 0, "total": 3 }
},
"conflicts": [],
"conflict_resolution_required": false
}
| Поле | Тип | Описание |
|---|---|---|
success |
boolean | false только при стратегии manual и наличии конфликтов — ничего не записано |
import_id |
string | Идентификатор операции импорта; стабилен при идемпотентном повторе |
target_project_id, target_version_id, target_version_name |
string / string / string | null | Куда лёг импорт (идентификаторы — строками) |
summary.<раздел> |
object | added, modified, deleted, total по разделу |
conflicts[] |
array | Конфликты по полям: element_type, element_id, element_name, field, current_value, imported_value |
conflict_resolution_required |
boolean | true, если conflicts[] непуст |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.MISSING_REQUIRED_FIELD |
400 | Отсутствует target.version_name; не передан ни connection_id, ни authentication |
DF_API.DUPLICATE_NAME |
409 | target.version_name уже занято другой живой версией проекта |
DF_API.LICENSE_LIMIT_REACHED |
403 | target.method: create при достигнутом лимите версий лицензии |
DF_API.UNPROCESSABLE_ENTITY |
422 | Источник не прошёл проверку (errors[], которые сообщает эндпоинт проверки) или превышает лимиты |
| Общие ошибки группы | — | Выше |
DF_API.INVALID_PARAMETER |
400 | Повреждённый архив или неверный тип файла |
5 Управление Git-подключениями (df-api/v2)
Реестр сохранённых Git-подключений компании (см. также раздел 4). Все эндпоинты требуют роли COMPANY_ADMIN (или SUPER_ADMIN); недостаточная роль отвечает 403 DF_API.WRITE_ACCESS_DENIED, подключение, невидимое ключу, — 404 DF_API.CONNECTION_NOT_FOUND. Пути имеют область компании и не содержат проекта и версии.
| Метод | Путь | Раздел |
|---|---|---|
GET |
/git-connections |
5.1 |
POST |
/git-connections |
5.2 |
GET |
/git-connections/{connection_id} |
5.3 |
PUT |
/git-connections/{connection_id} |
5.4 |
DELETE |
/git-connections/{connection_id} |
5.5 |
POST |
/git-connections/{connection_id}/test |
5.6 |
Объект подключения, который возвращают 5.1–5.4:
{
"id": "17",
"name": "Config repository",
"platform": "gitlab",
"repository_url": "https://gitlab.example.com/analytics/dataforge-config.git",
"branch": "main",
"path": "/sales",
"status": "active",
"last_used": "2026-05-05T08:30:00.000Z",
"created_at": "2026-04-01T10:00:00.000Z",
"created_by": "admin@example.com",
"shared": false,
"default": true
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор подключения |
name |
string | Отображаемое имя |
platform |
string | github, gitlab, bitbucket, azure-devops, generic; дополнительно на чтение github-enterprise (создаётся только из браузерного диалога) |
repository_url |
string | URL репозитория без учётных данных |
branch |
string | Ветка по умолчанию |
path |
string | Путь внутри репозитория, всегда с ведущим /; / для корня |
status |
string | active (последняя проверка пройдена) или failed |
last_used |
string | null | Обновляется экспортом/импортом через подключение |
created_at |
string | Дата создания |
created_by |
string | null | E-mail создателя |
shared |
boolean | Доступно всем пользователям компании; непубличное подключение видят только создатель и администраторы |
default |
boolean | Подключение компании по умолчанию |
Учётные данные не возвращаются никогда.
5.1 Список Git-подключений
Запрос
GET /df-api/v2/git-connections
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
page |
query | integer | нет | Номер страницы, нумерация с 1. По умолчанию 1 |
pageSize |
query | integer | нет | Размер страницы. По умолчанию 20, максимум 100 (большее значение отклоняется) |
Ответ
200 OK
{
"git-connections": [ { "id": "17", "name": "Config repository", "…": "…" } ],
"pagination": { "total": 1, "page": 1, "pageSize": 20, "totalPages": 1 }
}
| Поле | Тип | Описание |
|---|---|---|
git-connections[] |
array | Объекты подключений (выше). Ключ пишется через дефис |
pagination |
object | total, page, pageSize, totalPages |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.PAGE_SIZE_EXCEEDED |
400 | pageSize больше 100 |
DF_API.WRITE_ACCESS_DENIED |
403 | Владелец ключа не является администратором компании или суперадминистратором |
5.2 Создать Git-подключение
Запрос
POST /df-api/v2/git-connections
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
Idempotency-Key |
заголовок | UUID v4 | нет | Защита от повтора |
name |
тело | string | да | 1–255 символов |
platform |
тело | string | да | github, gitlab, bitbucket, azure-devops, generic |
repository_url |
тело | string | да | URL репозитория (внутренний хост отклоняется) |
branch |
тело | string | да | Ветка по умолчанию |
path |
тело | string | нет | Путь внутри репозитория |
authentication |
тело | object | да | Учётные данные (раздел 4): method pat / ssh / password и его поля |
settings.allow_branch_override |
тело | boolean | нет | Разрешить экспорту/импорту через это подключение указывать другую ветку. По умолчанию true |
settings.allow_path_override |
тело | boolean | нет | То же для пути. По умолчанию true |
settings.set_as_default |
тело | boolean | нет | Сделать подключением компании по умолчанию (снимает флаг с прежнего). По умолчанию false |
settings.share_with_all |
тело | boolean | нет | Сделать доступным всем пользователям компании. По умолчанию false (подключения, созданные во внутреннем интерфейсе, общие) |
{
"name": "Config repository",
"platform": "gitlab",
"repository_url": "https://gitlab.example.com/analytics/dataforge-config.git",
"branch": "main",
"path": "/sales",
"authentication": { "method": "pat", "token": "<personal-access-token>" },
"settings": { "set_as_default": true }
}
Детали
Перед сохранением подключение тестируется — недостижимый репозиторий или отклонённые учётные данные отменяют создание. Учётные данные шифруются при хранении.
Ответ
201 Created
{
"id": "17",
"name": "Config repository",
"platform": "gitlab",
"repository_url": "https://gitlab.example.com/analytics/dataforge-config.git",
"branch": "main",
"path": "/sales",
"status": "active",
"last_used": "2026-05-05T08:30:00.000Z",
"created_at": "2026-04-01T10:00:00.000Z",
"created_by": "admin@example.com",
"shared": false,
"default": true
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор подключения |
name |
string | Отображаемое имя |
platform |
string | github, gitlab, bitbucket, azure-devops, generic; дополнительно на чтение github-enterprise (создаётся только из браузерного диалога) |
repository_url |
string | URL репозитория без учётных данных |
branch |
string | Ветка по умолчанию |
path |
string | Путь внутри репозитория, всегда с ведущим /; / для корня |
status |
string | active (последняя проверка пройдена) или failed |
last_used |
string | null | Обновляется экспортом/импортом через подключение |
created_at |
string | Дата создания |
created_by |
string | null | E-mail создателя |
shared |
boolean | Доступно всем пользователям компании; непубличное подключение видят только создатель и администраторы |
default |
boolean | Подключение компании по умолчанию |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.GIT_CONNECTION_FAILED |
422 | Репозиторий недостижим или отклонил учётные данные |
DF_API.INVALID_PARAMETER |
400 | Ветка не существует |
DF_API.WRITE_ACCESS_DENIED |
403 | Владелец ключа не является администратором |
5.3 Получить Git-подключение
Запрос
GET /df-api/v2/git-connections/{connection_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
connection_id |
путь | integer | да | Идентификатор подключения |
Ответ
200 OK
{
"id": "17",
"name": "Config repository",
"platform": "gitlab",
"repository_url": "https://gitlab.example.com/analytics/dataforge-config.git",
"branch": "main",
"path": "/sales",
"status": "active",
"last_used": "2026-05-05T08:30:00.000Z",
"created_at": "2026-04-01T10:00:00.000Z",
"created_by": "admin@example.com",
"shared": false,
"default": true
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор подключения |
name |
string | Отображаемое имя |
platform |
string | github, gitlab, bitbucket, azure-devops, generic; дополнительно на чтение github-enterprise (создаётся только из браузерного диалога) |
repository_url |
string | URL репозитория без учётных данных |
branch |
string | Ветка по умолчанию |
path |
string | Путь внутри репозитория, всегда с ведущим /; / для корня |
status |
string | active (последняя проверка пройдена) или failed |
last_used |
string | null | Обновляется экспортом/импортом через подключение |
created_at |
string | Дата создания |
created_by |
string | null | E-mail создателя |
shared |
boolean | Доступно всем пользователям компании; непубличное подключение видят только создатель и администраторы |
default |
boolean | Подключение компании по умолчанию |
Ошибки. 404 DF_API.CONNECTION_NOT_FOUND, 403 DF_API.WRITE_ACCESS_DENIED.
5.4 Обновить Git-подключение
Запрос
PUT /df-api/v2/git-connections/{connection_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
connection_id |
путь | integer | да | Идентификатор подключения |
name, platform, repository_url, branch, path |
тело | — | нет | Как при создании; изменяются только переданные поля |
authentication |
тело | object | нет | Новые учётные данные; при отсутствии сохраняются прежние |
settings.* |
тело | boolean | нет | Любое подмножество настроек создания |
Детали
Смена хоста подключения требует ввести учётные данные заново.
Ответ
200 OK
{
"id": "17",
"name": "Config repository",
"platform": "gitlab",
"repository_url": "https://gitlab.example.com/analytics/dataforge-config.git",
"branch": "main",
"path": "/sales",
"status": "active",
"last_used": "2026-05-05T08:30:00.000Z",
"created_at": "2026-04-01T10:00:00.000Z",
"created_by": "admin@example.com",
"shared": false,
"default": true
}
| Поле | Тип | Описание |
|---|---|---|
id |
string | Идентификатор подключения |
name |
string | Отображаемое имя |
platform |
string | github, gitlab, bitbucket, azure-devops, generic; дополнительно на чтение github-enterprise (создаётся только из браузерного диалога) |
repository_url |
string | URL репозитория без учётных данных |
branch |
string | Ветка по умолчанию |
path |
string | Путь внутри репозитория, всегда с ведущим /; / для корня |
status |
string | active (последняя проверка пройдена) или failed |
last_used |
string | null | Обновляется экспортом/импортом через подключение |
created_at |
string | Дата создания |
created_by |
string | null | E-mail создателя |
shared |
boolean | Доступно всем пользователям компании; непубличное подключение видят только создатель и администраторы |
default |
boolean | Подключение компании по умолчанию |
Ошибки
| Код | HTTP | Условие |
|---|---|---|
DF_API.CONNECTION_NOT_FOUND |
404 | Подключение не существует или невидимо |
DF_API.INVALID_PARAMETER |
400 | repository_url переносится на другой хост без нового authentication |
DF_API.WRITE_ACCESS_DENIED |
403 | Владелец ключа не является администратором |
5.5 Удалить Git-подключение
Запрос
DELETE /df-api/v2/git-connections/{connection_id}
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
connection_id |
путь | integer | да | Идентификатор подключения |
Детали
Версии, импортированные через подключение, сохраняются и теряют ссылку.
Ответ
204 No Content
Ошибки. 404 DF_API.CONNECTION_NOT_FOUND, 403 DF_API.WRITE_ACCESS_DENIED.
5.6 Проверить Git-подключение
Запрос
POST /df-api/v2/git-connections/{connection_id}/test
| Параметр | Где | Тип | Обяз. | Описание |
|---|---|---|---|---|
connection_id |
путь | integer | да | Идентификатор подключения |
Детали
Без тела. Выполняет пять проверок репозитория и обновляет сохранённый status подключения, как во внутреннем интерфейсе. Idempotency-Key намеренно не учитывается — закешированный вердикт был бы устаревшим. Пустой репозиторий — допустимая цель экспорта: проверки проходят, last_commit равен null.
Ответ
200 OK
{
"git-connection_id": "17",
"status": "success",
"tests": {
"repository_reachable": true,
"authentication_valid": true,
"branch_exists": true,
"write_permission": true,
"path_accessible": true
},
"details": {
"last_commit": "3f2a9c1",
"last_commit_date": "2026-05-05T08:30:00.000Z",
"available_branches": ["main", "develop"]
},
"tested_at": "2026-05-05T09:00:00.000Z"
}
| Поле | Тип | Описание |
|---|---|---|
git-connection_id |
string | Проверенное подключение (ключ пишется именно так, через дефис) |
status |
string | success или failed |
tests |
object | Пять проверок лесенкой — каждая следующая подразумевает предыдущие: repository_reachable, authentication_valid, branch_exists, write_permission, path_accessible |
details.last_commit |
string | null | Короткий хеш вершины ветки |
details.last_commit_date |
string | null | Дата этого коммита |
details.available_branches |
array of string | Ветки репозитория |
tested_at |
string | Момент выполнения проверки |
Ошибки. 404 DF_API.CONNECTION_NOT_FOUND, 403 DF_API.WRITE_ACCESS_DENIED. Непройденная проверка ошибкой не является: ответ 200 со status: "failed".