Обзор

Обновлено: Aug 31, 2026Раздел: Интеграции

Изображения и объектное хранилище

Полная справка по API: https://api.mailoo.app/docs/v1

Mailoo хранит пользовательские изображения в S3-совместимом объектном хранилище (AWS S3, MinIO и др.). Весь доступ проходит через API Mailoo; интеграторы и браузеры никогда не получают учётных данных S3 или внутренних ключей объектов.

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

Обзор

  • Пространство имён: Каждый пользователь панели управления получает выделенный префикс ключей users/{userId}/ в общем бакете (userId --- внутренний id пользователя Mailoo из базы данных, CUID).
  • Публичный идентификатор: Клиенты используют id медиа (CUID), возвращаемый API. S3-ключи --- только внутренние.
  • Инициализация: API создаёт внутренний маркерный объект под этим префиксом при первой аутентифицированной активности (идемпотентно). Создание логируется на стороне сервера.
  • Удаление: При удалении учётной записи пользователя через API объекты в users/{userId}/ удаляются из хранилища в рамках этого процесса. Удаление проекта / интеграции / статьи ставит в очередь фоновую очистку S3 для связанных ключей медиа.
  • Загрузка / удаление / производные: Потоки панели управления с Bearer-авторизацией (через вашу сессию / BFF). Не передавайте S3-ключи или учётные данные бакета браузерам или сторонним сайтам.
  • Оригиналы vs ресурсы статей: Загрузка допускает более крупные оригиналы (до 25 МиБ до обработки); POST /images/derive создаёт масштабированные / перекодированные копии с той же областью, что и исходный файл.
  • Валидация: Тип файла проверяется по магическим байтам; EXIF-ориентация применяется и метаданные удаляются на стороне сервера. Анимированные GIF отклоняются.
  • Канонические URL встраивания: Сохранённый markdown / HTML использует HTTP-URL Mailoo с ``?id={mediaId}`` на /api/v1/images/public/content. Браузеры не могут обращаться по этому URL с API-ключом; интеграторы должны проксировать (см. ниже).
  • Внешнее чтение (API-ключ): GET /api/v1/images/public/content?id=… с X-API-Key и областью image.external-read (или FULL ключом) возвращает байты только для READY медиа, принадлежащих пользователю API-ключа.
  • ``S3_PUBLIC_BASE_URL``: Опциональная внутренняя деталь только для API; она не раскрывается в JSON-ответах и не должна использоваться как публичный контракт изображений.

Сводка по аутентификации

Маршруты изображений панели управления используют авторизованную Bearer-сессию. Чтение интеграторами --- X-API-Key с image.external-read (или FULL). Полные схемы: https://api.mailoo.app/docs/v1.


Операция Авторизация


Список изображений (курсор) Bearer; опциональные projectUid / integrationId / articleId для контекста видимости

Загрузка изображения (multipart) Bearer; поля формы file, scope, опциональные id контекста

Создание производного (масштаб / формат / сжатие) Bearer; JSON sourceId и хотя бы одно из maxWidth, maxHeight, format

Получение байтов изображения (владелец) Bearer; GET /images/{id}/content

Обновление / удаление по id Bearer

Получение байтов изображения (интегратор / сервер) X-API-Key с image.external-read (или FULL); id должен ссылаться на READY медиа пользователя ключа

Модель безопасности (нормативная)

  1. Владелец --- аутентифицированный id пользователя Mailoo из JWT или API-ключа --- никогда не клиентский user id.
  2. ``projectUid`` / ``integrationId`` / ``articleId`` --- контекст внутри данных этого владельца; API разрешает и проверяет цепочку.
  3. S3-ключи никогда не возвращаются клиентам.
  4. Ограниченные API-ключи должны включать image.external-read для вызова публичного эндпоинта чтения.

Области видимости

Медиа хранится с одной из областей USER, PROJECT, INTEGRATION или ARTICLE. Запрос списка с контекстом возвращает READY элементы, видимые в этом редакторском контексте.

Стоковые фото (панель блога)

Каждая интеграция Blog может хранить собственные API-ключи Unsplash и Pexels в разделе Подключение и настройки (зашифрованы в integration.config.stockPhotos; никогда не возвращаются в открытом виде). Платформенных стоковых API-ключей нет.

В панели изображений редактора статей вкладка Stock выполняет поиск с ключами этой интеграции. При выборе фото импортируются байты в UserMedia (те же области и публичные URL встраивания, что и при обычной загрузке). Отслеживание скачиваний Unsplash использует ключ Unsplash интеграции при импорте.

API панели управления (Bearer, редактор проекта):

  • GET /api/v1/projects/{uid}/integrations/{id}/stock/search?provider=unsplash|pexels&q=…
  • POST /api/v1/projects/{uid}/integrations/{id}/stock/import --- тело включает provider, externalId, scope и опциональные id иерархии

Справка по API (изображения)

Базовый путь: {apiBase}/api/v1/images.

Список (Bearer, курсор)

GET /api/v1/images --- параметры: limit (1--100, по умолчанию 24), cursor, опциональные фильтры projectUid, integrationId, articleId, scope, includeNonReady=true. Ответ: items, nextCursor, imagePublicEmbedBaseUrl.

Загрузка (Bearer)

POST /api/v1/images --- multipart: file, scope (USER | PROJECT | INTEGRATION | ARTICLE), плюс поля контекста по области (projectUid, integrationId, articleId при необходимости). Ответ содержит id, embedUrl, imagePublicEmbedBaseUrl, метаданные --- без S3-ключа.

Создание производного (Bearer)

POST /api/v1/images/derive --- JSON: sourceId, опциональные maxWidth, maxHeight, format, quality. Хотя бы одно из maxWidth, maxHeight или format обязательно.

Получение контента (Bearer)

GET /api/v1/images/{id}/content --- сырые байты для READY медиа.

Опциональное масштабирование на лету (тот же конвейер sharp, что и derive): параметры запроса ``w``, ``h``, ``fit`` (inside | cover | fill, по умолчанию inside), ``format`` (jpeg | jpg | png | webp), ``q`` (1--100, по умолчанию 85). Хотя бы один из ``w``, ``h`` или ``format`` должен быть указан для включения обработки; иначе объект стримится как есть.

Обновление / удаление (Bearer)

  • PATCH /api/v1/images/{id} --- JSON name, altText.
  • DELETE /api/v1/images/{id} --- удаление одного медиа с outbox повторов S3 при сбое.

Получение контента (API-ключ)

GET /api/v1/images/public/content?id={mediaId} --- X-API-Key; только для серверных прокси. Те же опциональные параметры трансформации, что и у Bearer-маршрута контента (``w``, ``h``, ``fit``, ``format``, ``q``), применяются при указании хотя бы одного из ``w``, ``h`` или ``format``.

Предварительно сгенерированные варианты через ``POST /api/v1/images/derive`` по-прежнему поддерживаются для стабильных URL (новый id медиа для каждого варианта).

Прокси интегратора и HTML блога

Полезные нагрузки статей Blog API включают ``imagePublicEmbedBaseUrl`` (префикс, заканчивающийся на ?id=). Ответ списка статей также повторяет тот же префикс на верхнем уровне (рядом с data / pagination). Ответы описания категории включают ``imagePublicEmbedBaseUrl`` в data, когда HTML описания может ссылаться на изображения Mailoo. Сохранённый ``htmlContent`` использует абсолютные канонические публичные URL под ``API_PUBLIC_URL``; замените эти URL в HTML на URL прокси вашего сайта с тем же id медиа.

Используйте ``rewriteMailooPublicImageUrls`` из ``@mailoo/images`` (также реэкспортируется для хостов, уже зависящих от этого пакета). См. nextjs-packages{.interpreted-text role="doc"}.

Конфигурация оператора (только API)

Устанавливается на хосте API (не в браузере):


Переменная Назначение


API_PUBLIC_URL Публичный базовый URL API (без завершающего слэша); используется для канонических URL встраивания

S3_BUCKET Имя бакета (обязательно)

S3_REGION Регион (по умолчанию us-east-1 если не задан)

S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEY Учётные данные (обязательно)

S3_ENDPOINT Пользовательский эндпоинт для MinIO / S3-совместимых (необязательно)

S3_FORCE_PATH_STYLE true для многих конфигураций MinIO (необязательно; по умолчанию path-style при наличии S3_ENDPOINT)

S3_PUBLIC_BASE_URL Необязательно; внутренняя деталь только для API --- не является частью публичного контракта интеграции

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

Дополнительные материалы

  • nextjs-packages{.interpreted-text role="doc"} --- фабрика прокси @mailoo/images
  • blog-headless-cms{.interpreted-text role="doc"}
  • website-forms{.interpreted-text role="doc"}
  • OpenAPI: https://api.mailoo.app/docs/v1