-
Notifications
You must be signed in to change notification settings - Fork 10
API Reference
Complete reference for all API endpoints provided by R2-Manager-Worker.
All API endpoints are relative to your Worker's base URL:
https://YOUR_DOMAIN/api
For local development: http://localhost:8787/api
All API endpoints (except signed file downloads) require a valid Cloudflare Access JWT token. This is automatically handled by Cloudflare Access when users authenticate via the web interface.
The JWT token is passed in the cf-access-jwt-assertion cookie or header.
API endpoints are protected by tiered rate limiting to prevent abuse and ensure fair resource allocation. Rate limits are enforced per authenticated user (identified by email) per Cloudflare location.
| Tier | Operations | Limit | Period | Example Endpoints |
|---|---|---|---|---|
| READ | GET operations | 300 requests | 60 seconds |
GET /api/buckets, GET /api/files/:bucket, GET /api/search
|
| WRITE | POST/PATCH operations | 100 requests | 60 seconds |
POST /api/files/:bucket/upload, PATCH /api/buckets/:name
|
| DELETE | DELETE operations | 30 requests | 60 seconds |
DELETE /api/buckets/:name, DELETE /api/files/:bucket/:file
|
- Per-User Limits: Each authenticated user has independent rate limits based on their email address
- Per-Location Enforcement: Limits are enforced at each Cloudflare location independently
- Eventually Consistent: Rate limit counters are eventually consistent across the network
- Automatic Classification: Endpoints are automatically classified by HTTP method and path
When a rate limit is exceeded, the API returns a 429 Too Many Requests response:
Response Status: 429 Too Many Requests
Response Headers:
-
Retry-After- Seconds to wait before retrying (typically 60) -
X-RateLimit-Limit- Maximum requests allowed in the period -
X-RateLimit-Period- Time period in seconds (60) -
X-RateLimit-Tier- Which tier was exceeded (READ,WRITE, orDELETE)
Response Body:
{
"error": "Rate limit exceeded",
"message": "You have exceeded the read operation rate limit of 100 requests per 60 seconds. Please wait before retrying.",
"tier": "READ",
"limit": 100,
"period": 60,
"retryAfter": 60
}Rate limiting is automatically disabled for localhost development (http://localhost:*) to simplify testing and development workflows.
-
Implement Retry Logic: When receiving a
429response, wait the duration specified inRetry-Afterheader before retrying - Batch Operations: Use bulk endpoints where available to minimize API calls
- Cache Results: Cache frequently accessed data to reduce redundant API calls
- Monitor Headers: Track rate limit headers to understand usage patterns
- Handle Gracefully: Display user-friendly messages when rate limits are reached
All responses are JSON with the following general structure:
Success Response:
{
"success": true,
"result": { ... }
}Error Response:
{
"error": "Error message description",
"details": "Additional error details (optional)"
}List all R2 buckets in your account.
GET /api/bucketsResponse:
{
"result": {
"buckets": [
{
"name": "my-bucket",
"creation_date": "2024-01-01T00:00:00.000Z",
"size": 1048576
}
]
}
}Notes:
- System buckets (e.g.,
r2-bucket,sqlite-mcp-server-wiki) are automatically filtered out - Bucket size is calculated by iterating through all objects (may be slow for large buckets)
Create a new R2 bucket.
POST /api/bucketsRequest Body:
{
"name": "new-bucket-name"
}Bucket Naming Requirements:
- Only lowercase letters (a-z), numbers (0-9), and hyphens (-)
- Cannot begin or end with a hyphen
- Must be 3-63 characters in length
Response:
{
"result": {
"bucket": {
"name": "new-bucket-name",
"creation_date": "2024-01-01T00:00:00.000Z"
}
}
}Delete an R2 bucket.
DELETE /api/buckets/:nameURL Parameters:
-
:name- The bucket name to delete
Query Parameters:
-
force(optional) - Set totrueto delete all objects in the bucket first- Example:
/api/buckets/my-bucket?force=true
- Example:
Response:
{
"success": true
}Important Notes:
- Without
force=true, the bucket must be empty - Force delete will iterate through all objects and delete them in batches
- Large buckets may take time to delete with force enabled
- Rate limiting delays are built-in to avoid API throttling
Rename an R2 bucket by creating a new bucket, copying all objects, and deleting the old bucket.
PATCH /api/buckets/:nameURL Parameters:
-
:name- The current bucket name
Request Body:
{
"newName": "new-bucket-name"
}Response:
{
"success": true,
"newName": "new-bucket-name"
}Important Notes:
- This is not a native R2 operation - it performs copy + delete
- All objects are copied to the new bucket, then the old bucket is deleted
- Metadata is preserved during the copy operation
- Large buckets may take significant time to rename
- Ensure adequate rate limits during this operation
List objects in a bucket with pagination support.
GET /api/files/:bucketURL Parameters:
-
:bucket- The bucket name
Query Parameters:
-
limit(optional, default: 20) - Number of objects to return per page -
cursor(optional) - Pagination cursor from previous response -
skipCache(optional, default: false) - Set totrueto bypass cache
Response:
{
"objects": [
{
"key": "file.jpg",
"size": 1048576,
"uploaded": "2024-01-01T00:00:00.000Z",
"url": "https://your-domain.com/api/files/bucket/download/file.jpg?ts=123456&sig=abc123"
}
],
"pagination": {
"cursor": "next-page-cursor",
"hasMore": true
}
}Notes:
- Files are sorted by last modified date (newest first)
- The
urlfield contains a signed URL for downloading the file - Files in the
assets/folder are automatically filtered out - Set
skipCache=truewhen you need fresh data after uploads/deletions
Upload a file to a bucket with support for chunked uploads.
POST /api/files/:bucket/uploadURL Parameters:
-
:bucket- The destination bucket name
Headers:
-
X-File-Name(required) - The file name (URL-encoded if needed) -
X-Chunk-Index(optional, default: 0) - Zero-based chunk index for multi-part uploads -
X-Total-Chunks(optional, default: 1) - Total number of chunks -
X-Chunk-MD5- MD5 checksum of the chunk for integrity verification
Request Body:
-
multipart/form-datawith afilefield containing the file data
Response:
{
"success": true,
"timestamp": "2024-01-01T00:00:00.000Z",
"etag": "5d41402abc4b2a76b9719d911017c592",
"chunkIndex": 0
}Response Fields:
-
etag- The ETag returned by R2, used for integrity verification -
chunkIndex- The index of the uploaded chunk
Upload Limits:
- Application supports up to 500MB per file
- Cloudflare enforces plan-based limits:
- Free/Pro: 100MB maximum
- Business: 200MB maximum
- Enterprise: 500MB maximum
Chunked Upload Example: For a 50MB file split into 5 chunks:
- Upload chunk 0:
X-Chunk-Index: 0,X-Total-Chunks: 5 - Upload chunk 1:
X-Chunk-Index: 1,X-Total-Chunks: 5 - Continue for all chunks...
Generate a signed URL for secure file sharing.
GET /api/files/:bucket/signed-url/:fileURL Parameters:
-
:bucket- The bucket name -
:file- The file key (URL-encoded if needed)
Response:
{
"success": true,
"url": "https://your-domain.com/api/files/bucket/download/file.jpg?ts=123456&sig=abc123"
}Security Features:
- URLs include HMAC-SHA256 signatures to prevent tampering
- Each URL includes a timestamp for uniqueness
- Signatures are validated on download
- Links remain valid indefinitely but can only download the specific file
Download a file using a signed URL.
GET /api/files/:bucket/download/:file?ts=TIMESTAMP&sig=SIGNATUREURL Parameters:
-
:bucket- The bucket name -
:file- The file key (URL-encoded if needed)
Query Parameters:
-
ts(required) - Timestamp included in signature -
sig(required) - HMAC signature for validation
Response:
- Binary file data with appropriate
Content-Typeheader -
Content-Disposition: attachmentheader to trigger download
Error Responses:
-
403 Forbidden- Invalid signature -
404 Not Found- File not found -
500 Internal Server Error- Download failed
Notes:
- This endpoint does NOT require Cloudflare Access authentication
- Signature validation ensures only authorized URLs can download files
- URLs are generated by the "Generate Signed URL" endpoint
Rename a file within the same bucket.
PATCH /api/files/:bucket/:file/renameURL Parameters:
-
:bucket- The bucket name -
:file- The file key (URL-encoded if needed)
Request Body:
{
"newKey": "new-filename.pdf"
}Response:
{
"success": true,
"newKey": "new-filename.pdf"
}Process:
- Validates that the new key doesn't already exist
- Fetches file from source location
- Preserves content type and metadata
- Creates file with new key
- Deletes original file
File Name Validation:
- Cannot be empty
- Blocks invalid characters:
< > : " | ? * - Prevents Windows reserved names (CON, PRN, AUX, NUL, COM1-9, LPT1-9)
- Checks for existing files with same name
Error Handling:
-
400 Bad Request- Missing or invalid new key -
404 Not Found- Source file not found -
409 Conflict- File with new name already exists -
500 Internal Server Error- Rename operation failed
Important Notes:
- If only a filename is provided (no path), the file's directory path is preserved
- Full paths can be provided to rename and move in one operation
- Original file is deleted after successful rename
- Operation cannot be undone
Delete a single file from a bucket.
DELETE /api/files/:bucket/delete/:fileURL Parameters:
-
:bucket- The bucket name -
:file- The file key (URL-encoded if needed)
Response:
{
"success": true
}Move a file to another bucket or folder within the same/different bucket.
POST /api/files/:bucket/:file/moveURL Parameters:
-
:bucket- The source bucket name -
:file- The file key (URL-encoded if needed)
Request Body:
{
"destinationBucket": "target-bucket",
"destinationPath": "optional/folder/path"
}Request Body Parameters:
-
destinationBucket(required) - Target bucket name -
destinationPath(optional) - Destination folder path within the target bucket- Leave empty to move to bucket root
- Include folder path to move to specific folder (e.g.,
"images/thumbnails") - Path will be normalized (trailing slash added if needed)
Response:
{
"success": true
}Process:
- Fetch file from source bucket
- Preserve content type and metadata
- Construct destination key:
destinationPath + "/" + filename - Upload to destination bucket with computed key
- Delete from source bucket
Examples:
# Move file to root of different bucket
POST /api/files/bucket-a/report.pdf/move
{"destinationBucket": "bucket-b"}
# Result: bucket-b/report.pdf
# Move file to folder in different bucket
POST /api/files/bucket-a/report.pdf/move
{"destinationBucket": "bucket-b", "destinationPath": "archives/2024"}
# Result: bucket-b/archives/2024/report.pdf
# Move file to folder in same bucket
POST /api/files/my-bucket/temp/document.pdf/move
{"destinationBucket": "my-bucket", "destinationPath": "archives"}
# Result: my-bucket/archives/document.pdfError Handling:
-
400 Bad Request- Missing destination bucket or source equals destination (same path) -
404 Not Found- Source file not found -
500 Internal Server Error- Copy or delete failed
Important Notes:
- Same-bucket moves are allowed when
destinationPathdiffers from source path - Only the filename is preserved; full source path is not kept
- Original file is deleted after successful move
Copy a file to another bucket or folder within the same/different bucket.
POST /api/files/:bucket/:file/copyURL Parameters:
-
:bucket- The source bucket name -
:file- The file key (URL-encoded if needed)
Request Body:
{
"destinationBucket": "target-bucket",
"destinationPath": "optional/folder/path"
}Request Body Parameters:
-
destinationBucket(required) - Target bucket name -
destinationPath(optional) - Destination folder path within the target bucket- Leave empty to copy to bucket root
- Include folder path to copy to specific folder (e.g.,
"backups/daily") - Path will be normalized (trailing slash added if needed)
Response:
{
"success": true
}Process:
- Fetch file from source bucket
- Preserve content type and metadata
- Construct destination key:
destinationPath + "/" + filename - Upload to destination bucket with computed key
- Source file remains unchanged
Examples:
# Copy file to root of different bucket
POST /api/files/bucket-a/data.csv/copy
{"destinationBucket": "bucket-b"}
# Result: bucket-b/data.csv (original remains at bucket-a/data.csv)
# Copy file to folder in different bucket
POST /api/files/bucket-a/data.csv/copy
{"destinationBucket": "bucket-b", "destinationPath": "backups/monthly"}
# Result: bucket-b/backups/monthly/data.csv
# Copy file to folder in same bucket (duplicate within bucket)
POST /api/files/my-bucket/invoice.pdf/copy
{"destinationBucket": "my-bucket", "destinationPath": "archive/2024"}
# Result: my-bucket/archive/2024/invoice.pdf (original remains at my-bucket/invoice.pdf)Error Handling:
-
400 Bad Request- Missing destination bucket or source equals destination (same path) -
404 Not Found- Source file not found -
500 Internal Server Error- Copy failed
Important Notes:
- Same-bucket copies are allowed when
destinationPathdiffers from source path - Allows creating duplicates within a bucket at different paths
- Only the filename is preserved; full source path is not kept
- Original file remains unchanged
Download multiple files as a ZIP archive.
POST /api/files/:bucket/download-zipURL Parameters:
-
:bucket- The bucket name
Request Body:
{
"files": ["file1.jpg", "file2.pdf", "folder/file3.png"]
}Response:
- Binary ZIP file data
Content-Type: application/zipContent-Disposition: attachment; filename="{bucket-name}-files.zip"
Error Responses:
-
500 Internal Server Error- Failed to fetch files or create ZIP
Notes:
- All files are fetched and compressed in-memory
- File structure is preserved in the ZIP (folders maintained)
- Large file selections may take time to process
List objects and folders in a bucket with pagination support.
GET /api/files/:bucketURL Parameters:
-
:bucket- The bucket name
Query Parameters:
-
limit(optional, default: 20) - Number of objects to return per page -
cursor(optional) - Pagination cursor from previous response -
prefix(optional) - Folder path to list contents from -
skipCache(optional, default: false) - Set totrueto bypass cache
Response:
{
"objects": [
{
"key": "file.jpg",
"size": 1048576,
"uploaded": "2024-01-01T00:00:00.000Z",
"url": "https://your-domain.com/api/files/bucket/download/file.jpg?ts=123456&sig=abc123"
}
],
"folders": ["images", "documents", "reports"],
"pagination": {
"cursor": "next-page-cursor",
"hasMore": true
}
}Notes:
- The
foldersarray contains folder names detected viadelimiter=/ - Folders are extracted from R2's
delimitedPrefixes - Use
prefixparameter to navigate into folders
Create a new folder by creating a .keep placeholder file.
POST /api/folders/:bucket/createURL Parameters:
-
:bucket- The bucket name
Request Body:
{
"folderName": "my-folder"
}Folder Name Validation:
- Only letters (a-z, A-Z), numbers (0-9), hyphens (-), underscores (_), and forward slashes (/)
- Cannot start or end with
/ - Cannot contain consecutive slashes (
//)
Response:
{
"success": true,
"folderPath": "my-folder/"
}Notes:
- Creates a
.keepplaceholder file atfolderName/.keep - Ensures folder exists even when empty
- Supports nested folders using
/(e.g.,parent/child/grandchild)
Rename a folder by copying all objects to a new prefix and deleting the originals.
PATCH /api/folders/:bucket/renameURL Parameters:
-
:bucket- The bucket name
Request Body:
{
"oldPath": "old-folder",
"newPath": "new-folder"
}Response:
{
"success": true,
"copied": 45,
"failed": 2
}Process:
- Lists all objects with
oldPathprefix - For each object, copies to
newPathprefix - Deletes all objects from
oldPath - Processes in batches of 100 with 300ms delays
Important Notes:
- This is a batch operation that may take time for large folders
- All nested folders and files are renamed
- Metadata is preserved during copy
- Operation cannot be undone
Copy a folder and all its contents to another bucket or folder within the same/different bucket.
POST /api/folders/:sourceBucket/:folderPath/copyURL Parameters:
-
:sourceBucket- Source bucket name -
:folderPath- Folder path to copy (URL-encoded)
Request Body:
{
"destinationBucket": "target-bucket",
"destinationPath": "optional/destination/folder"
}Request Body Parameters:
-
destinationBucket(required) - Target bucket name -
destinationPath(optional) - Destination folder path- Leave empty to copy to bucket root with source folder name
- Specify path to copy folder to specific location (e.g.,
"archives/backups") - Path will be normalized (trailing slash added if needed)
Response:
{
"success": true,
"copied": 120,
"failed": 2
}Process:
- Lists all objects with folder prefix in source bucket
- For each object:
- Fetches from source
- Uploads to destination with new path
- Source folder remains unchanged
- Processes in batches with rate limiting
Examples:
# Copy 'images' folder to different bucket (preserves folder name)
POST /api/folders/bucket-a/images/copy
{"destinationBucket": "bucket-b"}
# Result: bucket-b/images/... (all contents copied)
# Copy 'images' folder to specific location in different bucket
POST /api/folders/bucket-a/images/copy
{"destinationBucket": "bucket-b", "destinationPath": "backups/2024/images"}
# Result: bucket-b/backups/2024/images/... (all contents copied)
# Copy folder to another folder within same bucket
POST /api/folders/my-bucket/reports/copy
{"destinationBucket": "my-bucket", "destinationPath": "archives/reports"}
# Result: my-bucket/archives/reports/... (duplicate created)Important Notes:
- Same-bucket copies are allowed when
destinationPathdiffers from source - Allows creating folder duplicates within a bucket at different paths
- Source folder structure is preserved in destination
- All nested folders and files are copied
Move a folder and all its contents to another bucket or folder within the same/different bucket.
POST /api/folders/:sourceBucket/:folderPath/moveURL Parameters:
-
:sourceBucket- Source bucket name -
:folderPath- Folder path to move (URL-encoded)
Request Body:
{
"destinationBucket": "target-bucket",
"destinationPath": "optional/destination/folder"
}Request Body Parameters:
-
destinationBucket(required) - Target bucket name -
destinationPath(optional) - Destination folder path- Leave empty to move to bucket root with source folder name
- Specify path to move folder to specific location (e.g.,
"archives/old") - Path will be normalized (trailing slash added if needed)
Response:
{
"success": true,
"moved": 85,
"failed": 1
}Process:
- Copies all objects to destination (same as copy operation)
- Deletes all objects from source folder
- Source folder is removed after successful move
Examples:
# Move 'temp' folder to different bucket
POST /api/folders/bucket-a/temp/move
{"destinationBucket": "bucket-b"}
# Result: bucket-b/temp/... (bucket-a/temp/ is deleted)
# Move 'drafts' folder to specific location in different bucket
POST /api/folders/bucket-a/drafts/move
{"destinationBucket": "bucket-b", "destinationPath": "archives/2024/drafts"}
# Result: bucket-b/archives/2024/drafts/... (bucket-a/drafts/ is deleted)
# Move folder to another folder within same bucket
POST /api/folders/my-bucket/incoming/move
{"destinationBucket": "my-bucket", "destinationPath": "processed/incoming"}
# Result: my-bucket/processed/incoming/... (my-bucket/incoming/ is deleted)Important Notes:
- Same-bucket moves are allowed when
destinationPathdiffers from source - Allows reorganizing folders within a bucket
- This is a copy + delete operation
- If copy succeeds but delete fails, you may have duplicates
- Cannot be undone
- Large folders may take significant time
Delete a folder and optionally all its contents.
DELETE /api/folders/:bucket/:folderPathURL Parameters:
-
:bucket- The bucket name -
:folderPath- Folder path to delete (URL-encoded)
Query Parameters:
-
force(optional, default: false) - Set totrueto delete all contents
Response without force (folder contains files):
{
"success": false,
"fileCount": 45,
"message": "Folder contains files. Use force=true to delete."
}Response with force:
{
"success": true,
"deleted": 45
}Process:
- Lists all objects with folder prefix
- Counts total files
- If
force=falseand files exist, returns file count for confirmation - If
force=true, deletes all objects in batches - Processes in batches of 100 with 300ms delays
Safety Features:
- Requires explicit
force=truefor non-empty folders - Returns file count for user confirmation
- Batch processing with rate limiting
Analyze a bucket's files for AI Search indexability.
GET /api/ai-search/compatibility/:bucketNameURL Parameters:
-
:bucketName- The bucket name to analyze
Response:
{
"bucketName": "my-bucket",
"totalFiles": 100,
"indexableFiles": 75,
"nonIndexableFiles": 25,
"totalSize": 52428800,
"indexableSize": 39321600,
"files": {
"indexable": [
{ "key": "docs/readme.md", "size": 1024, "extension": ".md" }
],
"nonIndexable": [
{ "key": "images/photo.png", "size": 2048576, "extension": ".png", "reason": "Unsupported extension: .png" }
]
},
"supportedExtensions": [".txt", ".md", ".json", ".yaml", ".yml", ".html", ".js", ".ts", ".py", ".css", ".xml"]
}Supported File Types:
- Text:
.txt,.rst,.log,.ini,.conf,.env - Markdown:
.md,.mdx,.markdown - Data:
.json,.yaml,.yml,.toml - Code:
.js,.ts,.jsx,.tsx,.py,.html,.css,.xml - Scripts:
.sh,.bat,.ps1 - Documents:
.tex,.latex
Size Limit: 4MB per file
List all AI Search instances in your account.
GET /api/ai-search/instancesResponse:
{
"instances": [
{
"name": "my-rag",
"description": "My RAG instance",
"created_at": "2025-01-01T00:00:00.000Z",
"status": "active",
"data_source": {
"type": "r2",
"bucket_name": "my-bucket"
}
}
]
}Instance Status Values:
-
active- Instance is ready for queries -
indexing- Instance is currently indexing data -
paused- Instance is paused -
error- Instance encountered an error
Note: If the AI Search management API is not available, the response will include a dashboardUrl field linking to the Cloudflare Dashboard.
Create a new AI Search instance connected to an R2 bucket.
POST /api/ai-search/instancesRequest Body:
{
"name": "my-rag",
"description": "My RAG instance for documentation",
"bucketName": "my-bucket",
"embeddingModel": "@cf/baai/bge-base-en-v1.5",
"generationModel": "@cf/meta/llama-3.1-8b-instruct"
}Response:
{
"success": true,
"instance": {
"name": "my-rag",
"status": "indexing",
"data_source": { "type": "r2", "bucket_name": "my-bucket" }
}
}Note: Instance creation may redirect to Cloudflare Dashboard if the API is not available.
Delete an AI Search instance.
DELETE /api/ai-search/instances/:instanceNameURL Parameters:
-
:instanceName- The AI Search instance name
Response:
{
"success": true
}Manually trigger a sync/re-index of an AI Search instance.
POST /api/ai-search/instances/:instanceName/syncURL Parameters:
-
:instanceName- The AI Search instance name
Response:
{
"success": true,
"message": "Sync triggered successfully",
"job_id": "job-123-abc"
}Perform semantic search (retrieval only, no AI generation).
POST /api/ai-search/:instanceName/searchURL Parameters:
-
:instanceName- The AI Search instance name
Request Body:
{
"query": "How do I configure authentication?",
"rewrite_query": false,
"max_num_results": 10,
"score_threshold": 0.5,
"reranking": {
"enabled": true,
"model": "@cf/baai/bge-reranker-base"
}
}Response:
{
"data": [
{
"file_id": "abc123",
"filename": "docs/auth.md",
"score": 0.92,
"content": [
{ "id": "1", "type": "text", "text": "Authentication is configured via..." }
]
}
],
"has_more": false,
"next_page": null
}Perform AI-powered search with generated response.
POST /api/ai-search/:instanceName/ai-searchURL Parameters:
-
:instanceName- The AI Search instance name
Request Body:
{
"query": "How do I configure authentication?",
"rewrite_query": true,
"max_num_results": 5,
"score_threshold": 0.5,
"stream": false
}Response:
{
"response": "To configure authentication, you need to...",
"data": [
{
"file_id": "abc123",
"filename": "docs/auth.md",
"score": 0.92,
"content": [
{ "id": "1", "type": "text", "text": "Authentication is configured via..." }
]
}
],
"has_more": false,
"next_page": null
}Streaming Response:
Set stream: true to receive a streaming response with Content-Type: text/event-stream.
Get the Cloudflare Dashboard URL for AI Search management.
GET /api/ai-search/dashboard-urlResponse:
{
"url": "https://dash.cloudflare.com/?to=/:account/ai/ai-search",
"accountId": "abc123..."
}Query individual action logs with filtering and pagination.
GET /api/auditQuery Parameters:
-
operation_type- Filter by operation type (e.g.,file_upload,bucket_create) -
bucket_name- Filter by bucket name -
status- Filter by status (success,failed) -
start_date- Filter by start date (ISO format) -
end_date- Filter by end date (ISO format) -
user_email- Filter by user email -
limit(optional, default: 50) - Results per page -
offset(optional, default: 0) - Pagination offset -
sort_by(optional, default:timestamp) - Sort field (timestamp,operation_type,bucket_name,size_bytes) -
sort_order(optional, default:desc) - Sort direction (asc,desc)
Response:
{
"success": true,
"result": {
"entries": [
{
"id": 1,
"operation_type": "file_upload",
"bucket_name": "my-bucket",
"object_key": "documents/report.pdf",
"user_email": "user@example.com",
"status": "success",
"timestamp": "2025-11-27T10:30:00.000Z",
"metadata": null,
"size_bytes": 1048576,
"destination_bucket": null,
"destination_key": null
}
],
"total": 150,
"limit": 50,
"offset": 0
}
}Supported Operation Types:
-
File Operations:
file_upload,file_download,file_delete,file_rename,file_move,file_copy -
Folder Operations:
folder_create,folder_delete,folder_rename,folder_move,folder_copy -
Bucket Operations:
bucket_create,bucket_delete,bucket_rename
Get operation counts grouped by type for analytics.
GET /api/audit/summaryQuery Parameters:
-
start_date- Filter by start date (ISO format) -
end_date- Filter by end date (ISO format) -
bucket_name- Filter by bucket name
Response:
{
"success": true,
"result": {
"summary": [
{
"operation_type": "file_upload",
"count": 125,
"success_count": 123,
"failed_count": 2
},
{
"operation_type": "file_delete",
"count": 45,
"success_count": 45,
"failed_count": 0
}
]
}
}Notes:
- Summary is ordered by count (most frequent operations first)
- Useful for dashboards and analytics
- Can be filtered by date range and bucket
Get the web app manifest for PWA support.
GET /site.webmanifestResponse:
{
"name": "R2 Bucket Manager",
"short_name": "R2 Manager",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#000000",
"icons": []
}Notes:
- This endpoint bypasses Cloudflare Access authentication
- Served directly by the Worker (not from R2)
- Required for PWA functionality
| Status Code | Description |
|---|---|
200 OK |
Request succeeded |
204 No Content |
Request succeeded with no response body |
400 Bad Request |
Invalid request parameters or body |
401 Unauthorized |
Missing or invalid JWT token |
403 Forbidden |
Valid authentication but insufficient permissions |
404 Not Found |
Resource not found |
500 Internal Server Error |
Server-side error occurred |
The Worker includes built-in rate limiting protection:
- Bucket rename operations: 500ms delay between object copies
- Bucket deletion with force: 500ms delay between object deletions
- Bucket size calculation: 100ms delay between pagination requests
These delays prevent hitting Cloudflare API rate limits.
All API responses include CORS headers for cross-origin requests:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS, PATCH
Access-Control-Allow-Headers: Content-Type, Authorization, X-File-Name, X-Chunk-Index, X-Total-Chunks
- Home - Documentation overview
- Quick Start Guide - Get up and running in minutes
- Installation & Setup - Complete deployment guide
- Configuration Reference - Environment variables and settings
- Upgrade Guide - Database schema migrations
- Bucket Management - Create, rename, delete buckets
- Object Lifecycles - Automate expiration and IA transitions ⭐ NEW
- Job History - Track bulk operations with audit trail ⭐ NEW
- Webhooks - Configure HTTP notifications for events ⭐ NEW
- AI Search - Semantic search with Cloudflare AI
- S3 Import - Migrate from AWS S3 to R2 ⭐ NEW
- Cross-Bucket Search - Search across all buckets with filters
- File Operations - Upload, download, move, copy, delete files
- Folder Management - Organize files hierarchically
- Signed URLs & Sharing - Generate secure shareable links
- Advanced Filtering - Filter by extension, size, and date
- Development Guide - Local setup and development workflow
- API Reference - Complete endpoint documentation
- Architecture Overview - Technical stack and design
- Authentication & Security - Zero Trust implementation
- JWT Validation - JWT token validation and verification
- Changelog - Release history and updates ⭐ NEW
- Troubleshooting - Common issues and solutions
- FAQ - Frequently asked questions
- Roadmap - Planned features and enhancements