Загрузить файл
POST/api/v1/uploads
- Доступ
- Ключ API
- Право
content:write
Изображение (до limits.maxImageBytes: 10 МБ на бесплатном тарифе) или видео MP4/WebM (до limits.maxVideoBytes: 100 МБ на бесплатном). У тарифа без лимита на файл (Pro) файл ограничен местом (413 QUOTA_EXCEEDED) и пределом сервера для одного файла — 64 МБ для изображения, 4 ГБ для видео (params.ceiling = server); тело больше 100 МБ лучше передавать через /v1/uploads/resumable. Тип определяется по первым байтам: другой формат (400 UPLOAD_FORMAT_UNSUPPORTED) или слишком большой файл (413 IMAGE_TOO_LARGE / VIDEO_TOO_LARGE с params.limitBytes) отклоняется, ничего не сохраняя. Видео хранится одной версией и должно уже быть тем, что описывает limits.video: H.264 с AAC или VP9/AV1 с Opus, в пределах кадра, частоты, длительности и битрейта; иначе — 415 VIDEO_NOT_SUITABLE с params.problems, сервер не перекодирует (сайт и приложение lacuna сжимают сами). Видео передаётся потоком и приходит в статусе PROCESSING, пока сервер не сохранит версию без метаданных контейнера и обложку. Аккаунт загружает limits.uploadsAtOnce файлов одновременно (иначе 429 UPLOAD_USER_BUSY), занятый сервер отвечает 503 UPLOAD_SERVER_BUSY — в обоих ответах есть Retry-After, и ничего не изменилось. Тело, которое 30 секунд не передаётся, сбрасывается (408 UPLOAD_STALLED).
Пример запроса
curl -X POST "https://lac.pics/api/v1/uploads" \
-H "Authorization: Bearer lac_api_YOUR_KEY" \
-H "Idempotency-Key: capture-2026-09-27-a7f3c1" \
-F "file=@capture.png" \
-F "visibility=unlisted"Параметры
Заголовки
Idempotency-KeystringСлучайная строка из 16–128 латинских букв, цифр,
_и-, одна на файл. Повтор с тем же ключом и теми же данными вернёт уже загруженный файл (201) и не продлит его срок; квитанции хранятся не меньше 24 часов. Попытка ещё идёт — 409 сRetry-After; тот же ключ с другими данными — 409; файл уже удалён или истёк — 410. Без заголовка каждый запрос — новая загрузка.шаблон
^[A-Za-z0-9_-]{16,128}$
Тело запроса
multipart/form-dataобязательный
filestring · binaryобязательныйИзображение или видео.
tagsstringМассив строк в JSON, например
["design","release"]; правила те же, что у тегов в JSON.не длиннее 2 048
titlestringНазвание, до 180 символов.
не длиннее 180
visibilitystringprivate— только ты;unlisted— все, у кого есть ссылка;public— ещё лента и профиль, нельзя вместе сoneTime(400ONE_TIME_NOT_PUBLIC). Не передано при создании — настройка аккаунта; при изменении — доступ прежний.значения:
"private""unlisted""public"ttlstringСрок хранения от момента запроса:
day,week,monthилиforever— без срока. После него ссылка перестаёт открываться, зашифрованные данные удаляются в фоне.значения:
"forever""day""week""month"passwordstringтолько в запросе8–128 символов. Пустая строка снимает пароль, без поля пароль не меняется. Хранится как Argon2id и не возвращается; смена закрывает доступ тем, кто уже открывал. В ленте, профилях и альбомах другие видят такой файл закрытой карточкой.
не длиннее 128 · шаблон
^(?:[\s\S]{8,128})?$oneTimebooleanФайл откроет только первый гость — не дольше 10 минут, включая перемотку видео. Твой просмотр и запросы GET/HEAD ссылку не тратят. Нельзя вместе с
public; в ленте, профилях и альбомах такой файл не показывается.по умолчанию false
Ответы
201Создано
Createdidstringобязательныйid файла.
titlestringобязательныйНазвание.
tagsмассив stringобязательныйТеги.
до 10 элементов · без повторов
originalNamestringИсходное имя файла.
typestringобязательныйIMAGE,VIDEO,PASTEилиFOLDER— папка с кодом.значения:
"IMAGE""VIDEO""PASTE""FOLDER"mimestringобязательныйMIME-тип сохранённого файла.
pasteFormatstringили nullФормат заметки.
значения:
"plain""markdown""code"pasteLanguagestringили nullЯзык подсветки заметки.
folderFilesintegerили nullУ папки с кодом — сколько в ней файлов; у остального null.
от 1
revisionintegerобязательныйРевизия текста заметки для правки.
от 1
accessVersionintegerобязательныйShare access version: 1 for a new file, raised by every change of visibility, password or one-time. From 2 on,
urlcarries it as ?v= so messengers build a fresh link card instead of the one they kept for the previous access.от 1
sizeinteger · int64обязательныйРазмер в байтах.
visibilitystringобязательныйДоступ:
private,unlistedилиpublic.значения:
"private""unlisted""public"allowDownloadbooleanобязательныйПоказывается ли кнопка скачивания.
passwordProtectedbooleanобязательныйЕсть ли пароль.
oneTimebooleanобязательныйОдноразовая ли ссылка.
consumedAtstring · date-timeили nullКогда одноразовая ссылка была открыта.
readExpiresAtstring · date-timeили nullДо какого момента открывший одноразовую ссылку может смотреть файл.
readMaxExpiresAtstring · date-timeили nullСамый поздний конец доступа по одноразовой ссылке.
hasVideoTextbooleanЕсть ли у видео субтитры или расшифровка.
videoTextRevisionintegerРевизия текста видео.
0–2 147 483 647
viewsintegerобязательныйЗасчитанные открытия гостями, без повторов в пределах доступа зрителя (обычно сутки). Просмотры владельца не считаются.
от 0
viewLimitintegerили nullЛимит просмотров (Pro) или null.
1–1 000 000
viewLimitReachedAtstring · date-timeили nullКогда лимит просмотров исчерпан; null, пока просмотры есть или лимита нет.
mediaStatusstringОбработка:
PROCESSING— идёт,READY— готово,FAILED— не удалась. Воспроизведение и превью — послеREADY; оригинал владелец может скачать и раньше, с?download=1.значения:
"PROCESSING""READY""FAILED"mediaErrorstringили nullПричина, если обработка не удалась.
widthintegerили nullШирина в пикселях.
heightintegerили nullВысота в пикселях.
durationMsintegerили nullДлительность видео в миллисекундах.
videoCodecstringили nullКодек видео.
hasAudiobooleanЕсть ли звук.
previewUrlstringили nullАдрес зашифрованного превью; доступ — как у самого файла.
expiresAtstring · date-timeили nullКогда файл и ссылка перестанут работать; null — без срока.
createdAtstring · date-timeобязательныйКогда создан.
urlstring · uriобязательныйСсылка на страницу файла.
mediaUrlstringобязательныйАдрес самого файла.
moderationHoldstringили nullАвтопроверка:
review— скрыт до решения модератора,blocked— скрыт модератором. Другие видят такой файл как приватный.значения:
"review""blocked"favoritebooleanВ избранном (в списках).
ownedbooleanСвой файл (в списках).
authorobjectАвтор.
3 поля
idstringid автора.
usernamestringНикнейм.
namestringИмя.
contentContentФайл.
то же, что Content выше
- 401Нужен действующий ключ
- 403Нет права или функции тарифа
- 404Не найдено
- 409Конфликт
- 410Файл удалён или истёк
- 415VIDEO_NOT_SUITABLE: the video is not stored as it is; params.problems names what to fix (compress it on the client).VIDEO_NOT_SUITABLE
Пример ответа
{
"id": "Xq3u9RkT0bLmA7cV2pWz1eFy",
"title": "capture",
"tags": [
"release"
],
"originalName": "capture.png",
"type": "IMAGE",
"mime": "image/png",
"pasteFormat": null,
"pasteLanguage": null,
"folderFiles": 1,
"revision": 1,
"accessVersion": 1,
"size": 482133,
"visibility": "unlisted",
"allowDownload": true,
"passwordProtected": false,
"oneTime": false,
"consumedAt": null,
"readExpiresAt": null,
"readMaxExpiresAt": null,
"hasVideoText": false,
"videoTextRevision": 0,
"views": 3,
"viewLimit": null,
"viewLimitReachedAt": null,
"mediaStatus": "READY",
"mediaError": null,
"width": 1920,
"height": 1080,
"durationMs": null,
"videoCodec": null,
"hasAudio": false,
"previewUrl": null,
"expiresAt": null,
"createdAt": "2026-09-27T09:30:00.000Z",
"url": "https://lac.pics/s/Xq3u9RkT0bLmA7cV2pWz1eFy",
"mediaUrl": "/api/media/Xq3u9RkT0bLmA7cV2pWz1eFy",
"moderationHold": null,
"favorite": false,
"owned": true,
"author": {
"id": "cmf8a1x2k0000q7lh3v9w2e4d",
"username": "alex",
"name": "Alex"
}
}Коды ошибок
| Код | Статус | Текст |
|---|---|---|
ONE_TIME_NOT_PUBLIC | 400 | Одноразовый файл нельзя опубликовать в ленте и профиле. Выбери доступ по ссылке или отключи одноразовую ссылку. |
UPLOAD_FORMAT_UNSUPPORTED | 400 | Поддерживаются статичные PNG, JPEG, WebP, AVIF, а также MP4 и WebM. Изображение — до 40 мегапикселей. |
UPLOAD_STALLED | 408 | Файл перестал передаваться. Проверь соединение и повтори загрузку. |
IMAGE_TOO_LARGE | 413 | Изображение больше допустимого размера. Сожми его или уменьши разрешение. |
QUOTA_EXCEEDED | 413 | Недостаточно места в аккаунте. |
VIDEO_TOO_LARGE | 413 | Видео больше допустимого размера. Сожми его в «Сжатии» — в кабинете lacuna или в приложении для Windows. |
VIDEO_NOT_SUITABLE | 415 | Видео нужно сжать перед загрузкой: lacuna хранит H.264 с AAC (MP4) или VP9/AV1 с Opus (WebM) до 3840 × 2160. Сожми его в приложении lacuna для Windows или в «Сжатии» на сайте. |
UPLOAD_USER_BUSY | 429 | С этого аккаунта уже идут загрузки. Следующая начнётся, когда одна из них закончится. |
UPLOAD_SERVER_BUSY | 503 | Сервер сейчас принимает много файлов. Повтори через несколько секунд. |
Ответы любого метода с ключом — неверный или истёкший ключ, нет права, частые запросы — в разделе Ошибки.