# Warpbin API v1 > Warpbin brings an event's photos and videos together in one gallery: guests upload through a link or QR code, and the host manages the gallery on its Manage page. This API lets software create galleries, sort files into albums, upload, list and delete files. Everything it does shows in the gallery's Manage page too; it is the same gallery. Human docs: https://warpbin.com/docs/api Base URL: https://warpbin.com/api/v1 Auth: send "X-API-Key: wb_live_..." (or "Authorization: Bearer wb_live_...") on every request. Keys come from contact@warpbin.com and act for one account: they work only on galleries that account owns. Format: JSON bodies in and out, except uploads (TUS or multipart form) and downloads (the file's bytes). ## Model - Gallery: one event. Guest link https://warpbin.com/{slug}; host's Manage page https://warpbin.com/manage/{gallery_id}. The id is in the Manage link (a custom guest link is not the id). Older endpoints call it drive_id or id: same value. - Which galleries a key works on: uploads work into any gallery that takes uploads. The /v1/galleries/{gallery_id}/... routes (albums, file list, file delete) need the gallery to be on the Pro subscription of the key's account; other galleries answer 403 NOT_GALLERY_OWNER. createGallery needs an active Pro subscription. Galleries are bought at https://warpbin.com/pricing (one-time or Pro). - admin_id: the gallery's admin password (the pd in its Manage link). Needed only to upload into a gallery whose guest uploads are off. - Album: optional group of files in a gallery, id album_id (UUID). Names are unique per gallery; the id survives renames, so store the id. A file is in one album or none. Uploading never creates an album. - File: its id is its filename, the name it was stored under (uploads return it). Never changes. If the name is taken, the file is stored under a free one (photo_2.jpg). - File status: processing (previews being made) -> ready, or failed (stored, but no preview could be made). Files the host hid from guests are still listed and manageable. - File types: photos JPEG, PNG, GIF, WebP, HEIC, AVIF; videos MP4, MOV, AVI, WebM, MKV; other files (PDF, TXT, ...) kept as they are. ## Conventions - Errors: HTTP status plus {"error": "", "type": ""}. Branch on type; for 5xx branch on the status. - Paging: lists answer {"": [...], "next_after": string | null}, ordered by name. Query: limit (1-1000, default 100) and after (the previous page's next_after; omit for the first page). Stop when next_after is null. Deleting while paging never skips items. - Retries are safe: creating an album that exists returns it (200), deleting something already gone succeeds, a finished resumable upload is never stored twice. Retry the same request after a timeout, 429 or 5xx. - Rate limits: 429 Too Many Requests means wait and retry. TUS chunk requests have their own, higher limit. - Errors any request can get: 401 MISSING_API_KEY or INVALID_API_KEY; 429; 500 SERVER_ERROR (safe to retry). - Errors any /v1/galleries/{gallery_id}/... request can get: 404 GALLERY_NOT_FOUND; 403 NOT_GALLERY_OWNER (another account's gallery); 403 GALLERY_EXPIRED or GALLERY_DELETED (it can't change any more). ## Endpoints ### POST /v1/createGallery Create a gallery owned by your account. Needs an active Pro subscription. Alias: POST /v1/createDrive. Body: {"alt_tenant_url"?: string} - a custom guest address, as in warpbin.com/my-project. 200: {"success": true, "drive_id", "admin_id", "drive_url", "manage_url", "message"}. Keep admin_id safe: it manages the gallery. Errors (these answer {"success": false, "message"}): 403 no active Pro subscription; 400 custom address not allowed (message says why); 409 custom address taken. ### POST /v1/galleries/{gallery_id}/albums Create an album. Body: {"name": string} - required, up to 255 characters, no commas, semicolons or line breaks. 201 (new) or 200 (an album with that name already exists, returned as is): {"album_id", "name", "file_count", "created_at"}. file_count includes files still processing. Errors: 400 INVALID_ALBUM_NAME. ### GET /v1/galleries/{gallery_id}/albums List albums by name. Query: limit, after. 200: {"albums": [{"album_id", "name", "file_count", "created_at"}], "next_after"}. ### GET /v1/galleries/{gallery_id}/albums/{album_id} One album. 200: {"album_id", "name", "file_count", "created_at"}. Errors: 400 INVALID_ALBUM_ID; 404 ALBUM_NOT_FOUND. ### DELETE /v1/galleries/{gallery_id}/albums/{album_id} Delete an album. Query: delete_files=true also deletes every photo and video in it (default false: they stay in the gallery, in no album). 200: {"deleted_files": [filename, ...]} (empty without delete_files). An album already gone answers 200 with []. Errors: 400 INVALID_ALBUM_ID; 503 STORAGE_ERROR (storage kept some files, so the album was kept: send the same delete again). ### Resumable upload (TUS 1.0 with creation and termination; recommended) POST /v1/tus - open a session. Headers: Tus-Resumable: 1.0.0, Upload-Length: , Upload-Metadata: comma-separated "key base64(value)" pairs: drive_id (required): the gallery filename (required): the file's name with its extension session_id (required): a UUID you generate, grouping one client session's uploads album_id (optional): checked here, before any bytes are sent admin_id (optional): only when guest uploads are off user_id (optional): your own id for who uploaded it consent_given (optional): "true" if the uploader agreed to the gallery's terms -> 201 with Location: /api/v1/tus/{upload_id} PATCH /v1/tus/{upload_id} - headers Tus-Resumable: 1.0.0, Upload-Offset: , Content-Type: application/offset+octet-stream; body: the next chunk. -> 204 with the new Upload-Offset. HEAD /v1/tus/{upload_id} - 200 with Upload-Offset, the byte to continue from. On a finished upload Upload-Offset equals Upload-Length and Upload-Metadata holds "filename base64(stored name)"; sending the last PATCH again answers 204 and stores nothing. DELETE /v1/tus/{upload_id} - abandon a session. Any TUS client works (tus-js-client, tuspy): endpoint https://warpbin.com/api/v1/tus, the API key header, the metadata above. After the last PATCH the file is listed at once with status processing, then ready. Limits: 50 GB per file; chunks of 1-10 MiB suit most networks; unfinished sessions last up to 24 hours and are lost on a server restart (404 or 410 on a known session: nothing was stored, start that file again with a new POST). Errors: 400 MISSING_FIELD; 400 ALBUM_NAME_NOT_SUPPORTED (album or album_name sent: create the album, send its album_id); 400 INVALID_ALBUM_ID; 400 ALBUM_NOT_FOUND; 403 DRIVE_EXPIRED, UPLOADS_DISABLED (guest uploads off, no admin_id), PLAN_LIMIT_EXCEEDED - don't retry these; 404 / 410 session unknown or expired; 409 OFFSET_MISMATCH (body has server_offset: HEAD, then continue from it); 413 FILE_TOO_LARGE; 507 DISK_SPACE_CRITICAL (wait and retry). ### POST /v1/uploadFile Simple upload: one multipart/form-data request per file. Fields: file_contents (the file, required), filename (required), drive_id (required), album_id, admin_id, user_id, consent_given. 202: {"message", "filename" (the stored name, the file's id), "file_preview_url", "file_download_url"}. Processed in the background. A retry after a lost response stores the file again under a new name (photo_2.jpg); use the resumable upload when that matters. Errors: 400 MISSING_FIELD; 400 INVALID_DRIVE_ID; 400 ALBUM_NAME_NOT_SUPPORTED, INVALID_ALBUM_ID, ALBUM_NOT_FOUND; 403 DRIVE_EXPIRED; 403 UPLOADS_DISABLED; 507 STORAGE_SPACE (the gallery's storage is full). ### GET /v1/galleries/{gallery_id}/files List files by name: the whole gallery, or one album. Query: album_id, limit, after. 200: {"files": [file, ...], "next_after"}. Each file: filename, album_id (or null), type (image | video | other), size (bytes), status (processing | ready | failed), capture_time (from the file's own data, or null), uploaded_at, shares (times guests shared it: the photo, its link or a copied link), downloads (single-file downloads since October 2026, including getFile). Hidden and still-processing files are listed; deleted files are not. Errors: 400 INVALID_ALBUM_ID. ### GET /v1/fileInfo?drive_id={drive_id}&filename={filename} A file's page and download links. Your galleries answer for every file; other galleries only for files their guests can see. 200: {"filename", "file_preview_url" (opens without a key), "file_download_url"}. Errors: 400 MISSING_PARAMETER; 400 INVALID_DRIVE_ID; 404 NOT_FOUND. ### GET /v1/getFile?id={drive_id}&file={filename} The original file's bytes, with its content type. Note the short names: id is the gallery, file the filename. Other galleries follow their host's rules (hidden files and turned-off downloads stay closed). Errors: 400 MISSING_PARAMETER; 400 INVALID_FILENAME; 404 NOT_FOUND; 502 STORAGE_ERROR (retry). ### DELETE /v1/galleries/{gallery_id}/files/{filename} Delete a file for good; URL-encode the filename. 204 whether it was there or already gone. The original and previews go at once, also for a file still processing. Copies already downloaded or shared can't be recalled, and chat-app link previews may show it for up to a day. Errors: 503 STORAGE_ERROR (send the same delete again).