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.
Try out API endpoints with your own keys in our interactive playground.
Open API Playground