Skip to content

Resumable uploads

GET/api/v1/uploads/resumable

Access
API key
Permission
content:write

List up to twenty recent uploads owned by the active account epoch

Example request

curl "https://lac.pics/api/v1/uploads/resumable" \
  -H "Authorization: Bearer lac_api_YOUR_KEY"

Parameters

Headers

  • X-Lacuna-Accountstring

    Optional expected account ID; mismatch fails409 before reading state or buffering bytes.

Responses

  • 200Confirmed persisted state. No unconfirmed chunk bytes contribute to progress.object
    • uploadsarray of ResumableUploadrequired

      up to 20 items

      ResumableUpload 11 fields
      • idstring · uuidrequired

        The upload id.

      • statestringrequired

        The state: UPLOADING, COMPLETING, COMPLETED, CANCELLED or EXPIRED.

        values: "UPLOADING" "COMPLETING" "COMPLETED" "CANCELLED" "EXPIRED"

      • filenamestringrequired
      • sizeinteger · int64required

        Size in bytes.

        1–4,294,967,296

      • chunkSizeintegerrequired

        The part size: 2,097,152 bytes (2 MB).

        values: 2097152

      • chunkCountintegerrequired

        1–50

      • fingerprintstringrequired

        pattern ^[a-f0-9]{64}$

      • receivedarray of integerrequired

        Numbers of the confirmed parts.

        unique

      • receivedBytesinteger · int64required

        Confirmed bytes.

        0–4,294,967,296

      • expiresAtstring · date-timerequired
      • contentContentrequiredor null
        Content 40 fields
        • idstringrequired

          The file id.

        • titlestringrequired

          Title, up to 180 characters.

        • tagsarray of stringrequired

          NFKC, trim, collapse spaces and lowercase; deduplicated after normalization. Raw controls are invalid. Omission preserves tags on update; an empty array clears them.

          up to 10 items · unique

        • originalNamestring

          The original file name.

        • typestringrequired

          IMAGE, VIDEO, PASTE or FOLDER (a folder of code).

          values: "IMAGE" "VIDEO" "PASTE" "FOLDER"

        • mimestringrequired

          The MIME type of the stored file.

        • pasteFormatstringor null

          values: "plain" "markdown" "code"

        • pasteLanguagestringor null
        • folderFilesintegeror null

          A code folder (type FOLDER): files in its archive. Null for other kinds. The archive itself is the media: GET /api/media/{id} serves it (Range requests read one file by the ZIP central directory), ?download=1 as an attachment.

          at least 1

        • revisionintegerrequired

          Optimistic revision for editing saved paste text; distinct from share access version.

          at least 1

        • accessVersionintegerrequired

          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.

          at least 1

        • sizeinteger · int64required

          Size in bytes.

        • visibilitystringrequired

          private is owner-only. unlisted is accessible by link. public also appears in the authenticated feed and profile. public cannot be combined with oneTime (400 ONE_TIME_NOT_PUBLIC). Omitted on creation: use the account default (private or unlisted). Omitted on update: retain current access.

          values: "private" "unlisted" "public"

        • allowDownloadbooleanrequired
        • passwordProtectedbooleanrequired
        • oneTimebooleanrequired
        • consumedAtstring · date-timeor null
        • readExpiresAtstring · date-timeor null
        • readMaxExpiresAtstring · date-timeor null
        • hasVideoTextboolean
        • videoTextRevisioninteger

          0–2,147,483,647

        • viewsintegerrequired

          Explicit guest opens, deduplicated during the viewer grant (normally 24 hours). Owner previews are excluded.

          at least 0

        • viewLimitintegeror null

          Link control (Pro, plan feature view_limit): after this many counted views the link answers like an expired one (404 SHARE_UNAVAILABLE) to everyone but the owner and viewers still holding the grant of their counted open. Media of a limited file is served only after an explicit open (POST /api/share/{id}/open), so direct media links and link cards cannot bypass the count. Null: no limit.

          1–1,000,000

        • viewLimitReachedAtstring · date-timeor null

          When the view limit was used up; null while views remain or without a limit.

        • mediaStatusstring

          New videos are processed asynchronously. Playback and previews require READY. The owner may explicitly download the original with ?download=1 while PROCESSING or FAILED; it is returned as an application/octet-stream attachment.

          values: "PROCESSING" "READY" "FAILED"

        • mediaErrorstringor null

          The reason when processing failed.

        • widthintegeror null

          Width in pixels.

        • heightintegeror null

          Height in pixels.

        • durationMsintegeror null

          Video duration in milliseconds.

        • videoCodecstringor null
        • hasAudioboolean
        • previewUrlstringor null

          Encrypted derived preview served with the same access checks as the source.

        • expiresAtstring · date-timeor null
        • createdAtstring · date-timerequired

          When it was created.

        • urlstring · urirequired

          The file page to share: {WEB_ORIGIN}/s/{id}, with ?v={accessVersion} once access changed (the page ignores the parameter; older links keep working).

        • mediaUrlstringrequired

          The address of the file itself.

        • moderationHoldstringor null

          Automatic check: review — hidden from everyone but the owner until a moderator decides; blocked — kept hidden by a moderator. Others get such a file exactly like a private one, so only the owner ever sees a non-null value.

          values: "review" "blocked"

        • favoriteboolean

          Present in list responses

        • ownedboolean

          Present in list responses

        • authorobject
          3 fields
          • idstring

            The author’s id.

          • usernamestring
          • namestring
  • 400Typed error. Reconcile uncertain results through status; retry completion with the same key and metadata.
  • 401Typed error. Reconcile uncertain results through status; retry completion with the same key and metadata.
  • 403Typed error. Reconcile uncertain results through status; retry completion with the same key and metadata.
  • 404Typed error. Reconcile uncertain results through status; retry completion with the same key and metadata.
  • 408Typed error. Reconcile uncertain results through status; retry completion with the same key and metadata.
  • 409Typed error. Reconcile uncertain results through status; retry completion with the same key and metadata.
  • 410Typed error. Reconcile uncertain results through status; retry completion with the same key and metadata.
  • 413Typed error. Reconcile uncertain results through status; retry completion with the same key and metadata.
  • 429Typed error. Reconcile uncertain results through status; retry completion with the same key and metadata.
  • 500Typed error. Reconcile uncertain results through status; retry completion with the same key and metadata.
  • 503Typed error. Reconcile uncertain results through status; retry completion with the same key and metadata.

Example response

200 · application/json
{
  "uploads": [
    {
      "id": "Xq3u9RkT0bLmA7cV2pWz1eFy",
      "state": "COMPLETED",
      "filename": "recording.mp4",
      "size": 4194304,
      "chunkSize": 2097152,
      "chunkCount": 2,
      "fingerprint": "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8",
      "received": [
        0,
        1
      ],
      "receivedBytes": 4194304,
      "expiresAt": "2026-09-28T09:30:00.000Z",
      "content": {
        "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"
        }
      }
    }
  ]
}

Error codes

Answers of any method with a key (an invalid or expired key, a missing permission, too many requests) are in Errors.

Resumable uploads: GET /api/v1/uploads/resumable · lacuna API