К содержимому

Загрузить файл

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

  • visibilitystring

    private — только ты; unlisted — все, у кого есть ссылка; public — ещё лента и профиль, нельзя вместе с oneTime (400 ONE_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СозданоCreated
    • idstringобязательный

      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, url carries 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 поля
      • idstring

        id автора.

      • usernamestring

        Никнейм.

      • namestring

        Имя.

    • contentContent

      Файл.

      то же, что Content выше

  • 400Некорректный запросONE_TIME_NOT_PUBLICUPLOAD_FORMAT_UNSUPPORTED
  • 401Нужен действующий ключ
  • 403Нет права или функции тарифа
  • 404Не найдено
  • 408Тело запроса перестало приходитьUPLOAD_STALLED
  • 409Конфликт
  • 410Файл удалён или истёк
  • 413Слишком большой файл или нет местаIMAGE_TOO_LARGEQUOTA_EXCEEDEDVIDEO_TOO_LARGE
  • 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
  • 429Слишком много запросовUPLOAD_USER_BUSY
  • 503Сервис занят или недоступенUPLOAD_SERVER_BUSY

Пример ответа

201 · application/json
{
  "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_PUBLIC400Одноразовый файл нельзя опубликовать в ленте и профиле. Выбери доступ по ссылке или отключи одноразовую ссылку.
UPLOAD_FORMAT_UNSUPPORTED400Поддерживаются статичные PNG, JPEG, WebP, AVIF, а также MP4 и WebM. Изображение — до 40 мегапикселей.
UPLOAD_STALLED408Файл перестал передаваться. Проверь соединение и повтори загрузку.
IMAGE_TOO_LARGE413Изображение больше допустимого размера. Сожми его или уменьши разрешение.
QUOTA_EXCEEDED413Недостаточно места в аккаунте.
VIDEO_TOO_LARGE413Видео больше допустимого размера. Сожми его в «Сжатии» — в кабинете lacuna или в приложении для Windows.
VIDEO_NOT_SUITABLE415Видео нужно сжать перед загрузкой: lacuna хранит H.264 с AAC (MP4) или VP9/AV1 с Opus (WebM) до 3840 × 2160. Сожми его в приложении lacuna для Windows или в «Сжатии» на сайте.
UPLOAD_USER_BUSY429С этого аккаунта уже идут загрузки. Следующая начнётся, когда одна из них закончится.
UPLOAD_SERVER_BUSY503Сервер сейчас принимает много файлов. Повтори через несколько секунд.

Ответы любого метода с ключом — неверный или истёкший ключ, нет права, частые запросы — в разделе Ошибки.

Загрузить файл: POST /api/v1/uploads · API lacuna