Перейти к содержанию

Пользователи

Эндпоинты для управления учётными записями пользователей (список, создание, обновление и удаление пользователей, аватары, ключи API и 2FA), группами пользователей и приглашениями.

Список пользователей

GET /users

Выводит учётные записи пользователей, отсортированные по имени пользователя. Вызывающая сторона с api.users.read видит все учётные записи; любой другой вызывающий получает список из одной строки только со своей учётной записью в том же формате с постраничной разбивкой.

Параметры

Имя Тип Обязательный Описание
page integer Нет Номер страницы для постраничной разбивки (по умолчанию: 1)
per_page integer Нет Число результатов на странице (по умолчанию: 20, максимум: 1000, оба значения задаются в конфигурации pagination плагина)
search string Нет Фильтр по свободному текстовому запросу по имени пользователя, адресу почты и полному имени.
access string Нет Фильтр по пользователям, у которых есть действующий доступ к разрешению (например, admin.login, api.super). permission принимается как псевдоним.
group string Нет Фильтр по участникам одной группы учётных записей.
filter string Нет Идентификатор активной вкладки раздела «Пользователи» (см. GET /users/filters). Вызывает onApiUserListFilter, чтобы плагин мог сузить список до постраничной разбивки. Работает и с хранилищем учётных записей Flex, и с обычным файловым. Не указывайте или используйте all для неотфильтрованного списка.

Ответ

{
    "data": [
        {
            "username": "editor",
            "email": "editor@example.com",
            "fullname": "Jane Editor",
            "title": "",
            "state": "enabled",
            "language": "",
            "content_editor": "",
            "access": { "api": { "access": true, "pages": { "read": true, "write": true } } },
            "groups": [],
            "avatar_url": null,
            "twofa_enabled": false,
            "twofa_secret": false,
            "created": "2026-09-01T10:00:00+00:00",
            "modified": "2026-09-01T10:00:00+00:00"
        }
    ],
    "meta": {
        "pagination": { "page": 1, "per_page": 20, "total": 1, "total_pages": 1 }
    },
    "links": {
        "self": "/api/v1/users?page=1&per_page=20"
    }
}

Коды ответов

Код Описание
200 Успех
401 Не авторизован

Каждая строка пользователя также содержит значения любых пользовательских полей, которые сайт добавил в схему учётной записи, и отображение extra, если плагин предоставляет для неё значения столбцов. twofa_secret — логическое значение, которое лишь сообщает, был ли сгенерирован секрет; сам секрет никогда не возвращается.


Список вкладок пользователей

GET /users/filters

Выводит вкладки фильтров, доступные для списка пользователей, вместе с политикой стартового представления. Возвращает встроенную вкладку «All Users» и любые вкладки, добавленные плагинами через событие onApiUserListFilters, с учётом разрешений вызывающей стороны. Выбор вкладки добавляет ?filter=<id> к GET /users, что вызывает onApiUserListFilter, чтобы плагин-владелец мог сузить список до постраничной разбивки.

Ответ

{
    "data": {
        "tabs": [
            { "id": "all", "plugin": "api", "label": "All Users" },
            { "id": "active", "plugin": "my-plugin", "label": "Active", "icon": "fa-bolt", "priority": 10 }
        ],
        "defaultFilter": "all",
        "showAll": true
    }
}

Коды ответов

Код Описание
200 Успех
401 Не авторизован
403 Запрещено — требуется api.users.read

data в ответе — объект с тремя ключами:

  • tabs — упорядоченный ряд вкладок. Каждая вкладка содержит id (передаётся обратно как ?filter=<id>; all зарезервирован для встроенной вкладки), slug плагина plugin и простой текстовый label. Вкладки также могут содержать icon, priority (большее значение сортирует раньше) и badge / badgeEndpoint для счётчика в реальном времени.
  • defaultFilter — вкладка, которую клиент должен открыть, если в URL нет filter. По умолчанию all; плагин может предложить другую вкладку через $event['defaultFilter'] (учитывается только если она соответствует вкладке, видимой вызывающей стороне, иначе используется первая вкладка).
  • showAll — присутствует ли встроенная вкладка «All Users». По умолчанию true; плагин может установить $event['showAll'] = false, чтобы убрать её, когда показ всех учётных записей не является полезным (или безопасным) стартовым представлением. «All Users» убирается только после того, как плагин добавил хотя бы одну разрешённую вкладку, поэтому ряд никогда не остаётся пустым.

Фильтр плагина может только сужать список: он выполняется после search, а фильтры access и group и постраничная разбивка применяются основным эндпоинтом после него, поэтому вкладка никогда не может расширить видимость или изменить структуру ответа. Вкладки работают с обоими хранилищами учётных записей. При учётных записях Flex collection события — это коллекция Flex; при обычных файловых учётных записях — ArrayCollection пользователей с ключами по имени пользователя, и из возвращённого плагином сохраняются только учётные записи, уже присутствующие в списке. О контрактах onApiUserListFilters и onApiUserListFilter см. страницу События API.


Список столбцов пользователей

GET /users/columns

Выводит дополнительные столбцы, которые плагины добавили в список пользователей через событие onApiUserListColumns, с учётом разрешений вызывающей стороны. Каждый столбец объявляет, как помечается и форматируется значение, принадлежащее плагину; сами значения передаются в отображении extra каждого пользователя в GET /users и заполняются через onApiUserListColumnData только для текущей страницы.

Ответ

{
    "data": {
        "columns": [
            {
                "id": "my-plugin-valid-till",
                "plugin": "my-plugin",
                "label": "Valid until",
                "field": "subscription.valid_till",
                "formatter": "datetime",
                "sortable": false,
                "priority": 50
            }
        ]
    }
}

Коды ответов

Код Описание
200 Успех
401 Не авторизован
403 Запрещено — требуется api.users.read

data.columns в ответе — упорядоченный список столбцов, объявленных плагинами. Каждый столбец содержит:

  • id — уникальный идентификатор столбца.
  • plugin — slug плагина-владельца.
  • label — простой текстовый заголовок столбца.
  • field — ключ, который нужно читать из отображения extra каждого пользователя в GET /users.
  • formatter — одно из значений text, link, date, datetime, boolean, number, badge. Сервер проверяет его по белому списку и подставляет text для всего остального; рендеринг выполняет клиент, поэтому по сети не передаются ни разметка, ни рендерер.
  • sortable — необязательно; предлагает ли столбец клиентскую сортировку текущей страницы.
  • priority — необязательно; большее значение сортирует раньше.

Столбцы принадлежат плагинам, но безопасны по построению: значения в отображении extra каждого пользователя — только скаляры, проверка authorize повторно выполняется на сервере (и удаляется из этого ответа), а событие данных изолировано, поэтому сбойный плагин приводит лишь к отсутствию значений, а не к поломке списка. Значения столбцов вычисляются только для учётных записей текущей страницы — никогда для всех учётных записей.

О контрактах onApiUserListColumns и onApiUserListColumnData см. страницу События API.


Получение пользователя

GET /users/{username}

Возвращает сведения о пользователе. Для чтения собственной учётной записи нужно только api.access; для чтения чужой — api.users.read.

Параметры

Имя Тип Обязательный Описание
username string Да Имя пользователя, которое нужно получить

Ответ

{
    "data": {
        "username": "editor",
        "email": "editor@example.com",
        "fullname": "Jane Editor",
        "title": "",
        "state": "enabled",
        "language": "",
        "content_editor": "",
        "access": { "api": { "access": true, "pages": { "read": true, "write": true } } },
        "groups": [],
        "avatar_url": null,
        "twofa_enabled": false,
        "twofa_secret": false,
        "created": "2026-09-01T10:00:00+00:00",
        "modified": "2026-09-01T10:00:00+00:00",
        "twofa_global_enabled": true
    }
}

Коды ответов

Код Описание
200 Успех
401 Не авторизован
403 Запрещено (чтение чужой учётной записи без api.users.read)
404 Пользователь не найден

Ответ содержит заголовок ETag; отправьте его обратно как If-Match в Обновлении пользователя, чтобы не перезаписать параллельное изменение. twofa_secret лишь сообщает, был ли сгенерирован секрет, а twofa_global_enabled — установлена ли поддержка 2FA в плагине Login, чтобы клиент знал, предлагать ли настройку 2FA. Пользовательские поля, добавленные сайтом в схему учётной записи, также включаются.


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

POST /users

Создаёт новую учётную запись пользователя. Требуется api.users.write.

Параметры

Имя Тип Обязательный Описание
username string Да Уникальное имя пользователя, от 3 до 64 символов. Не может начинаться с точки или содержать .., а также не может содержать / ? * : ; { } или перевод строки.
password string Да Пароль пользователя. Должен соответствовать system.pwd_regex сайта, если он задан, и содержать не менее 8 символов, если не задан.
email string Да Адрес электронной почты пользователя
fullname string Нет Полное отображаемое имя
title string Нет Титул, отображаемый вместе с учётной записью
state string Нет Состояние учётной записи: enabled (по умолчанию) или disabled
access object Нет Объект доступа с разрешениями. Только суперадминистратор может выдать admin.super или api.super.
groups array Нет Имена групп. Применяется только если вызывающая сторона — суперадминистратор; в остальных случаях игнорируется.

Запрос

{"username": "editor", "password": "SecurePass123!", "email": "editor@example.com", "fullname": "Jane Editor"}

Ответ

{"data": {"username": "editor", "email": "editor@example.com", "fullname": "Jane Editor", "title": "", "state": "enabled", "language": "", "content_editor": "", "access": {}, "groups": [], "avatar_url": null, "twofa_enabled": false, "twofa_secret": false, "created": "2026-09-21T10:00:00+00:00", "modified": "2026-09-21T10:00:00+00:00"}}

Коды ответов

Код Описание
201 Пользователь создан. Заголовок Location указывает на нового пользователя.
401 Не авторизован
403 Запрещено (нет api.users.write или вызывающая сторона без прав суперпользователя выдаёт супердоступ)
409 Имя пользователя уже существует
422 Ошибка валидации (отсутствует поле, неверное имя пользователя, пароль не соответствует политике или поле не проходит валидацию по схеме учётной записи)

Любые пользовательские поля, добавленные сайтом в схему учётной записи (user/blueprints/user/account.yaml), также можно передать в теле запроса — они валидируются по этой схеме.


Обновление пользователя

PATCH /users/{username}

Обновляет учётную запись пользователя. Меняются только переданные поля. Собственную учётную запись можно обновлять с api.access; для обновления чужой нужен api.users.write.

Параметры

Имя Тип Обязательный Описание
username string Да Имя пользователя, которое нужно обновить (параметр пути)
email string Нет Новый адрес электронной почты
fullname string Нет Новое полное отображаемое имя
title string Нет Новый титул
language string Нет Предпочитаемый язык админки
content_editor string Нет Предпочитаемый редактор контента
state string Нет Новое состояние учётной записи (enabled или disabled). Требуется api.users.write.
access object Нет Новый объект доступа с разрешениями. Требуется api.users.write; только суперадминистратор может выдать супердоступ.
groups array Нет Новые имена групп. Только для суперадминистраторов.
password string Нет Новый пароль. Должен соответствовать system.pwd_regex, если он задан, и содержать не менее 8 символов, если не задан.

Запрос

{"fullname": "Jane Q. Editor", "password": "N3wSecurePass!"}

Ответ

{"data": {"username": "editor", "email": "editor@example.com", "fullname": "Jane Q. Editor", "title": "", "state": "enabled", "language": "", "content_editor": "", "access": {}, "groups": [], "avatar_url": null, "twofa_enabled": false, "twofa_secret": false, "created": "2026-09-01T10:00:00+00:00", "modified": "2026-09-21T10:00:00+00:00", "twofa_global_enabled": true}}

Коды ответов

Код Описание
200 Пользователь обновлён
401 Не авторизован
403 Запрещено (нет api.users.write, отправка state/access/groups без нужного разрешения, либо вызывающая сторона без прав суперпользователя редактирует суперадминистратора)
404 Пользователь не найден
409 Конфликт (несовпадение ETag)
422 Ошибка валидации (пустое тело, пароль не соответствует политике или поле не проходит валидацию по схеме учётной записи)

Поддерживает оптимистичный контроль конкурентного доступа через заголовок If-Match. Передавайте ETag из последнего GET-запроса, чтобы не перезаписать параллельные изменения.

twofa_enabled и twofa_secret здесь игнорируются, поэтому клиент может без ошибки отправить обратно весь объект пользователя. Двухфакторная аутентификация меняется только через эндпоинты Включение 2FA и Отключение 2FA, которые проверяют код при изменении собственной учётной записи.

Смена пароля или установка state в disabled делает недействительным каждый уже выданный токен API для этой учётной записи. Пользовательские поля, добавленные сайтом в схему учётной записи, также можно передавать.


Удаление пользователя

DELETE /users/{username}

Удаляет учётную запись пользователя. Требуется api.users.write.

Параметры

Имя Тип Обязательный Описание
username string Да Имя пользователя, которого нужно удалить

Коды ответов

Код Описание
204 Пользователь удалён
401 Не авторизован
403 Запрещено (нет api.users.write, удаление собственной учётной записи или вызывающая сторона без прав суперпользователя удаляет суперадминистратора)
404 Пользователь не найден

Загрузка аватара

POST /users/{username}/avatar

Загружает пользовательское изображение аватара для пользователя. Отправляется как multipart/form-data. Для собственного аватара дополнительные разрешения не нужны; для чужого нужен api.users.write.

Параметры

Имя Тип Обязательный Описание
username string Да Имя пользователя, для которого загружается аватар
avatar file Да Файл изображения (PNG, JPEG или WebP, до 8 МБ). Поле также может называться file. Проверяется содержимое файла, а не заявленный тип.

Ответ

{"data": {"username": "admin", "email": "admin@example.com", "fullname": "Site Admin", "title": "", "state": "enabled", "language": "", "content_editor": "", "access": {"admin": {"super": true}}, "groups": [], "avatar_url": "/api/v1/thumbnails/3f2a9c1b.jpg", "twofa_enabled": false, "twofa_secret": false, "created": "2026-09-01T10:00:00+00:00", "modified": "2026-09-01T10:00:00+00:00"}}

Коды ответов

Код Описание
201 Аватар загружен; тело ответа — обновлённый пользователь
401 Не авторизован
403 Запрещено (нет api.users.write или вызывающая сторона без прав суперпользователя меняет суперадминистратора)
404 Пользователь не найден
422 Ошибка валидации (нет файла, файл слишком большой или не является изображением PNG, JPEG либо WebP)

Удаление аватара

DELETE /users/{username}/avatar

Удаляет пользовательский аватар пользователя. Для собственного аватара дополнительные разрешения не нужны; для чужого нужен api.users.write.

Параметры

Имя Тип Обязательный Описание
username string Да Имя пользователя, для которого удаляется аватар

Ответ

{"data": {"username": "admin", "email": "admin@example.com", "fullname": "Site Admin", "title": "", "state": "enabled", "language": "", "content_editor": "", "access": {"admin": {"super": true}}, "groups": [], "avatar_url": null, "twofa_enabled": false, "twofa_secret": false, "created": "2026-09-01T10:00:00+00:00", "modified": "2026-09-01T10:00:00+00:00"}}

Коды ответов

Код Описание
200 Аватар удалён; тело ответа — обновлённый пользователь
401 Не авторизован
403 Запрещено (нет api.users.write или вызывающая сторона без прав суперпользователя меняет суперадминистратора)
404 Пользователь не найден

Генерация секрета 2FA

POST /users/{username}/2fa

Создаёт или пересоздаёт секрет двухфакторной аутентификации TOTP и возвращает data URI QR-кода. Генерация секрета отключает 2FA, пока код не будет подтверждён через «Включение 2FA». Для собственной учётной записи нужно api.access; для чужой — api.users.write.

Параметры

Имя Тип Обязательный Описание
username string Да Имя пользователя, для которого создаётся 2FA

Ответ

{"data": {"secret": "JBSW Y3DP EHPK 3PXP", "qr_code": "data:image/png;base64,..."}}

Коды ответов

Код Описание
200 Секрет создан
401 Не авторизован
403 Запрещено. Разрешения проверяются до загрузки учётной записи, поэтому вызывающая сторона без них получает 403 независимо от того, существует ли имя пользователя.
404 Пользователь не найден
500 Плагин Login с поддержкой 2FA не установлен

Список ключей API

GET /users/{username}/api-keys

Выводит все ключи API пользователя. Секреты ключей не возвращаются. Для собственных ключей нужно api.access; для чужих — api.users.read.

Параметры

Имя Тип Обязательный Описание
username string Да Имя пользователя, для которого нужно вывести ключи API

Ответ

{"data": [{"id": "9f86d081884c7d65", "name": "CI Deploy Key", "prefix": "grav_1a2b3c4...", "scopes": [], "active": true, "created": 1710000000, "last_used": null, "expires": 1717776000}]}

Коды ответов

Код Описание
200 Успех
401 Не авторизован
403 Запрещено
404 Пользователь не найден

created, last_used и expires — временные метки Unix; expires равен null для ключа без срока действия.


Создание ключа API

POST /users/{username}/api-keys

Создаёт новый ключ API для пользователя. Необработанный ключ возвращается в ответе только один раз. Для собственных ключей нужно api.access; для чужих — api.users.write.

Параметры

Имя Тип Обязательный Описание
username string Да Имя пользователя, для которого создаётся ключ API
name string Нет Описательное имя ключа API (по умолчанию: API Key)
scopes array Нет Список областей действия разрешений для ключа. Пустой список означает, что ключ несёт полный доступ учётной записи.
expiry_days integer Нет Число дней до истечения срока действия ключа. Не указывайте или задайте null, чтобы ключ не истекал.

Запрос

{"name": "CI Deploy Key", "scopes": ["api.pages.read"], "expiry_days": 90}

Ответ

{"data": {"id": "9f86d081884c7d65", "name": "CI Deploy Key", "prefix": "grav_1a2b3c4...", "scopes": ["api.pages.read"], "active": true, "created": 1710000000, "last_used": null, "expires": 1717776000, "api_key": "grav_1a2b3c4d5e6f..."}}

Коды ответов

Код Описание
201 Ключ API создан
401 Не авторизован
403 Запрещено (нет разрешения, вызывающая сторона без прав суперпользователя создаёт ключ для суперадминистратора, либо ключ с областями действия запрашивает область за пределами собственных)
404 Пользователь не найден

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


Отзыв ключа API

DELETE /users/{username}/api-keys/{keyId}

Отзывает и удаляет ключ API. Для собственных ключей нужно api.access; для чужих — api.users.write.

Параметры

Имя Тип Обязательный Описание
username string Да Имя пользователя, которому принадлежит ключ API
keyId string Да Идентификатор отзываемого ключа API

Коды ответов

Код Описание
204 Ключ API отозван
401 Не авторизован
403 Запрещено
404 Пользователь или ключ API не найдены

Включение 2FA

POST /users/{username}/2fa/enable

Проверяет код TOTP по ранее сгенерированному секрету и помечает 2FA как включённую для учётной записи. Включить 2FA в собственной учётной записи может только её владелец (не администраторы), и владельцу нужно api.access. Вызывает onApiUser2faEnabled.

Параметры

Имя Тип Обязательный Описание
username string Да Имя пользователя (параметр пути).
code string Да Текущий 6-значный код TOTP из приложения-аутентификатора.

Запрос

{"code": "123456"}

Ответ

{"data": {"twofa_enabled": true}}

Коды ответов

Код Описание
200 2FA включена.
401 Не авторизован.
403 Вызывающая сторона не является владельцем учётной записи или не имеет api.access. Владение проверяется до загрузки учётной записи, поэтому это не раскрывает, существует ли имя пользователя.
404 Пользователь не найден.
422 Отсутствует код, неверный код или секрет 2FA ещё не сгенерирован (сначала вызовите POST /users/{username}/2fa).
500 Плагин Login с поддержкой 2FA не установлен.

Отключение 2FA

POST /users/{username}/2fa/disable

Отключает 2FA для учётной записи. Самостоятельное отключение требует api.access и действующего текущего кода TOTP, что не даёт украденной сессии отключить 2FA в одиночку. Администраторы с api.users.write (или суперадминистраторы) могут принудительно отключить 2FA без кода для восстановления при потере устройства; только суперадминистратор может сделать это для учётной записи суперадминистратора. Оба пути очищают twofa_secret. Вызывает onApiUser2faDisabled с флагом forced_by_admin.

Параметры

Имя Тип Обязательный Описание
username string Да Имя пользователя (параметр пути).
code string Нет Текущий код TOTP. Требуется для самостоятельного отключения без api.users.write; игнорируется при принудительном отключении администратором.

Запрос

{"code": "123456"}

Ответ

{"data": {"twofa_enabled": false}}

Коды ответов

Код Описание
200 2FA отключена.
401 Не авторизован.
403 Вызывающая сторона не является ни владельцем учётной записи, ни обладателем api.users.write, либо администратор без прав суперпользователя нацелен на суперадминистратора. Проверяется до загрузки учётной записи, поэтому это не раскрывает, существует ли имя пользователя.
404 Пользователь не найден.
422 Отсутствует или неверен код (только для самостоятельного отключения).
500 Плагин Login с поддержкой 2FA не установлен.

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

GET /users/row-actions

Выводит кнопки действий для отдельного пользователя, которые плагины добавили в список пользователей через событие onApiUserListRowActions, с фильтрацией по разрешениям вызывающей стороны. Каждое действие — это описание без рендерера, которое Admin2 отображает в ячейке «Actions» строки пользователя; вызов действия отправляет POST /users/{username}/row-action.

Ответ

{
    "data": {
        "actions": [
            {
                "id": "impersonate-user",
                "plugin": "impersonate",
                "label": "Impersonate",
                "icon": "fa-user-secret",
                "action": "start",
                "confirm": "Impersonate this user?",
                "priority": 80
            }
        ]
    }
}

Коды ответов

Код Описание
200 Успех
401 Не авторизован
403 Запрещено — требуется api.users.read

data.actions в ответе — упорядоченный список действий в строке, объявленных плагинами. Каждое действие содержит:

  • id — уникальный идентификатор действия; ключ, отправляемый на эндпоинт выполнения.
  • plugin — slug плагина-владельца.
  • label — простой текстовый текст кнопки (он же её доступное имя и подсказка).
  • icon — необязательный класс иконки Font Awesome.
  • action — необязательный глагол, передаваемый обратно обработчику; для клиента непрозрачен.
  • confirm — необязательный запрос, показываемый в диалоге подтверждения перед выполнением действия.
  • priority — необязательно; большее значение сортирует раньше.

Действия принадлежат плагинам, но безопасны по построению: по сети не передаются ни разметка, ни рендерер, список ограничен по размеру, а проверка authorize повторно выполняется на сервере и удаляется из этого ответа. authorize в объявлении определяет только то, какие кнопки отображаются, — это не граница безопасности; эндпоинт выполнения заново проверяет разрешения независимо.

О контрактах onApiUserListRowActions и onApiUserListRowAction см. страницу События API.


Выполнение действия в строке пользователя

POST /users/{username}/row-action

Выполняет объявленное плагином действие строки списка пользователей для одной учётной записи. API заново проверяет authorize объявленного действия для вызывающей стороны, затем вызывает onApiUserListRowAction с именем целевого пользователя; обработчик плагина заново проверяет разрешения для этой цели и возвращает результат. Любой URL перенаправления в результате проверяется на безопасную цель того же источника, прежде чем дойти до клиента.

Параметры

Имя Тип Обязательный Описание
username Да Целевая учётная запись, для которой выполняется действие.
id string Да Идентификатор объявленного действия в строке (из GET /users/row-actions).

Запрос

{
    "id": "impersonate-user"
}

Ответ

{
    "data": {
        "status": "success",
        "message": "Impersonating alice",
        "url": "/admin/impersonate/alice"
    }
}

Коды ответов

Код Описание
200 Действие выполнено; тело содержит результат обработчика.
401 Не авторизован
403 Запрещено — у вызывающей стороны нет api.users.read, вызывающая сторона без прав суперпользователя нацелена на суперадминистратора, либо обработчик отклонил эту цель
404 Неизвестное имя пользователя или идентификатор действия, на который у вызывающей стороны нет разрешения
422 В теле нет id действия

Отправьте id объявленного действия в строке. API подтверждает, что вызывающая сторона может перечислять пользователей (api.users.read), загружает целевую учётную запись (только суперадминистратор может действовать в отношении учётной записи суперадминистратора) и заново проверяет собственный authorize действия — неизвестный или неразрешённый идентификатор даёт неотличимый 404, поэтому ничего не утекает. Затем вызывается onApiUserListRowAction с полученным username; обработчик должен проверить $event['plugin'], заново проверить разрешения для цели и установить $event['result'].

Результат приводится к фиксированной форме:

  • status — success или error; определяет, покажет ли Admin2 уведомление об успехе или об ошибке.
  • message — необязательный текст, показываемый во всплывающем уведомлении (с ограничением длины).
  • url — необязательное перенаправление. Проверку проходит только путь относительно корня (не протокольно-относительная форма //host) или абсолютный URL того же источника; схема javascript:/data: или URL другого источника отбрасывается. Admin2 открывает прошедший URL в новой вкладке с noopener.

Обработчик, выбросивший исключение, приводит к 200 со status: error и общим сообщением, а не к поломке списка пользователей; выброшенное ForbiddenException передаётся как 403.

О контракте onApiUserListRowAction см. страницу События API.


Список групп

GET /groups

Выводит группы пользователей, отсортированные по имени группы. Требуется api.users.read.

Параметры

Имя Тип Обязательный Описание
page integer Нет Номер страницы для постраничной разбивки (по умолчанию: 1)
per_page integer Нет Число результатов на странице (по умолчанию: 20, максимум: 1000)
search string Нет Фильтр по свободному текстовому запросу по имени группы, читаемому имени и описанию.

Ответ

{
    "data": [
        {
            "groupname": "editors",
            "readableName": "Editors",
            "description": "Can edit site content",
            "icon": "users",
            "enabled": true,
            "access": { "api": { "access": true, "pages": { "read": true, "write": true } } }
        }
    ],
    "meta": {
        "pagination": { "page": 1, "per_page": 20, "total": 1, "total_pages": 1 }
    },
    "links": {
        "self": "/api/v1/groups?page=1&per_page=20"
    }
}

Коды ответов

Код Описание
200 Успех
401 Не авторизован
403 Запрещено (нет api.users.read)

Группы всегда читаются из user/config/groups.yaml и сохраняются в него. Группы, существующие только в наложенном окружении, не выводятся, поэтому любую группу, возвращённую этим эндпоинтом, можно также отредактировать или удалить.


Получение группы

GET /groups/{name}

Возвращает одну группу пользователей. Требуется api.users.read.

Параметры

Имя Тип Обязательный Описание
name string Да Имя группы (параметр пути)

Ответ

{"data": {"groupname": "editors", "readableName": "Editors", "description": "Can edit site content", "icon": "users", "enabled": true, "access": {"api": {"access": true, "pages": {"read": true, "write": true}}}}}

Коды ответов

Код Описание
200 Успех
401 Не авторизован
403 Запрещено (нет api.users.read)
404 Группа не найдена

Ответ содержит заголовок ETag; отправьте его обратно как If-Match в Обновлении группы, чтобы не перезаписать параллельное изменение.


Создание группы

POST /groups

Создаёт группу пользователей в user/config/groups.yaml. Требуется суперадминистратор, так как членство в группе может давать любые разрешения. Вызывает onApiGroupCreated.

Параметры

Имя Тип Обязательный Описание
groupname string Да Имя группы: от 1 до 200 букв, цифр, дефисов или подчёркиваний. Это ключ хранения, и позже его нельзя изменить.
readableName string Нет Отображаемое имя
description string Нет Описание
icon string Нет Имя иконки
enabled boolean Нет Активна ли группа (по умолчанию: true)
access object Нет Объект доступа с разрешениями, выдаваемыми участникам

Запрос

{"groupname": "editors", "readableName": "Editors", "description": "Can edit site content", "access": {"api": {"access": true, "pages": {"read": true, "write": true}}}}

Ответ

{"data": {"groupname": "editors", "readableName": "Editors", "description": "Can edit site content", "icon": "", "enabled": true, "access": {"api": {"access": true, "pages": {"read": true, "write": true}}}}}

Коды ответов

Код Описание
201 Группа создана. Заголовок Location указывает на новую группу.
401 Не авторизован
403 Запрещено (не суперадминистратор)
409 Группа с таким именем уже существует
422 Ошибка валидации (отсутствует или неверен groupname)

Обновление группы

PATCH /groups/{name}

Обновляет группу пользователей. Меняются только переданные поля; access заменяется целиком. Требуется суперадминистратор. Вызывает onApiGroupUpdated.

Параметры

Имя Тип Обязательный Описание
name string Да Имя группы (параметр пути). Группы нельзя переименовать.
readableName string Нет Отображаемое имя
description string Нет Описание
icon string Нет Имя иконки
enabled boolean Нет Активна ли группа
access object Нет Объект доступа с разрешениями. Заменяет существующий.

Запрос

{"description": "Can edit and publish site content", "enabled": true}

Ответ

{"data": {"groupname": "editors", "readableName": "Editors", "description": "Can edit and publish site content", "icon": "users", "enabled": true, "access": {"api": {"access": true, "pages": {"read": true, "write": true}}}}}

Коды ответов

Код Описание
200 Группа обновлена
401 Не авторизован
403 Запрещено (не суперадминистратор)
404 Группа не найдена
409 Конфликт (несовпадение ETag)
422 Ошибка валидации (пустое тело)

Поддерживает оптимистичный контроль конкурентного доступа через заголовок If-Match. Передавайте ETag из последнего GET-запроса, чтобы не перезаписать параллельные изменения.


Удаление группы

DELETE /groups/{name}

Удаляет группу пользователей из user/config/groups.yaml. Требуется суперадминистратор. Вызывает onApiGroupDeleted.

Параметры

Имя Тип Обязательный Описание
name string Yes Имя группы (параметр пути)

Коды ответов

Код Описание
204 Группа удалена
401 Не авторизован
403 Запрещено (не суперадминистратор)
404 Группа не найдена

Учётные записи, у которых удалённая группа указана в groups, сохраняют эту запись; она просто больше ничего не даёт.


Список приглашений

GET /invitations

Выводит ожидающие приглашения, сначала новые. Просроченные приглашения предварительно удаляются. Требуется api.users.write, так как каждая запись содержит токен, по которому принимается приглашение.

Ответ

{"data": {"invitations": [{"token": "b7c1e0f4a9d2...", "email": "new.editor@example.com", "fullname": "New Editor", "groups": [], "created": 1758448800, "created_by": "admin", "created_by_name": "Site Admin", "expires": 1759053600, "expired": false}]}}

Коды ответов

Код Описание
200 Успех
401 Не авторизован
403 Запрещено (нет api.users.write)

created и expires — временные метки Unix. Доступ, который даёт приглашение, в список не включается.


Создание приглашения

POST /invitations

Создаёт приглашение с заранее заданным доступом и отправляет его по почте, если настроен плагин Email. Получатель сам выбирает имя пользователя и пароль при принятии и получает ровно тот доступ, который задан здесь. Требуется api.users.write.

Параметры

Имя Тип Обязательный Описание
email string Да Адрес, на который отправляется приглашение. Любое ожидающее приглашение для того же адреса заменяется.
fullname string Нет Имя, подставляемое в форму принятия
access object Нет Объект доступа с разрешениями, которые получает новая учётная запись. admin.super и api.super удаляются, если вызывающая сторона не суперадминистратор.
groups array Нет Группы, в которые вступает новая учётная запись. Применяется только если вызывающая сторона — суперадминистратор; в остальных случаях игнорируется.
expiration integer Нет Секунды до истечения срока действия приглашения. По умолчанию plugins.api.invitations.expiration (7 дней). Значения меньше 300 заменяются значением по умолчанию, а максимум — 30 дней (2592000).
message string Нет Личная заметка, включаемая в письмо
admin_base_url string Нет Базовый URL админки для построения ссылки-приглашения, если админка обслуживается не по адресу по умолчанию

Запрос

{"email": "new.editor@example.com", "fullname": "New Editor", "access": {"api": {"access": true, "pages": {"read": true}}}, "expiration": 604800}

Ответ

{"data": {"token": "b7c1e0f4a9d2...", "email": "new.editor@example.com", "fullname": "New Editor", "groups": [], "created": 1758448800, "created_by": "admin", "created_by_name": "Site Admin", "expires": 1759053600, "expired": false, "link": "https://example.com/admin/invite?token=b7c1e0f4a9d2...", "email_sent": false, "warning": "Email is not configured, so no invitation email was sent. Share the link manually."}}

Коды ответов

Код Описание
201 Приглашение создано. Заголовок Location указывает на /auth/invite/{token} — публичный эндпоинт, который проверяет и принимает приглашение.
401 Не авторизован
403 Запрещено (нет api.users.write)
409 Пользователь с таким адресом почты уже существует
422 Ошибка валидации (отсутствует или неверен адрес почты)

Приглашение создаётся, даже если письмо не удаётся отправить. В этом случае email_sent равен false, а warning объясняет причину, чтобы ссылку можно было передать вручную. Получатель открывает ссылку, а форма принятия использует GET /auth/invite/{token} и POST /auth/invite/{token} для создания учётной записи.


Отзыв приглашения

DELETE /invitations/{token}

Отзывает ожидающее приглашение, чтобы его ссылка перестала работать. Требуется api.users.write.

Параметры

Имя Тип Обязательный Описание
token string Да Токен приглашения (параметр пути)

Коды ответов

Код Описание
204 Приглашение отозвано
401 Не авторизован
403 Запрещено (нет api.users.write)
404 Приглашение не найдено

Повторная отправка приглашения

POST /invitations/{token}/resend

Повторно отправляет письмо для ожидающего приглашения. Токен и срок действия остаются прежними. Требуется api.users.write.

Параметры

Имя Тип Обязательный Описание
token string Да Токен приглашения (параметр пути)
message string Нет Личная заметка, включаемая в письмо
admin_base_url string Нет Базовый URL админки для построения ссылки-приглашения

Запрос

{"message": "Reminder: your invitation is waiting."}

Ответ

{"data": {"token": "b7c1e0f4a9d2...", "email": "new.editor@example.com", "fullname": "New Editor", "groups": [], "created": 1758448800, "created_by": "admin", "created_by_name": "Site Admin", "expires": 1759053600, "expired": false, "link": "https://example.com/admin/invite?token=b7c1e0f4a9d2...", "email_sent": true}}

Коды ответов

Код Описание
200 Письмо отправлено
401 Не авторизован
403 Запрещено (нет api.users.write)
404 Приглашение не найдено или просрочено
422 Почта не настроена