REST API reference for file uploads, BYOB storage, webhooks, and more.
Base URL
https://api.r2upload.io/v1Sign up for free and get your API keys from the dashboard.
Generate an API key with the permissions you need.
Use our API to upload files directly or from URLs.
All API requests require authentication using an API key. Include your API key in the X-API-Key header:
curl -X GET "https://api.r2upload.io/v1/external/files" \
-H "X-API-Key: r2u_live_xxxxxxxxxxxxx"curl -X POST "https://api.r2upload.io/v1/external/files/upload" \
-H "X-API-Key: r2u_live_xxxxxxxxxxxxx" \
-F "file=@/path/to/file.pdf" \
-F "folder=uploads" \
-F "is_public=false" \
-F "content_disposition=attachment"curl -X POST "https://api.r2upload.io/v1/external/files/upload-from-url" \
-H "X-API-Key: r2u_live_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/image.jpg",
"filename": "my-image.jpg",
"folder": "uploads",
"is_public": false,
"async": true
}'| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/external/files/upload | Upload a file directly (multipart/form-data) |
| POST | /v1/external/files/upload-from-url | Upload from a remote URL (sync or async) |
| POST | /v1/external/files/bulk-upload-from-urls | Bulk upload from multiple URLs at once |
| Method | Endpoint | Description |
|---|---|---|
| GET | /v1/external/files | List all uploads with pagination & filtering |
| GET | /v1/external/files/{uuid} | Get upload details by UUID |
| PATCH | /v1/external/files/{uuid} | Update file metadata (filename, folder, visibility) |
| DELETE | /v1/external/files/{uuid} | Move file to trash (recoverable for 30 days) |
| POST | /v1/external/files/{uuid}/cancel | Cancel a pending or in-progress upload |
| POST | /v1/external/files/bulk-cancel | Cancel multiple pending uploads at once |
| Method | Endpoint | Description |
|---|---|---|
| GET | /v1/external/files/trash | List all trashed files |
| POST | /v1/external/files/{uuid}/restore | Restore a trashed file |
| DELETE | /v1/external/files/{uuid}/force | Permanently delete a file (irreversible) |
| DELETE | /v1/external/files/trash | Empty trash — permanently delete all trashed files |
| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/external/files/check-hash | Check if a file already exists by SHA-256 hash |
| GET | /v1/external/files/deduplication-stats | Get deduplication savings statistics |
{
"success": true,
"data": {
"uuid": "a1b2c3d4-e5f6-7890...",
"filename": "photo.jpg",
"download_url": "https://...",
"size_bytes": 1024000,
"size_formatted": "1000 KB",
"mime_type": "image/jpeg",
"upload_time_ms": 150
}
}{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "The file is required.",
"details": {
"file": ["The file field is required."]
}
}
}API requests are rate limited based on your subscription plan. Rate limit information is included in response headers.
| Plan | Requests/Month | Burst Limit |
|---|---|---|
| Free | 500 | 10/min |
| Starter | 100,000 | 100/min |
| Pro | 1,000,000 | 1,000/min |
The API uses consistent error codes across all endpoints. Handle these in your integration for robust error handling.
| Code | HTTP Status | Description |
|---|---|---|
| VALIDATION_ERROR | 422 | Request validation failed |
| UNAUTHENTICATED | 401 | Missing or invalid authentication |
| FORBIDDEN | 403 | Insufficient permissions |
| NOT_FOUND | 404 | Resource not found |
| RATE_LIMITED | 429 | Too many requests |
| STORAGE_ERROR | 500 | Storage operation failed |
| QUOTA_EXCEEDED | 403 | Plan quota exceeded |
| FILE_TOO_LARGE | 413 | File exceeds size limit |
| INVALID_FILE_TYPE | 415 | File type not allowed |
Receive real-time notifications when events occur. Configure webhooks in your dashboard to receive HTTP POST requests.
upload.completed - File uploaded successfullyupload.failed - Upload failedupload.deleted - File was deletedstorage.connected - Storage connection addedstorage.disconnected - Storage connection removedX-Webhook-Signature - HMAC-SHA256 signatureX-Webhook-Event - Event typeX-Webhook-ID - Unique delivery IDContent-Type - application/json{
"event": "upload.completed",
"timestamp": "2025-01-15T10:30:00Z",
"data": {
"upload": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"filename": "document.pdf",
"object_key": "uploads/document.pdf",
"download_url": "https://your-bucket.r2.dev/uploads/document.pdf",
"mime_type": "application/pdf",
"size_bytes": 1048576,
"size_formatted": "1 MB",
"file_hash": "sha256:abc123...",
"is_public": true,
"created_at": "2025-01-15T10:29:55Z"
}
}
}Connect any S3-compatible storage provider to use your own buckets. Supports AWS S3, Cloudflare R2, DigitalOcean Spaces, Backblaze B2, Wasabi, MinIO, and more.
curl -X POST https://api.r2upload.io/v1/external/files/upload \
-H "X-API-Key: r2u_live_xxxxxxxxxxxxx" \
-F "[email protected]" \
-F "folder=uploads" \
-F "is_public=false"Tip: Files are automatically routed to your default storage connection. Manage connections, view per-bucket stats, and test connectivity from the Storage dashboard.
When using Bring Your Own Bucket (BYOB), files are uploaded directly from the browser to your storage bucket via high-speed presigned multipart uploads. To enable support for file sizes up to 5 TB per file (upgraded from the previous 5 GB limit) even on the Free plan, you must configure a Cross-Origin Resource Sharing (CORS) policy on your storage bucket.
To keep your bucket secure, only allow trusted origins. For the dashboard and playground to work, you must add (https://r2upload.io) to the AllowedOriginslist. If you are uploading directly from your own application via our client SDKs, remember to also append your app's domain (e.g., https://your-app.com).
Go to the Cloudflare Dashboard → R2→ select your bucket → Settingstab → find CORS Policy and apply the following JSON:
[
{
"AllowedOrigins": [
"https://r2upload.io",
"http://your-app.com"
],
"AllowedMethods": [
"GET",
"PUT",
"POST",
"DELETE",
"HEAD"
],
"AllowedHeaders": [
"*"
],
"ExposeHeaders": [
"ETag"
],
"MaxAgeSeconds": 3600
}
]Try out API endpoints with your own keys in our interactive playground.
Open API Playground