Теги, мозаики, шаблоны
Объекты, из которых собирается рабочее пространство оператора: теги, мозаики, шаблоны камер, отчёты.
На этой странице собраны объекты, которые сами по себе не передают видео, но определяют, как устроено рабочее место: чем сгруппированы камеры, что оператор видит на экране, какими настройками заводятся новые камеры и какие аналитические вопросы сохранены для повторного использования.
Примеры предполагают заданные переменные окружения:
export BASE="https://cctv.example.com" export TOKEN=$(curl -sS "$BASE/api/v1/auth/login" \ -H 'Content-Type: application/json' \ -d '{"login":"admin","password":"<пароль>"}' \ | python3 -c 'import sys, json; print(json.load(sys.stdin)["token"])')
Общие правила аутентификации, пагинации и кодов ошибок — на странице Введение и аутентификация.
Любой эндпоинт этой страницы может вернуть 401 {"error":"unauthorized"}, 403 {"error":"forbidden"}
и 503 {"error":"db_unavailable"}. В таблицах ниже перечислены только ошибки, специфичные для
запроса. Попытка не-суперадмина назвать чужую организацию в ?org / org_id всегда даёт
403 {"error":"cross_org"} — молчаливого отката к своей организации не происходит нигде.
Что за что отвечает#
Тег — способ сгруппировать камеры и единица выдачи прав. Права оператору выдаются не на отдельные камеры, а на тег: «оператор смены видит тег „Периметр“». Идентичность тега — это его UUID, поэтому переименование бесплатно и ничего не разрывает.
Мозаика — сохранённая раскладка камер (видеостена): сетка столбцы × строки и упорядоченный
список ячеек. Ячейка — это либо конкретная камера, либо тег, который автоматически разворачивается
в свои камеры. Поэтому мозаика, собранная из тегов, сама подхватывает новые камеры, как только им
проставят нужный тег.
Шаблон камеры — снимок настроек (профили, DVR, размещение, теги, заметки), который подставляется в форму при создании камеры. Шаблон никогда не меняет уже созданные камеры: правка шаблона влияет только на следующие создания.
Сохранённый отчёт — аналитический вопрос (мера, группировка, фильтры) с периодом по умолчанию, сохранённый под именем. Отчёты используются как источник данных для виджетов дашбордов.
Не путайте шаблон камеры (/api/v1/camera-templates) с шаблоном события
(/api/v1/templates): первый описывает настройки устройства, второй — оформление и индексацию
событий. Шаблоны событий описаны на странице
События и аналитика.
Теги#
Тег — единица группировки камер и выдачи прав. Полный справочник эндпоинтов тегов находится на странице Организации и пользователи вместе с грантами, чтобы права и их носители были описаны в одном месте. Здесь — только карта маршрутов, чтобы не искать:
| Метод и путь | Назначение | Доступ |
|---|---|---|
GET /api/v1/tags |
список тегов организации | администратор |
POST /api/v1/tags |
создать тег | администратор |
PATCH /api/v1/tags/{id} |
переименовать, сменить вид, перенести в другую организацию | администратор (перенос — только суперадмин) |
DELETE /api/v1/tags/{id} |
удалить тег | администратор |
Что важно помнить, работая с тегами из мозаик и шаблонов камер:
- Виды тегов (
plain,site,custom) различаются только значком в интерфейсе; поведение одинаковое. - Жёсткий потолок — 1024 тега на организацию; организация может задать себе меньший
max_tags. - Переименование не трогает ни гранты, ни ссылки из мозаик и шаблонов: ссылаются на UUID.
- Удаление тега каскадное и необратимое: камеры теряют тег, а гранты, выданные через этот тег,
удаляются — операторы, у которых доступ был только по нему, молча теряют доступ. Перенос тега в
другую организацию, в отличие от удаления, блокируется, пока на тег кто-то ссылается
(
409 tag_org_move_referenced).
Мозаики#
Мозаика — сохранённая видеостена. Чтение доступно любому вошедшему (оператор смотрит стены), создание и правка — только администратору. Оператор видит мозаику лишь тогда, когда его гранты покрывают хотя бы одну её ячейку.
Позиция ячейки клиентом не задаётся: порядок элементов в массиве items и есть порядок на экране.
GET /api/v1/mosaics#
Любой вошедший — оператор видит только мозаики со своими камерами.
Назначение. Список мозаик, доступных вызывающему.
Параметры запроса
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
org |
uuid | своя организация | сужение для суперадмина |
after |
uuid | — | курсор: next из предыдущей страницы |
limit |
целое | 500 |
диапазон 1..500 |
q |
строка | — | подстрока имени, до 128 символов |
Пример запроса
curl -sS -G "$BASE/api/v1/mosaics" \ -H "Authorization: Bearer $TOKEN" \ --data-urlencode 'q=периметр' \ --data-urlencode 'limit=100'
Пример ответа
{ "rows": [ { "id": "<UUID>", "org_id": "<UUID>", "name": "Периметр 3×3", "grid_cols": 3, "grid_rows": 3, "auto_rotate_seconds": 20, "search_filter_enabled": true, "created_by": "<UUID>", "created_at": "2026-08-01T10:00:00Z" } ], "next": null }
Ошибки
| Код | Тело | Причина |
|---|---|---|
400 |
query_too_long |
q длиннее 128 символов |
403 |
cross_org |
чужая организация в ?org |
POST /api/v1/mosaics#
Администратор
Назначение. Создать мозаику вместе с упорядоченным набором ячеек.
Тело запроса
| Поле | Тип | Обязательно | По умолчанию | Описание |
|---|---|---|---|---|
name |
строка | да | — | непустое имя |
grid_cols |
целое | да | — | число столбцов сетки |
grid_rows |
целое | да | — | число строк сетки |
auto_rotate_seconds |
целое | null | нет | null |
автолистание страниц, секунд; null — выключено |
search_filter_enabled |
bool | нет | false |
показывать оператору строку поиска по мозаике |
items |
массив | нет | [] |
до 256 элементов вида {"kind":"camera"|"tag","ref_id":"<UUID>"} |
org_id |
uuid | null | нет | своя организация | суперадмин может указать любую |
Пример запроса
curl -sS -X POST "$BASE/api/v1/mosaics" \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{ "name": "Периметр 3×3", "grid_cols": 3, "grid_rows": 3, "auto_rotate_seconds": 20, "items": [ { "kind": "tag", "ref_id": "<UUID>" }, { "kind": "camera", "ref_id": "<UUID>" } ] }'
Пример ответа — 201:
{ "id": "<UUID>", "org_id": "<UUID>", "name": "Периметр 3×3", "grid_cols": 3, "grid_rows": 3, "auto_rotate_seconds": 20, "search_filter_enabled": false, "created_by": "<UUID>", "created_at": "2026-08-18T09:40:00Z", "items": [ { "position": 0, "kind": "tag", "ref_id": "<UUID>" }, { "position": 1, "kind": "camera", "ref_id": "<UUID>" } ] }
Ошибки
| Код | Тело | Причина |
|---|---|---|
400 |
name_empty |
пустое имя |
400 |
bad_grid |
размеры сетки вне допустимых границ |
400 |
bad_auto_rotate |
период автолистания вне границ |
400 |
too_many_items |
больше 256 ячеек |
400 |
bad_item_kind |
kind не camera и не tag |
400 |
duplicate_camera_item |
одна и та же камера дважды |
400 |
bad_item_ref |
камера или тег не принадлежат целевой организации |
403 |
not_admin, cross_org |
роль или организация |
409 |
mosaic_limit |
достигнут предел 256 мозаик на организацию |
409 |
mosaic_name_exists |
имя занято |
GET /api/v1/mosaics/{id}#
Любой вошедший
Назначение. Одна мозаика с упорядоченным списком ячеек — представление конструктора.
Параметры пути. id — uuid мозаики.
curl -sS "$BASE/api/v1/mosaics/<UUID>" \ -H "Authorization: Bearer $TOKEN"
Ответ — та же структура, что у создания.
Ошибки: 404 not_found — мозаики нет либо она в другой организации (существование не
раскрывается).
Примечания. Для не-администратора список items фильтруется по его правам: оператор никогда
не получает UUID камеры или тега, к которым у него нет доступа. Администратор видит полный набор.
PATCH /api/v1/mosaics/{id}#
Администратор
Назначение. Изменить имя, сетку, автолистание, строку поиска или состав ячеек.
Параметры пути. id — uuid мозаики.
Тело запроса — все поля необязательны:
| Поле | Тип | Описание |
|---|---|---|
name |
строка | новое имя |
grid_cols, grid_rows |
целое | размеры сетки |
auto_rotate_seconds |
целое | null | различает пропуск и null: поле опущено — без изменений; явный null — выключить автолистание; число — задать период |
search_filter_enabled |
bool | строка поиска |
items |
массив | если поле передано, весь упорядоченный набор ячеек заменяется; если опущено — ячейки не трогаются |
org_id |
uuid | перенос в другую организацию — только суперадмин; обязан сопровождаться полным новым items, иначе 400 mosaic_org_move_requires_items |
# Заменить состав ячеек целиком и выключить автолистание. curl -sS -X PATCH "$BASE/api/v1/mosaics/<UUID>" \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{ "auto_rotate_seconds": null, "items": [ { "kind": "tag", "ref_id": "<UUID>" } ] }'
Ошибки: все проверки создания; 400 mosaic_org_move_requires_items; 403 cross_org;
404 not_found; 409 mosaic_limit; 409 mosaic_name_exists.
items — заменили всёitems не дополняется и не сливается. Чтобы добавить одну камеру, прочитайте мозаику, добавьте
элемент в массив и отправьте массив целиком. Пустой массив [] очистит мозаику полностью.
DELETE /api/v1/mosaics/{id}#
Администратор
Назначение. Удалить мозаику; её ячейки удаляются каскадом. Камеры и теги не затрагиваются.
Параметры пути. id — uuid мозаики. Тело запроса. Отсутствует.
curl -sS -X DELETE "$BASE/api/v1/mosaics/<UUID>" \ -H "Authorization: Bearer $TOKEN"
{ "id": "<UUID>", "deleted": true }
Ошибки: 403 cross_org; 404 not_found.
GET /api/v1/mosaics/{id}/layout#
Любой вошедший
Назначение. Разрешённая страница мозаики: теги развёрнуты в камеры, на каждую ячейку сетки приходится одна запись с готовым решением о доступе. Это источник данных для видеостены и плеера.
Параметры пути. id — uuid мозаики.
Параметры запроса
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
page |
целое | 1 |
номер страницы раскладки, нумерация с единицы |
curl -sS "$BASE/api/v1/mosaics/<UUID>/layout?page=1" \ -H "Authorization: Bearer $TOKEN"
Пример ответа
{ "id": "<UUID>", "name": "Периметр 3×3", "grid_cols": 3, "grid_rows": 3, "auto_rotate_seconds": 20, "search_filter_enabled": false, "page": 1, "total_pages": 2, "accessible_total": 11, "available_tags": ["Периметр", "Склад"], "cells": [ { "position": 0, "camera_id": "<UUID>", "name": "Въезд, столб 3", "sub_path": "cam/<UUID>/main", "accessible": true, "live": true, "has_sub": true, "media_base": "https://node.example.com", "availability": "ready", "main_on_demand": false, "sub_on_demand": true, "mosaic_transport": "mse-ws", "mosaic_profile": "sub", "mosaic_allow_switch": true, "tags": ["Периметр"], "ptz": true, "ptz_pan_tilt": true, "ptz_zoom": true, "ptz_set_preset": false, "events": true } ] }
Ошибки
| Код | Тело | Причина |
|---|---|---|
403 |
no_accessible_cells |
не-администратор, чьи права не покрывают ни одной ячейки |
404 |
not_found |
мозаики нет либо она не видна |
Примечания.
accessibleиlive— разные признаки. У зрителя с правом только на превью будетaccessible: true(постер), ноlive: falseи пустойmedia_base. Открывать сокет живого видео можно только поlive.accessible_totalсчитает доступные ячейки по всей раскладке, а не по текущей странице.- Закрытая ячейка приходит с пустыми
name,sub_path,media_base, без тегов и без признаков PTZ — о чужой камере не раскрывается ничего. availability— строка с причиной состояния ячейки:ready(можно открывать),disabled(камера выключена),node_offline(нода не активна или отключена),node_unavailable(у ноды нет пригодного адреса для браузера),preview_only(доступ только к постеру),locked(ячейка закрыта правами).- Видео идёт из браузера прямо на ноду по адресу
media_base; контрол-плейн медиапрокси не является.
Шаблоны камер#
Шаблон камеры — снимок настроек, который форма создания камеры подставляет в поля. В отличие от наследования потоков, правка шаблона никогда не изменяет и не перезапускает уже существующие камеры: меняется только то, чем заполнится следующая созданная камера.
Все эндпоинты раздела — Администратор, область действия — одна организация.
Документ шаблона#
Документ (doc) описывается строго: любой неизвестный ключ в doc, doc.profiles[] или
doc.placement отклоняется разбором JSON ещё до обработчика — ответ в этом случае приходит
обычным текстом axum, а не в конверте {"error": …}.
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
enabled |
bool | null | нет | заводить камеру включённой |
onvif_events_enabled |
bool | null | нет | принимать события камеры по ONVIF |
dvr_mode |
строка | да | none | duration | size |
dvr_value |
целое | null | нет | глубина архива: секунды либо байты. При dvr_mode: "none" должно отсутствовать, иначе — быть больше нуля |
mosaic_transport |
строка | null | нет | mse-ws | hls — транспорт для мозаик |
mosaic_profile |
строка | null | нет | main | sub — какой поток показывать в мозаике |
mosaic_allow_switch |
bool | null | нет | разрешить оператору переключать профиль |
interval_timeout_secs |
целое | null | нет | тайм-аут автозакрытия интервальных событий камеры |
notes |
строка | null | нет | заметка, до 4000 символов |
tags |
массив uuid | нет ([]) |
до 32 тегов; все должны существовать в целевой организации |
profiles |
массив объектов | нет ([]) |
до 8 элементов вида {"kind":"main"}; kind соответствует ^[a-z0-9_]{1,16}$ и уникален. Допустим только ключ kind — ни URL, ни логина, ни токена в шаблоне нет |
placement |
объект | да | размещение, см. ниже |
Объект placement:
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
node_auto |
bool | да | подобрать ноду автоматически |
node_id |
uuid | null | нет | закрепить конкретную ноду |
storage_auto |
bool | да | подобрать хранилище автоматически |
storage |
строка | null | нет | закрепить конкретное хранилище |
Правила: задано ровно одно из node_auto: true / node_id. При dvr_mode: "none" оба поля
хранилища должны отсутствовать (или быть false); при включённом архиве задано ровно одно из
storage_auto / storage.
Пустой массив profiles допустим — шаблон может описывать только политику архива и размещения, не
предписывая потоки.
Общая таблица ошибок проверки документа (одинакова для создания и изменения):
| Код | Тело | Причина |
|---|---|---|
400 |
name_invalid |
имя пустое или длиннее 120 символов |
400 |
bad_dvr_mode, dvr_value_without_dvr, dvr_value_required |
режим и глубина архива |
400 |
bad_mosaic_transport, bad_mosaic_profile |
параметры мозаики |
400 |
mosaic_sub_profile_required |
выбран профиль sub (или разрешено переключение) при непустом списке профилей без sub |
400 |
bad_interval_timeout, notes_too_long |
тайм-аут интервалов, длина заметки |
400 |
bad_profile_shape, no_main_profile |
неверный или повторяющийся kind; непустой список профилей без main |
400 |
unknown_tag |
тег не принадлежит целевой организации |
400 |
template_node_choice, unknown_node |
выбор ноды |
400 |
template_storage_without_dvr, template_storage_choice, bad_dvr_storage, dvr_storage_not_on_node |
выбор хранилища |
409 |
profile_limit, tag_limit |
больше 8 профилей, больше 32 тегов |
GET /api/v1/camera-templates#
Администратор
Назначение. Список шаблонов камер организации.
Параметры запроса
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
org |
uuid | своя организация | сужение для суперадмина |
after |
uuid | — | курсор: next из предыдущей страницы |
limit |
целое | 500 |
диапазон 1..500 |
Параметр q этим обработчиком не используется.
curl -sS "$BASE/api/v1/camera-templates?limit=100" \ -H "Authorization: Bearer $TOKEN"
{ "rows": [ { "id": "<UUID>", "org_id": "<UUID>", "name": "Уличная с архивом 30 суток", "doc": { "enabled": true, "dvr_mode": "duration", "dvr_value": 2592000, "mosaic_transport": "mse-ws", "mosaic_profile": "sub", "tags": ["<UUID>"], "profiles": [ { "kind": "main" }, { "kind": "sub" } ], "placement": { "node_auto": true, "storage_auto": true } }, "created_by": "<UUID>", "created_at": "2026-08-01T10:00:00Z", "updated_at": "2026-08-01T10:00:00Z" } ], "next": null }
Ошибки: 403 cross_org; 403 not_admin.
Примечания. Список всегда сужен ровно до одной организации. Суперадмин без ?org= получает
шаблоны своей организации, а не всех сразу — чтобы посмотреть чужие, укажите ?org=<UUID> явно.
POST /api/v1/camera-templates#
Администратор
Назначение. Создать шаблон камеры.
Тело запроса
| Поле | Тип | Обязательно | По умолчанию | Описание |
|---|---|---|---|---|
name |
строка | да | — | 1..120 символов после обрезки пробелов |
doc |
объект | да | — | документ шаблона (см. выше) |
org_id |
uuid | null | нет | своя организация | суперадмин может указать любую |
curl -sS -X POST "$BASE/api/v1/camera-templates" \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{ "name": "Уличная с архивом 30 суток", "doc": { "enabled": true, "dvr_mode": "duration", "dvr_value": 2592000, "mosaic_transport": "mse-ws", "mosaic_profile": "sub", "mosaic_allow_switch": true, "tags": ["<UUID>"], "profiles": [ { "kind": "main" }, { "kind": "sub" } ], "placement": { "node_auto": true, "storage_auto": true } } }'
Ответ — 201 со строкой шаблона.
Ошибки: общая таблица проверки документа; 403 cross_org, 403 not_admin;
409 already_exists — имя уже занято в этой организации.
GET /api/v1/camera-templates/{id}#
Администратор
Назначение. Прочитать один шаблон камеры.
Параметры пути. id — uuid шаблона.
curl -sS "$BASE/api/v1/camera-templates/<UUID>" \ -H "Authorization: Bearer $TOKEN"
Ошибки: 404 not_found; 403 cross_org.
PATCH /api/v1/camera-templates/{id}#
Администратор
Назначение. Переименовать шаблон, заменить его документ или (только суперадмин) перенести его в другую организацию.
Параметры пути. id — uuid шаблона.
Тело запроса — все поля необязательны; пропущенное поле не меняется:
| Поле | Тип | Описание |
|---|---|---|
name |
строка | 1..120 символов |
doc |
объект | замена документа целиком, с повторной проверкой |
org_id |
uuid | перенос в другую организацию — только суперадмин |
curl -sS -X PATCH "$BASE/api/v1/camera-templates/<UUID>" \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{"name":"Уличная с архивом 45 суток"}'
Ошибки: все ошибки создания; 404 not_found; 403 cross_org;
403 organization_reassignment_superadmin_only — не-суперадмин передал org_id вообще, даже
равный текущему; 409 camera_template_name_exists — имя занято в организации назначения.
Примечания.
docне сливается с текущим: отправка заменяет документ целиком. Прочитайте шаблон, измените нужные поля и отправьте полный документ обратно.- Перенос в другую организацию заново проверяет
doc.tags,placement.node_idиplacement.storageотносительно организации назначения, поэтому перенос может завершиться ошибкамиunknown_tag,unknown_node,dvr_storage_not_on_node.
DELETE /api/v1/camera-templates/{id}#
Администратор
Назначение. Удалить шаблон камеры.
Параметры пути. id — uuid шаблона. Тело запроса. Отсутствует.
curl -sS -X DELETE "$BASE/api/v1/camera-templates/<UUID>" \ -H "Authorization: Bearer $TOKEN"
{ "id": "<UUID>", "deleted": true }
Ошибки: 404 not_found; 403 cross_org.
Примечания. Шаблон — снимок, поэтому его удаление никак не влияет на камеры, созданные по нему.
Сохранённые отчёты#
Сохранённый отчёт — это аналитический вопрос (мера, группировка, фильтры — та же грамматика, что у
POST /api/v1/event-analytics/query) вместе с периодом по умолчанию, сохранённый под именем.
Отчёты подключаются к виджетам дашбордов.
Чтение — для любого вошедшего с учётом видимости, запись — для администратора. Изменение защищено
оптимистической блокировкой: в PATCH передаётся revision, прочитанная последней.
Поле definition — это period, timezone и параметры аналитического запроса. Допустимые значения
period: today, last_24h, week, last_7d, month, last_30d.
GET /api/v1/reports#
Любой вошедший — обычный пользователь видит только отчёты
с visibility: "org".
Назначение. Список сохранённых отчётов, доступных вызывающему.
Параметры запроса. Используется только org (сужение для суперадмина).
curl -sS "$BASE/api/v1/reports" \ -H "Authorization: Bearer $TOKEN"
{ "rows": [ { "id": "<UUID>", "org_id": "<UUID>", "name": "События по камерам за неделю", "description": "", "definition": { "period": "last_7d", "timezone": "Europe/Moscow", "measure": "count_events", "group_by": "camera", "bucket": "day" }, "default_presentation": { "visualization": "bar" }, "visibility": "org", "created_by": "<UUID>", "revision": 2, "created_at": "2026-08-01T10:00:00Z", "updated_at": "2026-08-14T12:00:00Z" } ] }
Ответ — простая обёртка без курсора; порядок — от недавно изменённых к старым.
Ошибки: 403 cross_org.
POST /api/v1/reports#
Администратор
Назначение. Сохранить определение отчёта.
Тело запроса
| Поле | Тип | Обязательно | По умолчанию | Описание |
|---|---|---|---|---|
name |
строка | да | — | 1..128 символов |
description |
строка | нет | "" |
до 1024 символов |
definition |
объект | да | — | period (по умолчанию today), timezone (по умолчанию UTC) и параметры аналитического запроса |
default_presentation |
объект | нет | {} |
как отрисовывать по умолчанию |
visibility |
строка | нет | org |
org — виден всем в организации; admins — только администраторам |
org_id |
uuid | null | нет | своя организация | суперадмин может указать любую |
curl -sS -X POST "$BASE/api/v1/reports" \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{ "name": "События по камерам за неделю", "definition": { "period": "last_7d", "timezone": "Europe/Moscow", "measure": "count_events", "group_by": "camera", "bucket": "day" }, "default_presentation": { "visualization": "bar" }, "visibility": "org" }'
Ответ — 201 со строкой отчёта.
Ошибки
| Код | Тело | Причина |
|---|---|---|
400 |
analytics_bad_name, analytics_bad_description |
имя, описание |
400 |
analytics_bad_definition, analytics_bad_period, analytics_bad_visibility |
определение, период, видимость |
400 |
коды проверки аналитического запроса | см. События и аналитика |
403 |
cross_org |
чужая организация |
409 |
max_reports_reached, already_exists |
квота организации, имя занято |
GET /api/v1/reports/{id}#
Любой вошедший
Назначение. Прочитать один сохранённый отчёт.
Параметры пути. id — uuid отчёта.
curl -sS "$BASE/api/v1/reports/<UUID>" \ -H "Authorization: Bearer $TOKEN"
Ошибки: 404 not_found — отчёта нет либо он вам не виден (это одна и та же ситуация).
PATCH /api/v1/reports/{id}#
Администратор
Назначение. Изменить сохранённый отчёт.
Параметры пути. id — uuid отчёта.
Тело запроса
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
revision |
целое | да | значение revision, прочитанное последним |
name |
строка | нет | новое имя |
description |
строка | нет | новое описание |
definition |
объект | нет | новое определение |
default_presentation |
объект | нет | новое представление по умолчанию |
visibility |
строка | нет | org | admins |
curl -sS -X PATCH "$BASE/api/v1/reports/<UUID>" \ -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: application/json' \ -d '{"revision":2,"visibility":"admins"}'
Ответ — 200 с обновлённой строкой; revision увеличивается.
Ошибки: все проверки создания; 409 stale_revision — отчёт изменили после вашего чтения,
перечитайте и повторите; 409 analytics_report_visibility_in_use — сужение видимости, пока дашборд
показывает отчёт более широкой аудитории; 403 cross_org; 404 not_found.
DELETE /api/v1/reports/{id}#
Администратор
Назначение. Удалить сохранённый отчёт.
Параметры пути. id — uuid отчёта. Тело запроса. Отсутствует.
curl -sS -X DELETE "$BASE/api/v1/reports/<UUID>" \ -H "Authorization: Bearer $TOKEN"
{ "id": "<UUID>", "deleted": true }
Ошибки: 409 analytics_report_in_use — на отчёт всё ещё ссылается виджет дашборда, сначала
уберите виджет; 403 cross_org; 404 not_found.