integram.io · для разработчиков

API Интеграм

Через API доступно всё, что пользователь делает в интерфейсе Интеграма: создать таблицы и колонки, завести записи, пользователей и роли, выдать доступы, построить запрос с фильтрами и формулами.

Примеры даны для https://integram.io и базы mydb: подставьте имя своей базы.

Общие правила

Термины

Всё в базе Интеграма — термины: Клиент, Адрес, Статус, Пользователь. Пользователь видит их как таблицы и колонки, разработчик — как типы и их реквизиты. «Таблица Клиент с колонками Адрес и Телефон» и «тип Клиент с реквизитами Адрес и Телефон» — одно и то же.

  • Таблица (тип) — термин верхнего уровня. Значение её первой колонки — главное значение записи.
  • Колонка (реквизит) — термин, добавленный к таблице. Один термин может быть колонкой у разных таблиц.
  • Справочная колонка — ссылка на другую таблицу; в ней хранится id записи справочника.
  • Подчинённая таблица — записи, принадлежащие записи родителя (позиции заказа, пункты меню роли).

Адрес команды

Команда — это адрес вида /{база}/{команда}/{id}. Параметр JSON в адресе говорит, что ответ нужен в JSON, а не HTML-страницей.

https://integram.io/{база}/{команда}/{id}?JSON=1
  • _d_* — изменение структуры (таблиц и колонок), POST;
  • _m_* — изменение данных (записей), POST;
  • metadata, object, report, terms, xsrf — чтение, GET.

Поля POST-запросов передаются формой (-F в curl или application/x-www-form-urlencoded). Значение колонки передаётся полем t{id колонки}, например t41=ivan@example.com.

Имена вместо кодов

Таблицы, записи и запросы можно называть в адресе по именам, не зная их id: ядро ищет термин с таким именем, а для записи — запись с таким главным значением.

ГдеКакПример
Таблица в адресеИмя таблицы вместо её id — в любой командеmetadata/Клиент, object/Клиент, _m_new/Клиент
Запись в адресеИмя таблицы и главное значение записиedit_obj/Клиент/АО Ромашка, _m_set/Роль/Менеджер
Запрос в адресеНазвание запроса вместо idreport/Клиенты по категориям
Фильтр запросаИмя колонки в отчёте, пробелы — _FR_Дата_заказа=01.10.2026
curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/metadata/Пользователь?JSON=1"
curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/edit_obj/Роль/admin?JSON=1"
curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/report/Клиенты%20по%20категориям?JSON_KV"
  • пробел в адресе пишется как %20, остальную кириллицу curl передаёт как есть;
  • поля записи передаются только кодами t{id колонки}, фильтры записей — F_{id колонки}: id колонок отдаёт metadata;
  • если в базе два термина с одним именем, адрес берёт первый найденный — такие таблицы читайте по id.

Ответы и ошибки

Команды _d_* и _m_* отвечают объектом одного вида: id — созданный или изменённый элемент, obj — объект, к которому он относится, warnings — предупреждения.

{"id": 643, "obj": 641, "next_act": "edit_types", "args": "ext", "warnings": ""}

Ошибка приходит массивом с ключом error, и HTTP-статус у неё обычно 200: проверяйте в ответе ключ error, а не только код. Свой статус есть у немногих отказов: 401 — нет авторизации или неверный пароль в auth, 403 — неверный или устаревший _xsrf, 429 — вход временно заблокирован.

[{"error": "Вы хотите удалить реквизит у типа при наличии этого реквизита у экземпляров (всего: 1)!"}]

Авторизация

Токен API

Для программ и интеграций удобнее всего постоянный токен: заведите в базе пользователя (например, api), впишите ему в поле «Токен» случайную строку из 15–64 символов и выдайте роль с нужными правами. Токен передаётся заголовком X-Authorization в каждом запросе.

TOKEN=a3f1c9...           # токен пользователя api
curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/metadata?JSON=1"

Заголовок читается, только если в адресе или теле запроса есть параметр JSON (JSON, JSON_KV, JSON_OBJ…). Без него запрос считается переходом браузера и уходит на страницу входа.

Вместо X-Authorization подходит Authorization: <токен> или Authorization: Bearer <токен>. Ещё токен можно передать кукой, названной именем базы (mydb), или полем формы token в POST-запросе. Кука нужна командам, работающим с сессией, например файловому менеджеру dir_admin.

curl -s -b "mydb=$TOKEN" "https://integram.io/mydb/metadata?JSON=1"

Простейший вариант — Basic-авторизация: логин и пароль в каждом запросе. По RFC 7617 пара логин:пароль кодируется в Base64, curl делает это сам ключом -u.

curl -s -u "manager:Str0ng-Pass" "https://integram.io/mydb/metadata?JSON=1"

Токен XSRF

Каждый POST-запрос на изменение (_d_*, _m_*) должен нести поле _xsrf. Его выдаёт команда xsrf; заодно она сообщает пользователя, его роль и id.

curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/xsrf?JSON=1"

Ответ

{"_xsrf": "cd4b6417a3940ed4a84h074d", "token": "a3f1c9...", "user": "api", "role": "api", "id": "632", "msg": ""}

Получить в переменную (нужен jq)

XSRF=$(curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/xsrf?JSON=1" | jq -r ._xsrf)

Дальше в примерах $TOKEN и $XSRF — эти два значения. _xsrf привязан к токену, которым его получили: запрашивайте его и шлите POST под одним и тем же токеном.

Вход по логину и паролю

Команда auth проверяет логин и пароль и открывает сессию этого устройства. В ответе — токен сессии и _xsrf к нему.

curl -s "https://integram.io/mydb/auth?JSON=1" -F "login=manager" -F "pwd=Str0ng-Pass"

Ответ

{"_xsrf": "1cb413634d074d3804ed48", "token": "s.1824537600.9e0c...", "id": "632", "msg": ""}

Сессия живёт, пока ею пользуются: без запросов она гаснет через 30 дней. Пять неверных паролей подряд блокируют вход на 15 минут, сервер отвечает 429 с заголовком Retry-After.

Выход — GET /{база}/exit гасит текущую сессию, exit?all=1 — все сессии пользователя.

Базы

Список баз

Базы пользователя перечислены в его личном кабинете — базе my. Список отдаёт отчёт 313.

curl -s -H "X-Authorization: $TOKEN" "https://integram.io/my/report/313?JSON_KV=1"

Ответ (сокращён)

[
  {"DB": "test", "DBID": "178652", "Template": "RU", "Plan": "Startup", "Plan date": "23.04.2026"},
  {"DB": "mydb", "DBID": "195822", "Template": "RU", "Plan": "Startup", "Plan date": "23.04.2026"}
]

Создать базу

Команда _new_db кабинета my: db — имя новой базы (латиница и цифры), template — шаблон, обычно RU.

curl -s -H "X-Authorization: $TOKEN" "https://integram.io/my/_new_db/?JSON=1&db=apiman&template=RU"

Ответ

{"status": "Ok", "id": 221756}

В новой базе уже есть администратор: пользователь с логином, равным имени базы, и ролью admin (145). У него полный доступ в обход прав; переименовать его или сменить ему роль нельзя.

Структура: таблицы и колонки

Базовые типы

Тип каждой колонки — один из базовых. Его код передаётся параметром t при создании термина.

КодТипЧто хранит
3SHORTКороткая строка (до 127 символов)
8CHARSСтрока без ограничения длины
12MEMOМногострочный текст
13NUMBERЦелое число
14SIGNEDЧисло с дробной частью
9DATEДата, 30.10.2026
4DATETIMEДата и время; через API — unix-время в секундах
11BOOLEANДа / нет: 1 или пусто
10FILEФайл
2HTMLHTML-текст, выводится без экранирования
6PWDПароль: хранится хешем, на экране — «******»
7BUTTONКнопка-действие над записью
5GRANTОбъект системы — выбор таблицы или колонки
16REPORT_COLUMNКолонка запроса
17PATHПуть к файлу

Метаданные

Команда metadata без id описывает всю базу, с id — одну таблицу. Отсюда берут id колонок для t{id} в записях и запросах.

curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/metadata/18?JSON=1"
curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/metadata/Пользователь?JSON=1"     # то же по имени

Ответ (сокращён): таблица Пользователь

{
  "id": "18", "up": "0", "type": "3", "val": "Пользователь", "unique": "1",
  "reqs": [
    {"num": 1, "id": "115", "orig": "42", "val": "Роль", "type": "3", "ref": "42", "ref_id": "114",
     "attrs": ":!NULL:"},
    {"num": 2, "id": "41", "orig": "41", "val": "Email", "type": "3"},
    {"num": 4, "id": "156", "orig": "156", "val": "Дата", "type": "9", "attrs": "[TODAY]"}
  ]
}
  • id — id таблицы или колонки; val — имя; type — базовый тип;
  • unique — значения первой колонки уникальны;
  • ref — таблица-справочник у справочной колонки, ref_id — id ссылки на неё;
  • orig — термин колонки: у справочной — таблица-справочник, у обычной — сам термин;
  • arr_id — подчинённая таблица;
  • attrs — атрибуты колонки строкой, только если заданы.

Атрибуты хранятся строкой: :!NULL: — обязательное поле, :MULTI: — множественный выбор, :ALIAS=Имя: — псевдоним, а текст вне двоеточий — значение по умолчанию. Например, :!NULL::ALIAS=Исполнитель: — обязательная колонка с псевдонимом.

Список таблиц

Команда terms отдаёт таблицы базы, доступные пользователю: id, базовый тип первой колонки и имя.

curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/terms?JSON=1"

Ответ

[{"id": 641, "type": 3, "name": "Клиент"}, {"id": 18, "type": 3, "name": "Пользователь"}, {"id": 42, "type": 3, "name": "Роль"}]

Создать таблицу

_d_new создаёт термин — таблицу из одной колонки. t — базовый тип первой колонки, val — имя, unique=1 — значения первой колонки уникальны (так делают справочники).

curl -s "https://integram.io/mydb/_d_new?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "t=3" -F "val=Клиент"

Ответ: id новой таблицы — в obj

{"id": "", "obj": 641, "next_act": "edit_types", "args": "ext", "warnings": ""}

Повторный вызов с тем же именем не создаёт дубль: вернётся id существующего термина и предупреждение в warnings.

Добавить колонку

Колонка добавляется в два шага: создать термин колонки (_d_new) и добавить его к таблице (_d_req). Если подходящий термин уже есть, первый шаг пропускают.

curl -s "https://integram.io/mydb/_d_new?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "t=3" -F "val=ИНН"
# → {"obj": 642, ...}
curl -s "https://integram.io/mydb/_d_req/641?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "t=642"
# → {"id": 643, "obj": 641, ...}

Id колонки — id из ответа _d_req (643), а не obj: дальше значение этой колонки пишется полем t643.

Колонка-справочник

Справочная колонка ссылается на другую таблицу. Шаги: таблица-справочник, ссылка на неё (_d_ref), ссылка как колонка (_d_req).

curl -s "https://integram.io/mydb/_d_new?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "t=3" -F "val=Категория" -F "unique=1"
# → {"obj": 644}
curl -s "https://integram.io/mydb/_d_ref/644?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF"
# → {"obj": 645}       — ссылка на Категорию
curl -s "https://integram.io/mydb/_d_req/641?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "t=645"
# → {"id": 646}        — колонка Категория у Клиента

Множественный выбор включает и выключает _d_multi на колонке:

curl -s "https://integram.io/mydb/_d_multi/646?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF"

Если в таблице несколько колонок со ссылкой на один справочник (Автор, Исполнитель, Контролёр — все из Пользователя), дайте им псевдонимы через _d_alias с id колонки:

curl -s "https://integram.io/mydb/_d_alias/648?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "val=Исполнитель"

Подчинённая таблица

Табличная часть (позиции заказа, этапы проекта) — это таблица, добавленная к другой таблице через _d_req без ссылки. Её записи создаются с родителем up={id записи}.

curl -s "https://integram.io/mydb/_d_new?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "t=3" -F "val=Позиция"
# → {"obj": 700}
curl -s "https://integram.io/mydb/_d_req/690?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "t=700"     # 690 — таблица Заказ

Обязательность и значение по умолчанию

_d_null переключает обязательность колонки. _d_attrs задаёт значение по умолчанию: константу или переменную: [TODAY] — сегодня, [USER_ID] — текущий пользователь. Результат виден в attrs колонки в metadata.

curl -s "https://integram.io/mydb/_d_null/643?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF"
curl -s "https://integram.io/mydb/_d_attrs/650?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "val=[TODAY]"

Переместить и удалить

_d_ord ставит колонку на позицию order (первую колонку двигать нельзя), _d_up — на одну позицию выше.

curl -s "https://integram.io/mydb/_d_ord/648?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "order=1"

_d_del_req удаляет колонку. Если в ней есть данные, сервер откажет; forced=1 удаляет вместе с данными. Сам термин колонки остаётся и может пригодиться в другой таблице.

curl -s "https://integram.io/mydb/_d_del_req/643?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "forced=1"

_d_del удаляет пустую таблицу или неиспользуемый термин. Порядок для таблицы с данными: записи, затем ссылки на неё и доступы, затем сама таблица.

curl -s "https://integram.io/mydb/_d_del/642?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF"

_d_save переименовывает таблицу или меняет её базовый тип: val — имя, t — базовый тип, unique=1 — признак уникальности.

Записи

Прочитать записи

Команда object с id таблицы отдаёт её записи. Формат JSON_OBJ — массив строк: i — id записи, u — родитель, o — порядок, r — значения колонок по порядку метаданных.

curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/object/641/?JSON_OBJ&LIMIT=100"

Ответ

[
  {"i": 649, "u": 1, "o": 1, "r": ["АО Ромашка", "7701234567", "660:Клиент"]},
  {"i": 668, "u": 1, "o": 2, "r": ["ПАО Эллипс", "7709876543", "650:Лид"]}
]

Справочное значение приходит как id:Название, множественное — id1,id2:Название1,Название2.

ПараметрЧто делает
F_{id колонки}=значениеФильтр по колонке
F_{id таблицы}=значениеФильтр по первой колонке: её ключ — id самой таблицы
FR_{колонка}=…&TO_{колонка}=…Диапазон: от и до
F_U={id родителя}Записи подчинённой таблицы у одного родителя
F_I={id записи}Одна запись
ORDER={id колонки}Сортировка; ORDER=-{id} — по убыванию
LIMIT=100 · LIMIT=100,100Первые 100 записей · 100 записей, начиная со 101-й
_count=Только число записей: {"count": "42"}
full=1Не обрезать длинные значения

В значении фильтра работают условия: %ООО% — содержит, !значение — не равно, >100, <=20002, 10..20 — между, % — непусто, !% — пусто, IN(a,b) — одно из значений, @660 — ссылка на запись 660, @IN(21006,21014) — на одну из записей, [TODAY] и другие переменные.

# клиенты, в названии которых есть «Ромашка»: %25 — это % в адресе
curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/object/641/?JSON_OBJ&F_641=%25Ромашка%25"
# позиции заказа 691
curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/object/700/?JSON_OBJ&F_U=691"
# таблица по имени, фильтр — по id колонки ИНН
curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/object/Клиент?JSON_OBJ&F_643=7701234567"

Подчинённую таблицу без F_U сервер отдаёт пустой: её записи висят на родителях, а не на корне.

Создать запись

_m_new с id таблицы. Главное значение записи пишется в t{id таблицы}, колонки — в t{id колонки}. up=1 — запись верхнего уровня, up={id записи} — подчинённая.

curl -s "https://integram.io/mydb/_m_new/641?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=1" -F "t641=АО Ромашка" -F "t643=7701234567" -F "t646=660"

Ответ

{"id": 649, "obj": 649, "ord": 1, "next_act": "object", "args": "", "val": "АО Ромашка"}

В справочную колонку пишется id записи справочника (t646=660). Позиция заказа 691:

curl -s "https://integram.io/mydb/_m_new/700?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "up=691" -F "t700=Труба 32 мм" -F "t702=12"

Изменить запись

_m_set с id записи меняет переданные колонки, включая первую. Пустое значение очищает поле, у BOOLEAN снимают галку значением 0.

curl -s "https://integram.io/mydb/_m_set/649?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "t643=7701234568" -F "t646=661"

Признак удачной записи — "obj": 649 (id записи) и непустой id в ответе. В справочный ключ t{id} _m_set принимает только id; пробел (t646= ) очищает одиночную ссылку.

Запись можно назвать в адресе по имени таблицы и главному значению:

curl -s "https://integram.io/mydb/_m_set/Клиент/АО%20Ромашка?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "t643=7701234568" -F "t646=661"

В колонку с множественным выбором передают id записей через запятую: t648=616,617.

Варианты для справочной колонки отдаёт _ref_reqs с id колонки; параметр id — запись, для которой выбирают значение:

curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/_ref_reqs/646?JSON=1&id=649"
# → {"650": "Лид", "660": "Клиент", "661": "ЧС"}

Удалить и переместить

_m_del удаляет запись вместе с подчинёнными; если на неё ссылаются другие записи, сервер откажет ошибкой в error. _m_move переносит подчинённую запись к другому родителю, _m_up поднимает её на одну позицию среди соседей, _m_ord ставит на позицию order.

curl -s "https://integram.io/mydb/_m_del/668?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF"
curl -s "https://integram.io/mydb/_m_move/705?JSON=1&up=692" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF"

Все записи под фильтром удаляет object с _m_del_select. Записи, на которые есть ссылки, остаются. Ответ — переадресация, число удалённых — в параметре deleted её адреса:

curl -s -o /dev/null -w "%{redirect_url}\n" "https://integram.io/mydb/object/641/?JSON=1&F_646=650" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "_m_del_select=1"
# → …/object/641?…&deleted=31

Загрузка файлом

Тысячи записей загружают файлом: object/{таблица} с import=1 и файлом bki_file. Строка файла — значения колонок через ; в порядке метаданных, первой строкой — DATA. Справочные колонки задаются названиями, даты — ДД.ММ.ГГГГ, ; внутри значения экранируется как \;. Если первая колонка уникальна, существующие записи обновляются.

clients.bki

DATA
АО Ромашка;7701234567;Клиент;;
ПАО Эллипс;7709876543;Лид;;
curl -s "https://integram.io/mydb/object/641?JSON&import=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "bki_file=@clients.bki;type=text/plain"

Файл — до 8 МБ; большие объёмы делите на части по несколько тысяч строк. Для подчинённой таблицы добавьте в адрес F_U={id родителя}.

Пользователи, роли и доступ

Системные таблицы

Пользователи, роли, меню, доступы и запросы — обычные таблицы базы. Их записи создаются и меняются теми же _m_new, _m_set и _m_del.

ТаблицаidКолонки
Пользователь18t18 логин, t115 роль, t20 пароль, t33 имя, t41 email, t125 токен API
Роль42t42 название, t135 описание
Объекты (доступы роли)116t116 объект, t136 уровень, t49 маска; подчинена роли
Меню151t151 название, t153 адрес, t391 иконка; подчинено роли
Запрос22t22 название; колонки запроса — таблица 28
Функция63Справочник функций колонок запроса: SUM, COUNT, abn_ID…

Колонки Activity (t124) и xsrf (t40) заполняет сервер — не пишите в них. Неудачные входы ядро integram.io считает в журнале базы, а не в колонке пользователя.

Создать роль

curl -s "https://integram.io/mydb/_m_new/42?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=1" -F "t42=Менеджер" -F "t135=Ведёт клиентов и заказы"
# → {"id": 900, ...}

Роли базы — object/42/?JSON_OBJ. Роль admin с полным доступом — запись 145. Id роли по названию:

curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/object/Роль?JSON_OBJ&F_42=Менеджер"
# → [{"i": 900, "u": 1, "o": 1, "r": ["Менеджер", "", "", "Ведёт клиентов и заказы"]}]

Создать пользователя и задать пароль

Пользователь — запись таблицы 18: логин в t18, роль в t115, пароль в t20. Пароль сохраняется хешем, прочитать его обратно нельзя.

curl -s "https://integram.io/mydb/_m_new/18?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=1" -F "t18=ivanov" -F "t115=900" -F "t20=Str0ng-Pass" -F "t33=Иван Иванов" -F "t41=ivanov@example.com"
# → {"id": 910, ...}

Сменить пароль или роль — _m_set с id пользователя. Открытые сессии смена пароля не закрывает: выйти на всех устройствах — exit?all=1 под токеном этого пользователя.

curl -s "https://integram.io/mydb/_m_set/910?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "t20=N3w-Pass"
curl -s "https://integram.io/mydb/_m_set/910?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "t115=901"

Пользователь для интеграции получает вместо пароля токен API в t125 — с ним он работает заголовком X-Authorization (см. «Токен API»):

curl -s "https://integram.io/mydb/_m_new/18?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=1" -F "t18=api" -F "t115=900" -F "t125=$(openssl rand -hex 32)"

Выдать доступ

Доступ роли к таблице, колонке или запросу — запись таблицы 116, подчинённая роли: up — роль, t116 — объект, t136 — уровень.

t136Уровень
53READ — чтение
54WRITE — чтение и изменение
52BARRED — нет доступа (колонка не приходит даже в API)
curl -s "https://integram.io/mydb/_m_new/116?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=900" -F "t116=641" -F "t136=54"   # Клиент: запись
curl -s "https://integram.io/mydb/_m_new/116?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=900" -F "t116=644" -F "t136=53"   # Категория: чтение
curl -s "https://integram.io/mydb/_m_new/116?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=900" -F "t116=643" -F "t136=52"   # колонка ИНН скрыта

Уровень таблицы наследуют её колонки; отдельной колонке его можно понизить. Кроме таблиц в t116 бывают особые объекты: 0 — редактор структуры (WRITE на него нужен для команд _d_*), 1 — все таблицы, 10 — файловый менеджер. Поля t55 и t56 разрешают роли выгрузку и удаление.

Новая таблица не выдана ни одной роли: без доступа её записи отвечают 403, а выпадающий список справочника пуст. Выдавайте доступ сразу после _d_new всем ролям, чьи экраны ею пользуются.

Доступы роли — object/116/?JSON_OBJ&F_U={роль}, роли с доступом к таблице — object/42/?JSON_OBJ&F_116={таблица}.

Маски: только свои записи

Маска t49 у доступа фильтрует строки, которые увидит роль. Её значение работает как фильтр F_ по колонке из t116.

# менеджер видит только клиентов, где он — ответственный (колонка 651 ссылается на Пользователя)
curl -s "https://integram.io/mydb/_m_new/116?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=900" -F "t116=651" -F "t136=54" -F "t49=[USER_ID]"
# пользователь видит в таблице Пользователь только себя
curl -s "https://integram.io/mydb/_m_new/116?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=900" -F "t116=18" -F "t136=53" -F "t49=[USER]"
  • переменные: [USER] — логин, [USER_ID] — id пользователя, [ROLE], [ROLE_ID];
  • значение или условие: 164, %ООО%, @IN(21006,21014);
  • [Имя запроса] — подставляется первая ячейка первой строки запроса, например список id через GROUP_CONCAT;
  • маски на одну колонку складываются по ИЛИ, на разные колонки — по И.

Гостевой доступ

Посетитель без входа работает пользователем guest, если в базе есть и роль guest, и пользователь guest с этой ролью. Что видит гость, решают доступы и меню роли guest.

Запросы (отчёты)

Как устроен запрос

Запрос — запись таблицы 22, его колонки — записи таблицы 28 с up={id запроса}. У колонки есть источник (таблица или колонка), имя, формула, фильтр и функция. Как соединить таблицы и по чему группировать, ядро определяет само по метаданным.

ПолеЧто задаёт
t28Источник: id таблицы (её главное значение) или id колонки; 0 — вычисляемая колонка
t100Имя в отчёте: ключ в JSON_KV и имя фильтра FR_{имя}. Без имени колонку снаружи не отфильтровать
t101Формула: у колонки с источником — псевдоним (одно слово), у вычисляемой — SQL-выражение над псевдонимами
t102 / t103Фильтр: значение от / до
t104Функция: SUM, COUNT, AVG, MIN, MAX, GROUP_CONCAT; abn_ID — id записи
t105 / t106Фильтр по значению функции (HAVING)
t1071 — скрыть колонку: она фильтрует и связывает, но не выводится
t109Сортировка: 1, 2…; минус — по убыванию
t84Формат: NUMBER, SIGNED, DATE, HTML
t72Итог по колонке в форме отчёта: SUM, COUNT

Первая колонка задаёт главную таблицу: строки отчёта — её записи. Колонки связанных таблиц добавляются просто id их колонок — путь по ссылкам ядро находит само.

Создать запрос

Отчёт «Клиенты по категориям»: категория, число клиентов и сумма заказов.

curl -s "https://integram.io/mydb/_m_new/22?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" -F "up=1" -F "t22=Клиенты по категориям"
# → {"id": 950}
curl -s "https://integram.io/mydb/_m_new/28?JSON=1&up=950" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=950" -F "t28=646" -F "t100=Категория" -F "t109=1"
curl -s "https://integram.io/mydb/_m_new/28?JSON=1&up=950" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=950" -F "t28=641" -F "t100=Клиентов" -F "t104=COUNT" -F "t72=SUM"
curl -s "https://integram.io/mydb/_m_new/28?JSON=1&up=950" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=950" -F "t28=695" -F "t100=Сумма" -F "t104=SUM" -F "t84=NUMBER"

GROUP BY строится по всем видимым колонкам без функции — здесь по Категории. В _m_new функцию можно указать именем (t104=SUM), в _m_set — только id записи из таблицы Функция: object/63/?JSON_OBJ.

Колонки запроса — object/28/?JSON_OBJ&F_U=950, список запросов — object/22/?JSON_OBJ.

Формулы и вычисляемые колонки

Колонке-источнику дают псевдоним в t101, вычисляемая колонка (t28=0) использует его в SQL-выражении. В формуле — псевдоним, а не имя в отчёте.

curl -s "https://integram.io/mydb/_m_new/28?JSON=1&up=960" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=960" -F "t28=720" -F "t100=Мест" -F "t101=мест" -F "t107=1"
curl -s "https://integram.io/mydb/_m_new/28?JSON=1&up=960" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=960" -F "t28=721" -F "t100=Куплено" -F "t101=куплено"
curl -s "https://integram.io/mydb/_m_new/28?JSON=1&up=960" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=960" -F "t28=0" -F "t100=Загрузка, %" -F "t101=ROUND(куплено/мест*100, 2)"
  • псевдоним — одно слово, не совпадающее с SQL-словами (id, val, SUM);
  • агрегат внутри формулы: ROUND(SUM(Оценка), 1);
  • [THIS] — собственное значение колонки: COALESCE([THIS], 0);
  • ссылка: CONCAT('<a href="', Адрес, '">открыть</a>') с t84=HTML;
  • SELECT, FROM, TABLE в формулах запрещены — выборка из другой таблицы делается подзапросом.

Фильтры

Постоянный фильтр задаётся в t102 (от) и t103 (до) у колонки. Колонку только для фильтра скрывают (t107=1). Если у колонки нет «Имени в отчёте» (t100), её фильтр снаружи не переопределить — так задают ограничители, см. «Права на запрос».

t102Отбирает
ОдобренаРавно значению; у справочной колонки — по названию
660 при t104=abn_IDСсылка на запись справочника 660
% / !%Непусто / пусто
!1Не равно 1
>=[WEEK_AGO], [TODAY], [YESTERDAY], [MONTH_AGO], [NOW]Относительные даты
1.1 и t103=31.12Диапазон дат текущего года
[USER_ID] при t104=abn_IDСтроки текущего пользователя
_request_.ProjIDПараметр из адреса: report/950?ProjID=12
[Имя запроса]Значение другого запроса
# только свои заказы: колонка Ответственный (697) скрыта и фильтрует по текущему пользователю
curl -s "https://integram.io/mydb/_m_new/28?JSON=1&up=950" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=950" -F "t28=697" -F "t104=abn_ID" -F "t102=[USER_ID]" -F "t107=1"

Подзапросы

Суммы с разных уровней цепочки (Компания ← Заявка ← Договор) в одном запросе удваиваются: строки соединённых таблиц перемножаются. Каждую следующую сумму считают отдельным запросом и вставляют в формулу как [Имя запроса].

# подзапрос «Договоры компании»: сумма договоров компании [КомпанияID]
curl -s "https://integram.io/mydb/_m_new/22?JSON=1" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=1" -F "t22=Договоры компании"
# → {"id": 970}
curl -s "https://integram.io/mydb/_m_new/28?JSON=1&up=970" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=970" -F "t28=812" -F "t100=Сумма" -F "t104=SUM"
curl -s "https://integram.io/mydb/_m_new/28?JSON=1&up=970" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=970" -F "t28=803" -F "t104=abn_ID" -F "t102=[КомпанияID]" -F "t107=1"
# основной запрос: псевдоним КомпанияID и вычисляемая колонка с подзапросом
curl -s "https://integram.io/mydb/_m_new/28?JSON=1&up=980" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=980" -F "t28=800" -F "t100=КомпанияID" -F "t101=КомпанияID" -F "t104=abn_ID" -F "t107=1"
curl -s "https://integram.io/mydb/_m_new/28?JSON=1&up=980" \
  -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF" \
  -F "up=980" -F "t28=0" -F "t100=Законтрактовано" -F "t101=IFNULL([Договоры компании],0)"

Подзапрос без строк возвращает пусто — оберните его в IFNULL или задайте запросу «Если пусто, вернуть» (t113=0).

Выполнить запрос

report с id или названием запроса. JSON_KV — массив объектов с ключами из t100; JSON — с описанием колонок и форматов.

curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/report/950?JSON_KV"

Ответ

[
  {"Категория": "Клиент", "Клиентов": "12", "Сумма": "1840000"},
  {"Категория": "Лид", "Клиентов": "31", "Сумма": "0"}
]

Фильтры снаружи — FR_{имя} (от) и TO_{имя} (до), пробелы в имени заменяются на _. Они работают на колонках с заполненным «Именем в отчёте» (t100) и перекрывают их t102/t103; колонки без имени параметрами не меняются. ORDER={id колонки} сортирует (минус — по убыванию), LIMIT ограничивает число строк, RECORD_COUNT возвращает только их число.

curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/report/950?JSON_KV&FR_Категория=Клиент"
curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/report/951?JSON_KV&FR_Дата=01.10.2026&TO_Дата=31.10.2026&LIMIT=50"
# запрос по названию
curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/report/Клиенты%20по%20категориям?JSON_KV&FR_Категория=Клиент"

Права на запрос

Запрос работает как хранимая процедура: с правами того, кто его настроил, а не того, кто вызывает. Роли нужен только доступ READ к самому запросу (t116={id запроса}, t136=53). Он открывает все колонки и строки, которые отбирает запрос; доступы роли к таблицам и её маски к запросу не применяются.

Это не обход прав, а назначение запроса: отдать ровно то, что решил аналитик, в том числе из таблиц, которые роль руками не видит. Что увидит вызывающий, ограничивают фильтры внутри запроса, и внешний параметр их не отменит:

  • снаружи фильтруются только колонки с заполненным «Именем в отчёте» (t100): FR_{имя} и TO_{имя} перекрывают их t102/t103;
  • у колонки без t100 фильтр t102/t103 параметрами адреса не переопределяется — это защита от подмены фильтра пользователем;
  • фильтруемость включается явно, именем колонки: всё, чему аналитик не дал имени, закрыто для подмены. Это строже правила «фильтровать можно всё, кроме запрещённого».
# ограничитель «только свои заказы»: без t100, скрыт — FR_/TO_ его не заменят
curl -s "https://integram.io/mydb/_m_new/28?JSON=1&up=950"   -H "X-Authorization: $TOKEN" -F "_xsrf=$XSRF"   -F "up=950" -F "t28=697" -F "t104=abn_ID" -F "t102=[USER_ID]" -F "t107=1"

Не давайте колонке-ограничителю «Имя в отчёте». С именем её фильтр становится параметром: вызывающий подставит в FR_ чужой id вместо [USER_ID] и получит чужие строки.

Файлы и рабочие места

Файловый менеджер

dir_admin загружает HTML-шаблоны рабочих мест (templates=1) и скрипты со стилями (download=1). Кроме заголовка нужны кука {база}, поле token и _xsrf, полученный под этой кукой. Без куки сервер отвечает InvalidToken.

XSRF=$(curl -s -b "mydb=$TOKEN" "https://integram.io/mydb/xsrf?JSON=1" | jq -r ._xsrf)
curl -s -H "X-Authorization: $TOKEN" -b "mydb=$TOKEN" "https://integram.io/mydb/dir_admin/?JSON=1" \
  -F "_xsrf=$XSRF" -F "token=$TOKEN" -F "templates=1" -F "add_path=/" -F "upload=Загрузить" -F "rewrite=1" \
  -F "userfile=@clients.html"

Файлы из download=1 раздаются по адресу https://integram.io/download/mydb/. Адрес рабочего места в меню роли — имя шаблона без .html (t153=clients). Доступ роли к файлам — особый объект 10 в таблице 116.

Шаблонизатор

Адрес /mydb/clients открывает оболочку main.html, и её маркер <!-- File: a --> вставляет clients.html из папки базы (templates=1), а если его нет — из общей templates/.

  • Блок <!-- Begin: Clients -->…<!-- End: Clients --> получает строки запроса базы с тем же именем и повторяется по ним; вложенный блок — по строкам своего запроса на каждой строке внешнего.
  • Плейсхолдеры: {колонка} — значение строки, {_parent_.колонка} — строка внешнего блока, {_global_.user}, {_global_.xsrf} и другие — сессия, {_request_.имя} — параметр адреса.
  • Условий нет: блок без строк не выводится, строка с неподставленным {...} выбрасывается. Параметры FR_колонка в адресе фильтруют запросы всех блоков.

Резервная копия

backup создаёт архив базы в папке backups файлового менеджера. Делайте его перед массовыми изменениями структуры. Выгрузка одной таблицы — object/{таблица} с параметром csv или bki.

curl -s -b "mydb=$TOKEN" "https://integram.io/mydb/backup"
curl -s -H "X-Authorization: $TOKEN" "https://integram.io/mydb/object/641/?JSON=1&bki" -o clients.bki