Developer API v1.7.0

upload.am API

Upload, store, and share files from your own scripts, servers, and apps — the same speed, storage, and link controls the website gives your users, over a plain REST API.

  • REST + JSON
  • Bearer tokens
  • Presigned S3 uploads
  • Resumable multipart
  • Same limits as the website

Prefer plain text? Full reference as .md — handy for scripts and AI agents.

quickstart.sh
# 1. Get a presigned upload URL
curl -X POST https://upload.am/api/v1/upload/token \
  -H "Authorization: Bearer ua_live_xxx" -H "Content-Type: application/json" \
  -d '{"file_name": "report.pdf", "file_size": 204800}'

# 2. Put the bytes straight on storage
curl -X PUT "$upload_url" --data-binary @report.pdf

# 3. Confirm — the file now exists in your account
curl -X POST https://upload.am/api/v1/upload/confirm \
  -H "Authorization: Bearer ua_live_xxx" -H "Content-Type: application/json" \
  -d '{"object_key": "...", "public_uuid": "...", "node_id": 1,
       "original_name": "report.pdf", "size_bytes": 204800}'

Authentication

Exchange an email and password for an API token:

curl -X POST https://upload.am/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"your-password"}'

That call needs no Bearer header. It returns a token plus the same object as GET /me. POST /auth/logout revokes that token. You can still create tokens by hand in Account → API. A leaked Bearer still cannot mint new tokens — only the account password can.

Every other request needs:

Authorization: Bearer ua_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
StatusError codeMeaning
401missing_tokenNo Authorization header
401invalid_tokenToken not found or revoked
401invalid_credentialsWrong email or password on /auth/login
403account_disabledAccount suspended

Rate limits

Every endpoint has its own independent limit, counted per token — hitting the ceiling on one endpoint never blocks another. Going over returns 429 with a Retry-After header. Storage quota and the max size of a single file follow your account's plan (see GET /me below) — download speed itself is unmetered on every plan, same as on the website.

Uploading files

Files go straight into object storage over a presigned URL — the upload.am servers see the request headers, never the file bytes in full. It's the same protocol behind the website's own dropzone.

Small files (up to 8 MB)

A single PUT, three calls total — this is the flow shown in the quickstart above:

POST/upload/token→ presigned PUT URL
PUT{upload_url}→ the raw file bytes
POST/upload/confirm→ registers the file in your account

Large files — S3 multipart

The file is split into parts, each one gets its own presigned PUT:

POST/upload/multipart/create
POST/upload/multipart/sign-part→ once per part
POST/upload/multipart/complete
POST/upload/confirm

Any S3-compatible SDK (aws-sdk, boto3…) speaks this part/ETag format natively — nothing upload.am-specific at this step.

Options accepted by /upload/confirm
FieldTypeDescription
passwordstringPassword required to download — same as the website's dropzone
max_downloadsint, 1–1000File is deleted once the limit is hit
link_ttl10m·1h·24h·7dLink expires sooner than the plan's retention, if that's sooner
folder_uuidstringPlace the file into an existing folder. Unknown or foreign uuid → 404 folder_not_found, the file is not silently dropped into the root
sha25664 hex charsChecksum computed on your side, verified on download

Files

GET/filesList — folder_uuid or root. q without a folder searches the whole account
GET/files/{uuid}File details
PATCH/files/{uuid}Rename, set/clear password, set/clear download limit
POST/files/{uuid}/moveMove to a folder (or the root)
POST/files/{uuid}/downloadIssue a download link
DELETE/files/{uuid}Move to trash — 204 empty body
POST/files/{uuid}/restoreRestore from trash
DELETE/files/{uuid}/forcePermanently delete a trashed file — 204
Downloading — the Free-plan wait, without cookies

POST /files/{uuid}/download doesn't ask for the file's own password — that password protects the public /d/ page from strangers; your API token already proved this is your file. This call does not increment download_count and does not consume max_downloads — those apply to public /d/ downloads only. On paid plans the link comes back immediately. On Free, the same 10-second anti-bot wait the website shows applies — call the endpoint twice:

curl -X POST https://upload.am/api/v1/files/b6f1.../download -H "Authorization: Bearer ua_live_xxx"
→ 202 { "status": "waiting", "wait_seconds": 10 }

sleep 10

curl -X POST https://upload.am/api/v1/files/b6f1.../download -H "Authorization: Bearer ua_live_xxx"
→ 200 { "status": "ready", "download_url": "https://files.upload.am/...", "expires_in": 600 }

Folders

GET/foldersList — parent_uuid optional
POST/folders{"name", "parent_uuid"}
POST/folders/ensure{"path", "parent_uuid"} — create or reuse a folder path
PATCH/folders/{uuid}Rename
DELETE/folders/{uuid}Only if empty — files inside move up one level

Shares

A public link to one or more files — with a password, expiry, download limit, burn-after-download, or an email gate.

GET/shares
POST/shares
GET/shares/{uuid}
DELETE/shares/{uuid}Revoke
Example — create a share
curl -X POST https://upload.am/api/v1/shares \
  -H "Authorization: Bearer ua_live_xxx" -H "Content-Type: application/json" \
  -d '{
    "file_uuids": ["b6f1...e9", "a2c3...11"],
    "ttl": "24h",
    "max_downloads": 10,
    "password": "secret",
    "title": "Meeting materials"
  }'

Batches

One link for several just-uploaded files, no password/expiry setup needed — each file keeps its own download page inside. Files that already have a batch_uuid cannot join another group (422 files_not_found). There is no DELETE /batches in v1.

POST/batches{"uuids": [...]}
GET/batches/{uuid}

Plan, features and limits

GET /me returns what the account may do. Read it on every start and after a plan change; never hard-code plan codes.

  • plan.features — keys of included features: esign, ocr, online_editor, templates, work_tools, data_room, backups, block_sync, legal_hold, dlp, sso.
  • entitlements.limits[] — key, used, max (null = unlimited). Keys: storage, file, rooms, portals, household, seats, spaces, api_tokens, active_links, shared_folders, history_days.
  • entitlements.features[] — every feature with allowed and the min_plan that includes it.
  • A locked feature answers 403 {"error":"plan_feature_locked","feature":"…","min_plan":"…"}; an exhausted limit answers 403 {"error":"plan_limit_reached","limit":"…","max":N}.

The complete reference of every endpoint, file fields and error codes: /docs/api.md.

Errors

Validation failures (422) use Laravel's standard shape. Everything else is {"error": "code", "message": "..."}.

StatusMeaning
404{"error":"not_found"} — not found, or not yours. Upload with a bad folder_uuid returns folder_not_found
403plan_feature_locked, plan_limit_reached, child_account, device_wipe_pending, forbidden
423retention_locked (file locked until a date), protected (legal hold), trash_locked
422Validation, plus blocked_extension, blocked_content, weak_password, cannot_shorten
409Conflict — e.g. confirming the same upload twice
410Expired or revoked
413Over the plan's size or storage quota
429Rate limited — see Retry-After
507Storage node temporarily full

Changelog

Every change to the API lands here, dated, the day it ships.

v1.7.0

Business API: rooms, work tools, e-signature, file operations, team administration

  • Team administration in the API: `GET/PATCH /team`, `GET/PATCH /team/policies` (invite domains, link rules, stamp, retention), `GET /team/audit`, `GET /team/audit/export` (CSV), `GET /team/usage`, groups (`/team/groups`), folder grants (`/team/folders/{uuid}/grants`, `/group-grants`), `POST /team/members/{id}/transfer`, shared team Inbox (`/team/inbox`, `/toggle`, `/regenerate`), `GET/PUT /team/encryption`, read-only `GET /team/sso` (SSO is managed in the web app only), `POST /team/trial`.
  • Devices and sign-in: `GET /devices`, `POST /devices/{id}/sign-out`, `POST/DELETE /devices/{id}/wipe`, `POST /me/two-factor/recovery-codes`, `POST /me/export`, `DELETE /me`.
  • API tokens: `GET/POST /tokens`, `DELETE /tokens/{id}` (`403 plan_limit_reached`).
  • Billing: `GET/POST /invoices`, `GET /invoices/{number}/pdf`, `/agreement`, `GET /me/plan` (plan, usage, features with `min_plan`).
  • `GET /vpn/profile`; `GET/PATCH /brand` and logo upload (`/brand/logo/token`, `/confirm`, `DELETE /brand/logo`), personal or team.
  • `GET /team/members` now includes `user_id` for each member.
  • Rooms API: list, create, update and destroy Drop Rooms, client portals and data rooms (`/rooms`), with the public link, deadline and plan limits in every response.
  • Room files and folders: attach your files or whole folders, move files between room folders, remove files, view the room activity feed.
  • Client checklist API: add, list, delete and reopen document, form and approval requests, and set client reminders.
  • Data room API: NDA and Q&A settings, per-document access (open, stamped, view only, hidden), questions and answers, document index and read report (JSON or CSV).
  • Photo selection API: enable client selection with a limit, list the selected files and export them for Lightroom, Capture One or CSV.
  • Templates API: list built-in and own templates, save case-folder templates, create a folder structure from a template, save a room as a template and create a room from a template.
  • New `POST /transfers/lookup`, `POST /transfers`, `GET /transfers`, `POST /transfers/{uuid}/accept|decline|cancel`: send files to another upload.am user (move or copy, 24h/7d/30d request lifetime) and answer incoming requests.
  • New `GET /inbox/items` (files from the public drop link plus incoming transfers waiting for a decision) and `GET /inbox/badge` (counter).
  • New messages API: `GET/POST /messages`, `POST /messages/{id}/read`, `POST /messages/read-all`, `POST /messages/{id}/block`, `GET /messages/blocked`, `DELETE /messages/blocked/{userId}`; `POST /support` sends a support request.
  • New shared folders API: `GET/POST /shared-folders`, `DELETE /shared-folders/{id}`, `GET /shared-folders/{folderUuid}/files`. `POST` answers `403 plan_limit_reached` when the `shared_folders` limit is used up.
  • New household (family) API: `GET /household`, `POST /household/invite`, `POST /household/members/{id}/child`, `DELETE /household/members/{id}`, `POST /household/leave`, `POST /household/album`, `GET /household/members/{id}/files`, `POST /household/invites/{token}/accept|decline`.
  • `GET/POST /projects`, `GET/PATCH/DELETE /projects/{uuid}` — projects with due dates and an optional client; `POST /projects/{uuid}/tasks`, `PATCH|DELETE /projects/{uuid}/tasks/{id}`, `POST /projects/{uuid}/tasks/{id}/attach` — tasks with assignee, due date, done flag and attached files; `GET /tasks` — my tasks filtered by `status`, `due`, `project`. Plan feature `work_tools`.
  • `GET/POST /clients`, `GET/PATCH/DELETE /clients/{uuid}`, `POST /clients/{uuid}/docs`, `PATCH|DELETE /clients/{uuid}/docs/{id}` — clients with contracts and invoices linked to files; the list returns unpaid and overdue totals per currency in `meta`. Plan feature `work_tools`.
  • `GET/POST /knowledge-base`, `GET/PATCH/DELETE /knowledge-base/{uuid}`, `POST /knowledge-base/{uuid}/share` — Markdown knowledge base with search (`q`), categories and an optional secret public link. Plan feature `work_tools`.
  • `GET/POST /automations`, `POST /automations/{id}/toggle`, `DELETE /automations/{id}` — "if a file arrives, then move / label / lock / email / create a task" rules with conditions on folder, extension and name, and a run counter. Plan feature `work_tools`.
  • `GET/POST /signatures`, `GET /signatures/{uuid}`, `POST /signatures/{uuid}/cancel`, `POST /signatures/{uuid}/signers/{id}/resend`, `GET /signature-templates`, `DELETE /signature-templates/{id}` — e-signature for PDFs: up to 10 signers, sequential or parallel, expiry, message, templates, audit log, and temporary links to the signed PDF and completion certificate. Plan feature `esign`.
  • All of these accept the `X-Upload-Team: ` header to work in a team workspace (read: any non-guest member; write: owner/admin/editor/contributor).
  • Added `POST /bulk`: delete, move, lock, label, to_team and to_personal for files, and delete/move for folders, with a per-uuid result (done, skipped, error) and the same permission, retention-lock and legal-hold checks as the website.
  • Added `POST/DELETE /files/{uuid}/edit-lock` (24-hour editing lock on team files) and the review API: `GET /files/{uuid}/review`, `POST /files/{uuid}/review/comments`, `POST /files/{uuid}/review/comments/{id}/resolve`, `POST /files/{uuid}/review/decision`.
  • Added `GET /files/{uuid}/edit-url` (online editor session for Word, Excel and PowerPoint files; plan feature `online_editor`).
  • Added `POST /files/{uuid}/extract`, `GET /duplicates`, `POST /duplicates/clean`, `GET /trash/expired` and `POST /trash/restore-expired`.
  • Added `GET /rollback/preview` and `POST /rollback` (restore the account, a folder or a team to a date within 90 days).
  • Added `PATCH /shares/{uuid}` (expiry, password, download limit, view-only, watermark, login, IP allow-list, recipient, reminders) and `GET /shares/{uuid}/visits` (visit history with country and device summaries).
  • Added `GET /activity` (account events, share downloads and room events with pagination).
  • `PATCH /folders/{uuid}` now accepts `parent_uuid` to move a folder; added `GET /folders/{uuid}/protection`.
  • `POST /tokens` requires the account password; transfers with `mode: move` refuse files that are locked or under legal hold (`423 retention_locked`).
v1.6.0

Plans, features and limits; documented error codes

  • `GET /me` returns `plan.features` (keys of the features your plan includes) and `entitlements` (`source`, `limits[]` with `key`, `used`, `max` where `max: null` means unlimited, and `features[]` with `allowed` and `min_plan`). Read them on every start instead of hard-coding plan codes.
  • New numeric limits `api_tokens`, `active_links`, `shared_folders`, `history_days`. `POST /shares` answers `403 plan_limit_reached` when one is exhausted.
  • A feature outside the plan answers `403 plan_feature_locked` with `feature` and `min_plan`.
  • `GET /billing/plans` items carry `family`, `price_year_cents`, `household_max` and `features`; plans not on sale are not returned.
  • File objects carry `label`, `sensitive`, `tags`, `has_text`, `retain_until` and `legal_hold`.
  • `GET /device` and `POST /device/wiped` (remote wipe of a lost device); `403 device_wipe_pending` until the wipe is confirmed.
  • The affiliate payout wallet fields and `PATCH /me/payout-wallet` were removed on 2026-10-11.
v1.5.0

Block-level sync and text search

  • `GET /files/{uuid}/blocks`, `POST /files/{uuid}/delta` and `POST /files/{uuid}/delta/{id}/complete` — send only changed 8–64 MB blocks of a large file; unchanged blocks are copied inside the storage; the result is a new file version.
  • `GET /files?q=` also searches the recognized text of images and PDFs. Files carry `tags` and `has_text`.
v1.4.0

Teams

  • `GET /teams` — your teams with role, guest flag and seat usage.
  • `GET /team/members`, `POST /team/invites` (role or `guest: true`), `DELETE /team/invites/{id}`, `PATCH /team/members/{id}` (role: admin, editor, contributor, viewer, member; status) and `DELETE /team/members/{id}` (files pass to the team owner). Select the team with the `X-Upload-Team` header; changes need a team admin.
v1.3.0

Data protection

  • `GET /protection` and `PATCH /protection/retention` — retention periods for the trash and old versions (account or team via `X-Upload-Team`).
  • `POST /files/{uuid}/lock` and `POST /folders/{uuid}/lock` — lock files until a date (cannot be deleted, renamed or overwritten; only extendable). New file fields: `retain_until`, `legal_hold`, `label`, `sensitive`.
  • `GET/POST /holds` and `POST /holds/{uuid}/release` — legal holds for teams. Errors `423 retention_locked` and `423 protected`.
  • `GET /backups`, `POST /backups/restore-requests`, `GET /alerts`, `POST /alerts/{id}/dismiss|restore` — server backups, restore requests and ransomware alerts.
  • `GET /sensitive` and `POST /files/{uuid}/label` — confidential data detection and labels.
v1.2.3

Profile avatar

  • `GET /me` and `PATCH /me` now include `avatar_url`.
  • `POST /me/avatar/token` + `POST /me/avatar/confirm` — upload or replace your profile picture (2MB limit, same presigned flow as regular files).
v1.2.2

Account management

  • `PATCH /me` to change your name/email, `PATCH /me/password` to change your password (requires current password) — by request from desktop client users who don't want to open the website just to update their profile.
v1.2.1

Account-wide file listing

  • `GET /files?all=1` lists every file in your account in one flat, paginated feed (up to 200 per page) — useful for client-side tools like duplicate detection by `sha256`.
v1.2.0

Trash, file versions, Upload Inbox

  • `GET /files?trashed=1` lists deleted files; `GET /files?inbox_pending=1` lists files awaiting review from your Upload Inbox.
  • `GET /files/{uuid}/versions`, `.../versions/{v}/restore`, `.../versions/{v}/download` — file version history.
  • `POST /files/{uuid}/accept` and `.../decline` for Upload Inbox submissions.
  • `GET/PATCH /inbox`, `POST /inbox/regenerate-token` — manage your Upload Inbox link and rules.
v1.1.0

Login, logout, folder paths

  • `POST /auth/login` — email and password return a Bearer token. No token needed for this call.
  • `POST /auth/logout` revokes the current token.
  • `POST /folders/ensure` creates a folder path (`Contracts/2024`) or returns the existing one.
v1.0.2

File search and response fields

  • `GET /files?q=` without `folder_uuid` searches all files in the account, not only the root.
  • `download_count` is always an integer (`0` if none).
  • `POST /batches` includes `batch_uuid` on each file in the same response.
v1.0.1

Confirm response, folders, download counter

  • `POST /upload/confirm` returns the standard file object (`data`), same as `GET /files/{uuid}`.
  • New field `batch_uuid` on file objects.
  • Invalid `folder_uuid` on upload returns `404`.
  • `POST /files/{uuid}/download` no longer counts against `max_downloads`.
  • Consistent JSON for `404` responses.
v1.0

Initial public release

  • Bearer token authentication, managed from the dashboard (Account → API).
  • File uploads via presigned S3 URLs — single PUT for small files, multipart for large ones. Same protocol the website itself uses.
  • Files: list, get, rename, set password, set download limit, move, trash, restore, permanently delete, get a download link.
  • Folders: list, create, rename, delete.
  • Shares: create password-protected / time-limited / download-limited public links, list, revoke.
  • Batches: group already-uploaded files under one shareable link.
  • `GET /me` for account, plan, and quota information.