Reference

REST API

Upload files, create direct upload sessions, inspect share metadata, and download files without an SDK. This page documents the current public API surface.

Overview

The API is public and currently requires no user API key. Small files can be uploaded with a single multipart request. Larger files use a direct R2 upload session created by the service. Both upload flows accept either a preset duration or a fixed ISO 8601 expiresAt value with an explicit timezone.

Current public upload policy

Anonymous uploads are limited to 10 uploads per rolling 30 days, notification emails are capped at 3 recipients, audio uploads are blocked, and anonymous video uploads at or above 700 MB are rejected.

Inline

POST /api/upload accepts multipart/form-data with the file and delivery options.

Direct

POST /api/uploads creates a direct upload session, returns a presigned R2 upload URL, and is finalized with /complete.

Inline upload

Use the inline upload endpoint for smaller files. This is the simplest path and works well for scripts and small automation jobs.

Field Type Notes
file multipart file Required.
duration string Optional. One of 1h, 24h, 3d, 7d. Mutually exclusive with expiresAt.
expiresAt string Optional. Fixed expiry date in ISO 8601 format with an explicit timezone, for example 2026-04-25T18:00:00.000Z or 2026-04-25T20:00:00+02:00. Mutually exclusive with duration.
password string Optional. Protects downloads.
maxDownloads string/integer Optional. Positive integer, normalized up to 10,000.
notify repeated string Optional. Up to 3 notification email addresses.

POST /api/upload

curl -X POST https://dlvr.sh/api/upload \
  -F "file=@./report.pdf" \
  -F "duration=24h" \
  -F "password=secret" \
  -F "maxDownloads=10" \
  -F "notify=team@example.com"

Success response

{
  "id": "a1c94e2f",
  "url": "https://dlvr.sh/f/a1c94e2f/",
  "expires": "2026-04-16T14:00:00.000Z",
  "downloads": 0,
  "maxDownloads": 10,
  "passwordRequired": true,
  "filename": "report.pdf",
  "size": 128044
}

Direct upload for larger files

Larger files use a session-based direct upload flow. First create a session, then upload the file to the provided R2 URL, then finalize the upload. The session request can include either duration or expiresAt.

Deployment dependency

If direct upload signing is not configured on the deployment, POST /api/uploads returns 503.

1. Create upload session

curl -X POST https://dlvr.sh/api/uploads \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "artifact.zip",
    "contentType": "application/zip",
    "size": 104857600,
    "duration": "24h",
    "password": "secret",
    "maxDownloads": 5,
    "notifyEmails": ["team@example.com"]
  }'

2. Upload file to returned uploadUrl

curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: application/zip" \
  --data-binary "@./artifact.zip"

3. Finalize the upload

curl -X POST "https://dlvr.sh/api/uploads/$UPLOAD_ID/complete"

The session creation response includes uploadId, shareId, url, expiresAt, uploadUrl, and any headers required for the direct upload request.

The direct-upload session endpoint enforces the same anonymous quota, recipient limit, and media policy before creating the session. Finalization re-checks the media policy before the share link becomes active.

Metadata and download

Use metadata endpoints when you need to inspect a file before downloading it or render your own client-side download experience.

GET /api/files/:id

curl https://dlvr.sh/api/files/a1c94e2f

GET /api/files/:id response

{
  "id": "a1c94e2f",
  "filename": "artifact.zip",
  "size": 10485760,
  "expires": "2026-04-16T14:00:00.000Z",
  "passwordRequired": false,
  "downloads": 0,
  "maxDownloads": null,
  "remainingDownloads": null,
  "expired": false
}

POST /api/files/:id/download

curl -X POST https://dlvr.sh/api/files/a1c94e2f/download \
  -F "password=secret" \
  -o artifact.zip

The download endpoint enforces password checks, expiry, and max-download rules before streaming the file.

Errors and status codes

Status Meaning
400 Missing file, bad JSON, unsupported duration, or malformed parameters.
401 Password required or incorrect.
404 Share or underlying object not found.
409 Direct upload incomplete, or download limit reached during claim.
410 File has expired.
413 File exceeds the inline or overall upload limit.
415 Upload blocked by media policy, including audio files and large anonymous videos.
429 Anonymous upload quota exceeded for the rolling 30-day window.
503 Direct upload is not configured on the deployment.