Перейти к содержимому
СервисАпп API
На этой странице

Фотографии и документы акта

Все операции. Авторизация. Запросы и повторы.

Все пути в этом файле дополняют /api/v1 на домене организации.

Описание и ограничения

Поля и коллекция

Публичное поле Формат и доступ
id целое, только чтение
act_id целое, только чтение; задаётся путём
kind attachment, входное поле/только чтение
filename безопасное имя без пути, только чтение
mime_type проверенный MIME, только чтение
size целое число байтов, только чтение
created_at ISO 8601 с поясом, только чтение
version непрозрачная строка, только чтение
download_url относительный путь на том же домене организации, только чтение
file ровно один файл, входное поле
client_filename необязательное имя файла, входное поле

kind=attachment используется для фотографий и документов акта. Подпись согласования не входит в этот ресурс: её нельзя загрузить, скачать или удалить через эти методы. Допустимые поля загрузки перечислены ниже.

Доступ и выборка

Нужны act_media:read для чтения и act_media:write для записи, доступ к акту и права «Акты приёма оборудования → Просмотр» или «Акты приёма оборудования → Изменение» соответственно. Загрузка также требует «Системные настройки → Загрузка вложений». Действуют общие ограничения тарифа, мастерских и типа акта. Доступ проверяется при чтении списка, карточки, скачивании, просмотре журнала и повторе запроса. Недоступный или чужой идентификатор файла возвращает 404.

Список использует общую пагинацию по курсору, sort=id/-id. Допустим только filter[kind]=attachment; других фильтров и updated_since нет. Каждый элемент содержит version, а GET JSON-карточки дополнительно возвращает отдельный ETag этого представления без скачивания файла.

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

Загрузка

Content-Type — multipart/form-data с корректным boundary. Обязательны file и текстовый kind=attachment; client_filename необязателен. Если его нет, используется имя файла без пути имени части file. Итоговое имя должно быть непустым, не длиннее 255 символов, без управляющих символов и разделителей пути. Указанное явно client_filename с путём отклоняется. Имя используется для скачивания; ключ хранения назначает сервер.

Разрешены следующие MIME из существующей формы акта:

Категория MIME
Изображения image/jpeg, image/png, image/gif, image/webp
PDF и текст application/pdf, text/plain
Word application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document
Excel application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
PowerPoint application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation
Архивы application/zip, application/x-rar-compressed, application/x-7z-compressed

Тип определяется по содержимому и формату файла, включая документы Office. Одного расширения или присланного MIME недостаточно. Неподдерживаемый или несогласованный формат возвращает 422 FILE_TYPE_NOT_ALLOWED. Архив сохраняется без распаковки. SVG, HTML и исполняемые файлы не принимаются. Ссылка, строка base64, локальный путь или идентификатор другого файла не заменяют поле file.

Успех — 201 с JSON-карточкой и её data.version, meta.operation_id, meta.affected_resources и meta.warnings=[], без ETag. affected_resources содержит созданный act-media и изменённый acts: изменение состава вложений обновляет updated_at акта; при совпавшей секунде version может остаться прежней. Если готовность файла требует фонового восстановления, возвращается 202 по общему контракту; 201 означает, что метаданные и содержимое доступны.

{
  "data": {
    "id": 81,
    "act_id": 301,
    "kind": "attachment",
    "filename": "Фото устройства.jpg",
    "mime_type": "image/jpeg",
    "size": 245760,
    "created_at": "2026-10-30T09:00:00.000000Z",
    "version": "1793782800",
    "download_url": "/api/v1/acts/301/media/81/download"
  },
  "meta": {
    "operation_id": "op-example-upload-81",
    "affected_resources": [
      {"type": "act-media", "id": 81, "version": "1793782800", "deleted": false},
      {"type": "acts", "id": 301, "version": "1793782800", "deleted": false}
    ],
    "warnings": []
  }
}

Location у POST указывает на журнал операции по общим правилам; путь к карточке файла собирается по методу ресурса. GET карточки возвращает актуальные data и отдельный ETag представления, без operation_id принятого POST. Все ответы, включая ошибки, получают собственный X-Request-Id только в заголовке.

Скачивание и удаление

Скачивание возвращает содержимое файла с кодом 200 с проверенным Content-Type, безопасным Content-Disposition: attachment, Cache-Control: private, no-store, X-Content-Type-Options: nosniff и X-Request-Id. У бинарного успеха нет JSON-обёртки. Версию для удаления берут из data.version JSON-метаданных, не из содержимого и не из ETag. Ошибки до начала передачи имеют общий JSON-формат. Авторизация обязательна при каждом скачивании; download_url не является публичной или подписанной ссылкой для доступа без авторизации на диск. Отозванный токен не получает файл по старому URL.

Удаление принимает только {} и If-Resource-Version файла. Успех — 200, data={"id":81,"deleted":true}, operation_id и affected_resources: у act-media deleted=true, version=null; у акта новая version. Новая команда для уже отсутствующего ID получает 404, а повтор принятого удаления возвращает исходную запись об операции при сохранении текущих прав на её контекст.

Идемпотентность и восстановление

При повторе сохраняйте метод, путь, kind, итоговый client_filename, содержимое файла и условия проверки версии. Разделитель частей запроса не влияет на сравнение. Другой файл, имя или родитель с ключом уже принятой операции возвращает 409 IDEMPOTENCY_CONFLICT.

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

Если завершить загрузку не удалось и требуется проверка результата, операция получает состояние needs_reconciliation. Повтор с прежним ключом не создаёт другой файл. Дальнейшее состояние проверяйте в журнале операций.

Создание и удаление вложения записывают act_media.created/act_media.deleted и act.updated согласованно с итогом операции. До готовности файла событие создания не публикуется. В конверт входят только ID, секундная версия и признак удаления; для проверки текущего доступа сохраняется явная ссылка на родительский акт. Повтор запроса не создаёт новые события.

Повтор запроса не пишет второй файл и не пересоздаёт удалённое позднее вложение. Старый If-Resource-Version принятого удаления не проверяется заново до поиска записи об операции; права проверяются всегда. Неизвестный исход приводит к сверке операции, а не к повторной загрузке под новым ключом. Истечение срока хранения тела ответа не освобождает ключ.

Операции

Метод Путь Назначение
GET /acts/{act_id}/media Список метаданных файлов акта
POST /acts/{act_id}/media Добавление одного файла, multipart/form-data
GET /acts/{act_id}/media/{id} JSON-карточка файла с version и сильным ETag
GET /acts/{act_id}/media/{id}/download Защищённое скачивание содержимого
POST /acts/{act_id}/media/{id}/delete Удаление файла, JSON {}

GET /acts/{act_id}/media

Метаданные вложений акта; подпись согласования не входит в ресурс.

Доступ. Разрешения подключения: act_media:read. Права сотрудника: «Акты приёма оборудования → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
act_id путь строка да нет Шаблон: ^(?:[0-9]+)$
filter[kind] параметр запроса строка нет нет Допустимо: "attachment"
sort параметр запроса строка нет нет Допустимо: "id", "-id"
page[size] параметр запроса целое число нет нет ≥ 1; ≤ 100
page[cursor] параметр запроса строка нет нет не более 8192 символов

Ответы

HTTP Назначение и схема
200 Успех. Полная схема и пример
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
409 Конфликт состояния или повтора. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

Пример запроса

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff \
  "$API/acts/101/media" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json"

POST /acts/{act_id}/media

Добавить ровно одно вложение. Случайный multipart разделитель частей не меняет fingerprint.

Доступ. Разрешения подключения: act_media:write. Права сотрудника: «Акты приёма оборудования → Изменение», «Системные настройки → Загрузка вложений». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
act_id путь строка да нет Шаблон: ^(?:[0-9]+)$
Idempotency-Key заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._:-]+$

Тело запроса

Content-Type: multipart/form-data. Тело обязательно.

Поле Тип Обязательно null Ограничения и смысл
kind строка да нет Допустимо: "attachment"
file строка (двоичные данные) да нет Файл от 1 до 10 МиБ включительно; MIME проверяется по содержимому.
client_filename строка нет нет не более 255 символов

Ответы

HTTP Назначение и схема
201 Создано. Полная схема и пример
202 Принято, итог в журнале. Полная схема и пример
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
409 Конфликт состояния или повтора. Коды и формат ошибки
413 Превышен размер. Коды и формат ошибки
415 Неподдерживаемый Content-Type. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
201 Location строка
202 Location строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

У принятого POST Location и meta.operation_id указывают на журнал операции; ETag отсутствует. При повторе запроса сохраняются исходные data/meta, добавляется Idempotency-Replayed: true. Версии передавайте по назначению, указанному в описании ресурса.

Пример запроса

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff --request POST \
  "$API/acts/101/media" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: example:v1-act-media-store:001" \
  --form 'kind=attachment' \
  --form 'file=@./examples/attachment.txt;type=text/plain'

GET /acts/{act_id}/media/{id}

Карточка файла с самостоятельной секундной версией и ETag представления.

Доступ. Разрешения подключения: act_media:read. Права сотрудника: «Акты приёма оборудования → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
act_id путь строка да нет Шаблон: ^(?:[0-9]+)$
id путь строка да нет Шаблон: ^(?:[0-9]+)$
If-None-Match заголовок строка нет нет —

Ответы

HTTP Назначение и схема
200 Успех. Полная схема и пример
304 Представление не изменилось, без тела. Условный GET
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
200 ETag строка
304 ETag строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

Пример запроса

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff \
  "$API/acts/101/media/101" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json"

GET /acts/{act_id}/media/{id}/download

Защищённое скачивание. В Range не поддерживается.

Доступ. Разрешения подключения: act_media:read. Права сотрудника: «Акты приёма оборудования → Просмотр». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
act_id путь строка да нет Шаблон: ^(?:[0-9]+)$
id путь строка да нет Шаблон: ^(?:[0-9]+)$

Ответы

HTTP Назначение и схема
200 Успех. Бинарный файл без JSON-обёртки; вложения
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
200 Content-Disposition строка
200 X-Content-Type-Options строка
200 Cache-Control строка
401 Cache-Control строка
403 Cache-Control строка
404 Cache-Control строка
422 Cache-Control строка
429 Cache-Control строка
503 Cache-Control строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

Пример запроса

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff \
  "$API/acts/101/media/101/download" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json"

POST /acts/{act_id}/media/{id}/delete

Удаление проверяет версию метаданных файла, а не версию акта.

Доступ. Разрешения подключения: act_media:write. Права сотрудника: «Акты приёма оборудования → Изменение». Дополнительно действуют доступ к записям, мастерским, модулям и условия полей из описания ресурса выше.

Параметры

Имя Где Тип Обязательно null Ограничения
Authorization заголовок строка да нет Bearer <SERVICEAPP_TOKEN>
act_id путь строка да нет Шаблон: ^(?:[0-9]+)$
id путь строка да нет Шаблон: ^(?:[0-9]+)$
Idempotency-Key заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._:-]+$
If-Resource-Version заголовок строка да нет не менее 1 символов; не более 128 символов; Шаблон: ^[A-Za-z0-9._~-]+$

Тело запроса

Content-Type: application/json. Тело обязательно.

Тело — пустой JSON-объект {}. Другие ключи не принимаются.

Ответы

HTTP Назначение и схема
200 Успех. Полная схема и пример
401 Требуется действующий Bearer. Коды и формат ошибки
403 Недостаточно допуска. Коды и формат ошибки
404 Не найдено или недоступно. Коды и формат ошибки
409 Конфликт состояния или повтора. Коды и формат ошибки
412 Версия устарела. Коды и формат ошибки
422 Ошибка входных данных. Коды и формат ошибки
428 Нужно предусловие версии. Коды и формат ошибки
429 Лимит запросов, Retry-After. Коды и формат ошибки
503 Временно недоступно. Коды и формат ошибки
HTTP Заголовок ответа Тип Описание
200 Location строка

Каждый ответ содержит новый X-Request-Id в заголовке. Общие транспортные отказы и правила повтора действуют также при отказе до контроллера; см. ошибки.

У принятого POST Location и meta.operation_id указывают на журнал операции; ETag отсутствует. При повторе запроса сохраняются исходные data/meta, добавляется Idempotency-Replayed: true. Версии передавайте по назначению, указанному в описании ресурса.

Пример запроса

Запускается из каталога комплекта после настройки переменных в быстром старте. Замените демонстрационные идентификаторы 101 и UUID идентификаторами доступных записей. $RESOURCE_VERSION берётся из GET владельца версии, описанного выше. Для нового действия сохраните новый ключ; для повтора используйте прежний.

curl --silent --show-error --globoff --request POST \
  "$API/acts/101/media/101/delete" \
  --header "Authorization: Bearer $SERVICEAPP_TOKEN" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: example:v1-act-media-destroy:001" \
  --header "If-Resource-Version: $RESOURCE_VERSION" \
  --header "Content-Type: application/json" \
  --data-binary '@examples/requests/v1.act-media.destroy.json'