Getting started

Quickstart

Add uploads in a few minutes. Use the Try it panel on the right with your real API key and project ID — curl commands update automatically.

1. Create an API key and project

Sign up, open the dashboard, create a project, and generate an API key with files.write (and files.read if you want to poll session status or download files).

Copy these into your server environment:

  • REUPLOAD_API_KEY — full key (starts with ru_, shown once)
  • REUPLOAD_PROJECT_ID — UUID from project settings

2. Verify your key

GET /public/whoami confirms the key and lists projects (id, name, and uploadCorsOrigins when set) your key can use. Run the curl in the Try it panel.

whoami response
{
  "apiKeyId": "uuid",
  "workspaceId": "uuid",
  "name": "Production",
  "permissions": ["files.read", "files.write"],
  "allProjects": false,
  "projects": [
    {
      "id": "your-project-uuid",
      "name": "Production",
      "uploadCorsOrigins": ["https://app.example.com"]
    }
  ]
}

3. Upload a file

Pick one path — both end with the same processing and webhooks.

Path A — CDN flow (browser or client uploads)

Your server creates a session; the client PUTs bytes to a signed CDN URL; your server completes. Best when the browser uploads directly to storage.

Create an upload session

POST /uploads/session with projectId, filename, contentType, and exact byte size.

session response
{
  "uploadId": "uuid",
  "fileId": "uuid",
  "uploadUrl": "https://cdn.reupload.dev/v1/upload/eyJ2Ijox...",
  "expiresIn": 300
}

Return uploadUrl and uploadId to your client. Keep fileId if you need it before processing finishes.

Upload bytes to the CDN

PUT the file to uploadUrl with the same Content-Type and body size you declared. This is not a Reupload API call.

For browser apps, see Browser uploads or the React/Next + Node.js guide (CDN flow).

Complete the upload

POST /uploads/complete with uploadId returns 202:

JSON
{ "fileId": "uuid", "status": "processing" }

Path B — Server direct (your backend uploads)

One multipart/form-data request from your server. Use when users send files to your API first and you forward them to Reupload — no CDN PUT or upload CORS.

direct upload
curl -s -X POST 'https://api.reupload.dev/api/v1/uploads/direct' \
  -H 'Authorization: Bearer ru_...' \
  -F 'projectId=your-project-uuid' \
  -F 'filename=docs/report.pdf' \
  -F 'file=@./report.pdf;type=application/pdf'
direct upload response
{
  "uploadId": "uuid",
  "fileId": "uuid",
  "status": "processing"
}

Direct upload stores your file before the response returns

202 + processing means background work (scan, finalize, quotas) is still running — not that the upload failed. Use webhooks or poll GET /uploads/session/:uploadId for path, url, and confirmed sizeBytes. Why this design →

Full proxy example: Server-side upload guide. Details: Server-side uploads.

4. Wait for processing

The upload HTTP call succeeding does not mean the file is ready to serve. Direct upload already stored your bytes; CDN upload finished the PUT — in both cases Reupload still scans, finalizes, and emits webhooks in the background. Poll GET /uploads/session/:uploadId until session.status is COMPLETED — the response then includes a top-level file object with path, url, and sizeBytes (same shape as webhook data). Or handle a file.uploaded webhook. Applies to both upload paths. Why direct upload returns 202 →

5. Download or delete

GET /files/:fileId/access returns a signed CDN URL. DELETE /files/:fileId requires files.delete.

Endpoint matrix and quotas: API reference.

SDKs

Use official packages instead of hand-rolled fetch: @reupload/sdk (server), @reupload/client (browser), @reupload/react (React uploaders). Packages overview.