Загрузка файлов
Один запрос, до пятидесяти файлов, подпапки, поддерживаемые форматы и что означают счётчики в ответе.
Файлы кладутся в конкретную папку базы знаний — ту, чей идентификатор вернул
/mine:
POST /api/admin/library-folders/<id папки>/filesТело — обычная форма multipart/form-data. Поле называется files; их может быть несколько
в одном запросе.
curl -X POST "https://portal.example.com/api/admin/library-folders/$FOLDER/files" \
-H "Authorization: Bearer sk_forge_..." \
-F "files=@договор-2026-014.pdf"За один запрос — не больше пятидесяти файлов. Пятьдесят первый портал отклонит целиком, а не отрежет.
curl -X POST "https://portal.example.com/api/admin/library-folders/$FOLDER/files" \
-H "Authorization: Bearer sk_forge_..." \
-F "files=@акт-1.pdf" \
-F "files=@акт-2.pdf" \
-F "files=@реестр.xlsx"Подпапки
Чтобы файлы легли не в корень папки, а в подпапки, добавьте поле relativePaths — массив
строк той же длины, что и список файлов, в том же порядке. Пустая строка означает корень.
curl -X POST "https://portal.example.com/api/admin/library-folders/$FOLDER/files" \
-H "Authorization: Bearer sk_forge_..." \
-F 'relativePaths=["2026/01","2026/02",""]' \
-F "files=@январь.xlsx" \
-F "files=@февраль.xlsx" \
-F "files=@сводная.xlsx"Поле принимается и как повторяющееся поле формы, и как строка с JSON-массивом. Длина обязана
совпадать с числом файлов, иначе весь запрос отклоняется. Путь проверяется: выйти за пределы
папки через .. нельзя.
Форматы
Список ниже — то, что портал принимает на загрузку. Что именно он потом сумеет прочитать внутри файла — отдельный вопрос, и про него написано в разделе «Файлы».
Документы: .pdf, .docx, .doc, .xlsx, .xls, .pptx, .ppt, .odt, .ods, .odp,
.txt, .csv, .md, .html, .htm, .json, .eml, .srt.
Изображения: .png, .jpg, .jpeg.
Аудио и видео: .wav, .mp3, .ogg, .flac, .m4a, .webm, .weba, .mp4, .mkv,
.mov — при условии, что перевод записей в текст на этом портале включён. Если он выключен,
такие файлы не загружаются, но и ошибкой это не считается: они возвращаются в поле
skippedFiles ответа, а остальные файлы запроса принимаются.
Расширение должно соответствовать содержимому: для двоичных форматов портал проверяет
первые байты файла и отклоняет запрос при несовпадении. Текстовые
форматы (.txt, .csv, .md, .html, .htm, .json, .eml, .srt) эту проверку не
проходят — по первым байтам их не отличить.
Письма в формате .eml — единственный случай, когда тип надо указать явно: без этого
библиотека, которой вы отправляете запрос, скорее всего подставит application/octet-stream,
и файл будет отклонён.
curl -X POST "https://portal.example.com/api/admin/library-folders/$FOLDER/files" \
-H "Authorization: Bearer sk_forge_..." \
-F "files=@письмо.eml;type=message/rfc822"Размеры
Один документ — до 200 МБ. Для аудио и видео действует отдельный предел, он задаётся при установке портала; спросите его у администратора, если собираетесь грузить длинные записи.
Ответ
Успех — код 201:
{
"data": {
"uploaded": 2,
"deduplicated": 1,
"replaced": 0,
"alreadyInFolder": 0,
"files": [
{
"id": "b1f2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"filename": "акт-1.pdf",
"relativePath": "",
"deduplicated": false,
"alreadyInFolder": false
}
],
"skippedFiles": []
}
}Что означают счётчики:
| Счётчик | Что произошло |
|---|---|
uploaded | Файл новый: такого содержимого у портала не было, он добавлен в папку |
deduplicated | Точно такое содержимое портал уже хранил. Новой копии не появится, папка сошлётся на имеющийся файл |
alreadyInFolder | Это же содержимое уже лежит в этой папке по этому пути. Ничего не изменилось |
replaced | В папке по этому пути уже был файл с таким именем, но с другим содержимым. Старый заменён новым |
Счётчики пересекаются: файл, который уже лежал в папке и чьё содержимое портал уже знал,
увеличит и alreadyInFolder, и deduplicated. Сумма четырёх чисел не равна числу
отправленных файлов. Результат для каждого файла смотрите в массиве files.
Порядок элементов files не обязан совпадать с порядком файлов в запросе. Сопоставляйте
по паре «relativePath + filename», а не по номеру в массиве.
Поле skippedFiles — список из пар filename и reason для файлов, которые портал принял
к рассмотрению, но не сохранил. Сегодня туда попадают только медиафайлы при выключенном
переводе записей в текст.
Что происходит дальше
Загрузка возвращает 201 сразу, но файл в этот момент ещё не готов к работе: портал
обрабатывает его в фоне. Пока обработка не закончилась, файл виден в списке, но задачи его
содержимое ещё не используют. Состояние каждого файла видно в поле indexStatus
списка файлов и на странице папки в администраторской части. Что
означают состояния — в справочнике статусов.
Записи (аудио и видео) проходят более длинный путь: сначала перевод в текст, и только потом обработка получившегося текста.
Если что-то пошло не так
400. Запрос отклонён целиком, ни один файл не сохранён. Причина — вerror.details.reason, таблица причин.403. Папка не входит в список этого ключа. Сверьтесь с ответом/mine.- Файл принят, но задачи его не видят. Скорее всего обработка ещё идёт или закончилась
ошибкой — посмотрите
indexStatus. Повторная попытка запрашивается переобработкой папки. - Загрузили новую версию, а в папке старая. Замена по имени срабатывает только при
совпадении имени и пути. Файл с тем же именем, отправленный с другим
relativePaths, ляжет рядом как отдельный.