Skip to content

API Reference

Temp edited this page Jan 13, 2026 · 12 revisions

API Reference

Complete reference for all API endpoints provided by R2-Manager-Worker.

Base URL

All API endpoints are relative to your Worker's base URL:

https://YOUR_DOMAIN/api

For local development: http://localhost:8787/api

Authentication

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.


Rate Limiting

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.

Rate Limit Tiers

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

Rate Limit Behavior

  • 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

Rate Limit Response

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, or DELETE)

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
}

Local Development

Rate limiting is automatically disabled for localhost development (http://localhost:*) to simplify testing and development workflows.

Best Practices

  1. Implement Retry Logic: When receiving a 429 response, wait the duration specified in Retry-After header before retrying
  2. Batch Operations: Use bulk endpoints where available to minimize API calls
  3. Cache Results: Cache frequently accessed data to reduce redundant API calls
  4. Monitor Headers: Track rate limit headers to understand usage patterns
  5. Handle Gracefully: Display user-friendly messages when rate limits are reached

Response Format

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)"
}

Bucket Management

List Buckets

List all R2 buckets in your account.

GET /api/buckets

Response:

{
  "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 Bucket

Create a new R2 bucket.

POST /api/buckets

Request 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 Bucket

Delete an R2 bucket.

DELETE /api/buckets/:name

URL Parameters:

  • :name - The bucket name to delete

Query Parameters:

  • force (optional) - Set to true to delete all objects in the bucket first
    • Example: /api/buckets/my-bucket?force=true

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 Bucket

Rename an R2 bucket by creating a new bucket, copying all objects, and deleting the old bucket.

PATCH /api/buckets/:name

URL 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

File Management

List Files

List objects in a bucket with pagination support.

GET /api/files/:bucket

URL 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 to true to 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 url field contains a signed URL for downloading the file
  • Files in the assets/ folder are automatically filtered out
  • Set skipCache=true when you need fresh data after uploads/deletions

Upload File

Upload a file to a bucket with support for chunked uploads.

POST /api/files/:bucket/upload

URL 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-data with a file field 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:

  1. Upload chunk 0: X-Chunk-Index: 0, X-Total-Chunks: 5
  2. Upload chunk 1: X-Chunk-Index: 1, X-Total-Chunks: 5
  3. Continue for all chunks...

Generate Signed URL

Generate a signed URL for secure file sharing.

GET /api/files/:bucket/signed-url/:file

URL 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 File

Download a file using a signed URL.

GET /api/files/:bucket/download/:file?ts=TIMESTAMP&sig=SIGNATURE

URL 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-Type header
  • Content-Disposition: attachment header 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 File

Rename a file within the same bucket.

PATCH /api/files/:bucket/:file/rename

URL 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:

  1. Validates that the new key doesn't already exist
  2. Fetches file from source location
  3. Preserves content type and metadata
  4. Creates file with new key
  5. 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 File

Delete a single file from a bucket.

DELETE /api/files/:bucket/delete/:file

URL Parameters:

  • :bucket - The bucket name
  • :file - The file key (URL-encoded if needed)

Response:

{
  "success": true
}

Move File

Move a file to another bucket or folder within the same/different bucket.

POST /api/files/:bucket/:file/move

URL 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:

  1. Fetch file from source bucket
  2. Preserve content type and metadata
  3. Construct destination key: destinationPath + "/" + filename
  4. Upload to destination bucket with computed key
  5. 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.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 or delete failed

Important Notes:

  • Same-bucket moves are allowed when destinationPath differs from source path
  • Only the filename is preserved; full source path is not kept
  • Original file is deleted after successful move

Copy File

Copy a file to another bucket or folder within the same/different bucket.

POST /api/files/:bucket/:file/copy

URL 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:

  1. Fetch file from source bucket
  2. Preserve content type and metadata
  3. Construct destination key: destinationPath + "/" + filename
  4. Upload to destination bucket with computed key
  5. 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 destinationPath differs 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 ZIP Archive

Download multiple files as a ZIP archive.

POST /api/files/:bucket/download-zip

URL Parameters:

  • :bucket - The bucket name

Request Body:

{
  "files": ["file1.jpg", "file2.pdf", "folder/file3.png"]
}

Response:

  • Binary ZIP file data
  • Content-Type: application/zip
  • Content-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

Folder Management

List Files with Folders

List objects and folders in a bucket with pagination support.

GET /api/files/:bucket

URL 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 to true to 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 folders array contains folder names detected via delimiter=/
  • Folders are extracted from R2's delimitedPrefixes
  • Use prefix parameter to navigate into folders

Create Folder

Create a new folder by creating a .keep placeholder file.

POST /api/folders/:bucket/create

URL 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 .keep placeholder file at folderName/.keep
  • Ensures folder exists even when empty
  • Supports nested folders using / (e.g., parent/child/grandchild)

Rename Folder

Rename a folder by copying all objects to a new prefix and deleting the originals.

PATCH /api/folders/:bucket/rename

URL Parameters:

  • :bucket - The bucket name

Request Body:

{
  "oldPath": "old-folder",
  "newPath": "new-folder"
}

Response:

{
  "success": true,
  "copied": 45,
  "failed": 2
}

Process:

  1. Lists all objects with oldPath prefix
  2. For each object, copies to newPath prefix
  3. Deletes all objects from oldPath
  4. 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 Folder

Copy a folder and all its contents to another bucket or folder within the same/different bucket.

POST /api/folders/:sourceBucket/:folderPath/copy

URL 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:

  1. Lists all objects with folder prefix in source bucket
  2. For each object:
    • Fetches from source
    • Uploads to destination with new path
  3. Source folder remains unchanged
  4. 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 destinationPath differs 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 Folder

Move a folder and all its contents to another bucket or folder within the same/different bucket.

POST /api/folders/:sourceBucket/:folderPath/move

URL 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:

  1. Copies all objects to destination (same as copy operation)
  2. Deletes all objects from source folder
  3. 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 destinationPath differs 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 Folder

Delete a folder and optionally all its contents.

DELETE /api/folders/:bucket/:folderPath

URL Parameters:

  • :bucket - The bucket name
  • :folderPath - Folder path to delete (URL-encoded)

Query Parameters:

  • force (optional, default: false) - Set to true to 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:

  1. Lists all objects with folder prefix
  2. Counts total files
  3. If force=false and files exist, returns file count for confirmation
  4. If force=true, deletes all objects in batches
  5. Processes in batches of 100 with 300ms delays

Safety Features:

  • Requires explicit force=true for non-empty folders
  • Returns file count for user confirmation
  • Batch processing with rate limiting

AI Search

Check Bucket Compatibility

Analyze a bucket's files for AI Search indexability.

GET /api/ai-search/compatibility/:bucketName

URL 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 AI Search Instances

List all AI Search instances in your account.

GET /api/ai-search/instances

Response:

{
  "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 AI Search Instance

Create a new AI Search instance connected to an R2 bucket.

POST /api/ai-search/instances

Request 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 AI Search Instance

Delete an AI Search instance.

DELETE /api/ai-search/instances/:instanceName

URL Parameters:

  • :instanceName - The AI Search instance name

Response:

{
  "success": true
}

Trigger Instance Sync

Manually trigger a sync/re-index of an AI Search instance.

POST /api/ai-search/instances/:instanceName/sync

URL Parameters:

  • :instanceName - The AI Search instance name

Response:

{
  "success": true,
  "message": "Sync triggered successfully",
  "job_id": "job-123-abc"
}

Semantic Search

Perform semantic search (retrieval only, no AI generation).

POST /api/ai-search/:instanceName/search

URL 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
}

AI-Powered Search

Perform AI-powered search with generated response.

POST /api/ai-search/:instanceName/ai-search

URL 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 Dashboard URL

Get the Cloudflare Dashboard URL for AI Search management.

GET /api/ai-search/dashboard-url

Response:

{
  "url": "https://dash.cloudflare.com/?to=/:account/ai/ai-search",
  "accountId": "abc123..."
}

Audit Logging

List Audit Log Entries

Query individual action logs with filtering and pagination.

GET /api/audit

Query 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 Audit Summary

Get operation counts grouped by type for analytics.

GET /api/audit/summary

Query 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

Static Assets

Site Manifest

Get the web app manifest for PWA support.

GET /site.webmanifest

Response:

{
  "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

Error Codes

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

Rate Limiting

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.


CORS Headers

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

Additional Resources

R2 Bucket Manager Wiki

Getting Started

Core Features

Development

Security & Authentication

Support & Resources

  • Changelog - Release history and updates ⭐ NEW
  • Troubleshooting - Common issues and solutions
  • FAQ - Frequently asked questions
  • Roadmap - Planned features and enhancements

External Links

Clone this wiki locally