API · Uploads

Client-side uploads (CDN)

Your server creates an upload session and returns a signed CDN URL. The client PUTs file bytes to that URL, then your server calls complete. This is not a request to the Reupload API for the file body — only session create and complete hit the API.

Uploads overview · Server-side (direct) · Browser uploads (CORS) · @reupload/client · @reupload/react

Architecture

CDN flow: your server creates a session with POST /uploads/session; the client PUTs file bytes to uploadUrl; your server calls POST /uploads/complete. Only session create and complete hit the Reupload API — the file body goes to the CDN.

Client

Browser / app

Your server

Backend

Reupload

API

CDN

Storage

POST /uploads/session
uploadUrl, uploadId
uploadUrl, uploadId
PUT file bytes
POST /uploads/complete
202 processing
RequestResponse

Stack walkthrough with a Node.js proxy: React/Next + Node.js. Browser CORS for the CDN PUT: Browser uploads.

1. Create upload session

POST /uploads/session — requires files.write. The API key must have access to the projectId in the body.

Request body

request body
{
  "projectId": "uuid",
  "filename": "docs/report.pdf",
  "contentType": "application/pdf",
  "size": 502400,
  "isPublic": true
}
  • size must match the exact bytes the client will upload
  • contentType must be allowed and match the extension in filename
  • filename may include / paths (e.g. docs/report.pdf). Folders are created under the project;originalName keeps the full path, stored name is the basename.
  • isPublic (optional) — when true, the file is publicly accessible via CDN after processing. Default false.

Response

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

Return uploadUrl and uploadId to the client.uploadUrl expires after expiresIn seconds.

Request
curl -s -X POST 'https://api.reupload.dev/api/v1/uploads/session' \
  -H 'Authorization: Bearer ru_your_api_key_here' \
  -H 'Content-Type: application/json' \
  -d '{
    "projectId": "00000000-0000-4000-8000-000000000001",
    "filename": "your-file.pdf",
    "contentType": "application/pdf",
    "size": 0
  }'

Select a file in the Try it panel — session and upload will use the same file metadata.

2. Client upload (signed URL)

PUT file bytes to uploadUrl with:

  • Content-Type matching the session
  • Body size exactly matching declared size

Browser uploads require project CORS origins — see Browser uploads. Stack guide: React/Next + Node.js (CDN flow).

Request
curl -X PUT '$UPLOAD_URL_FROM_RESPONSE' \
  -H 'Content-Type: application/pdf' \
  --data-binary '@./your-file.pdf'

Select a file in the Try it panel — session and upload will use the same file metadata.

3. Complete upload

POST /uploads/complete with uploadId — returns 202 Accepted.

request body
{
  "uploadId": "uuid"
}

Response

complete response
{
  "fileId": "uuid",
  "status": "processing"
}

Reupload verifies the object in storage, then processes asynchronously (metadata, usage, webhooks).

Request
curl -s -X POST 'https://api.reupload.dev/api/v1/uploads/complete' \
  -H 'Authorization: Bearer ru_your_api_key_here' \
  -H 'Content-Type: application/json' \
  -d '{"uploadId": "00000000-0000-4000-8000-000000000002"}'

Get upload session

GET /uploads/session/:uploadId — requires files.read. Use to poll until COMPLETED.

Response

While processing, only session is returned. When session.status is COMPLETED, the response adds a top-level file object — same fields as webhook file.uploaded data (path, url, sizeBytes, etc.).

session (processing)
{
  "session": {
    "id": "uuid",
    "workspaceId": "uuid",
    "projectId": "uuid",
    "fileId": "uuid",
    "status": "PROCESSING",
    "expectedSize": 502400,
    "expectedMime": "application/pdf",
    "expiresAt": "2026-05-20T14:35:00.000Z",
    "completedAt": null,
    "failureReason": null,
    "createdAt": "2026-05-20T14:30:00.000Z"
  }
}
session (completed)
{
  "session": {
    "id": "uuid",
    "status": "COMPLETED",
    "fileId": "uuid",
    "expectedSize": 502400,
    "expectedMime": "application/pdf",
    "completedAt": "2026-05-30T14:30:00.000Z"
  },
  "file": {
    "fileId": "uuid",
    "projectId": "uuid",
    "path": "projects/uuid/files/uuid/report.pdf",
    "name": "report.pdf",
    "mimeType": "application/pdf",
    "sizeBytes": 502400,
    "url": "https://cdn.example.com/v1/download/...",
    "urlExpiresAt": "2026-05-30T14:35:00.000Z",
    "isPublic": false
  }
}

Session statuses

  • PENDING — awaiting client PUT
  • PROCESSING — complete received, worker running
  • COMPLETED — file ready
  • FAILED / CANCELLED — terminal
Request
curl -s 'https://api.reupload.dev/api/v1/uploads/session/00000000-0000-4000-8000-000000000002' \
  -H 'Authorization: Bearer ru_your_api_key_here'

Cancel upload session

DELETE /uploads/session/:uploadId — only for PENDING or UPLOADING sessions.

JSON
{ "success": true }
Request
curl -s -X DELETE 'https://api.reupload.dev/api/v1/uploads/session/00000000-0000-4000-8000-000000000002' \
  -H 'Authorization: Bearer ru_your_api_key_here'

Errors

Common codes: VALIDATION_ERROR, QUOTA_EXCEEDED, RATE_LIMITED. Full list: Errors.