Files
google-drive-s3/docs/openapi.yaml
T

1219 lines
40 KiB
YAML

openapi: 3.1.0
info:
title: Google Drive S3 API
version: 1.0.0
description: |
An intentionally small S3-compatible object-storage API backed by Google Drive.
Authenticate every non-public request with AWS Signature Version 4. Browser clients
should receive short-lived presigned URLs from a backend-for-frontend, never credentials.
servers:
- url: https://{worker-host}
variables:
worker-host:
default: your-worker.example.workers.dev
security:
- sigv4: []
tags:
- name: Objects
- name: Buckets
- name: Multipart uploads
- name: Dashboard Auth
- name: Dashboard Status
paths:
/auth/login:
post:
tags: [Dashboard Auth]
operationId: authLogin
summary: Login to dashboard
description: Authenticate with SHA-256 hashed dashboard password.
security: []
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/LoginRequest' }
responses:
'200':
description: Login successful.
content:
application/json:
schema: { $ref: '#/components/schemas/LoginResponse' }
'400':
description: Invalid request.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'401':
description: Invalid password.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'429':
description: Too many failed attempts.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'503':
description: Dashboard authentication not configured.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
/auth/session:
get:
tags: [Dashboard Auth]
operationId: authSession
summary: Verify session token
security:
- bearerAuth: []
responses:
'200':
description: Session is valid.
content:
application/json:
schema:
type: object
properties:
valid: { type: boolean, example: true }
'401':
description: Invalid or expired session.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'503':
description: Dashboard authentication not configured.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
/auth/logout:
post:
tags: [Dashboard Auth]
operationId: authLogout
summary: Logout of dashboard session
security:
- bearerAuth: []
responses:
'204':
description: Successfully logged out.
'503':
description: Dashboard authentication not configured.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
/api/status:
get:
tags: [Dashboard Status]
operationId: getGatewayStatus
summary: Get gateway and storage health status
security:
- bearerAuth: []
responses:
'200':
description: Gateway status and Drive account/quota overview.
content:
application/json:
schema: { $ref: '#/components/schemas/GatewayStatus' }
'401':
description: Invalid or expired session.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'503':
description: Dashboard authentication not configured.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
/api/buckets:
get:
tags: [Dashboard Status]
operationId: getBucketStats
summary: Get bucket list and object metrics
security:
- bearerAuth: []
parameters:
- name: refresh
in: query
description: Set to 1 to bypass KV cache.
required: false
schema: { type: string, example: "1" }
responses:
'200':
description: Bucket statistics and aggregate totals.
content:
application/json:
schema: { $ref: '#/components/schemas/BucketStats' }
'401':
description: Invalid or expired session.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'503':
description: Storage root folder or authentication not configured.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
post:
tags: [Dashboard Status]
operationId: createBucket
summary: Create a new bucket
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/CreateBucketRequest' }
responses:
'201':
description: Bucket created.
content:
application/json:
schema: { $ref: '#/components/schemas/BucketRecord' }
'400':
description: Invalid bucket name.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'401':
description: Invalid or expired session.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'409':
description: Bucket already exists.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'503':
description: Storage root folder or authentication not configured.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
/api/buckets/{name}:
parameters:
- name: name
in: path
required: true
schema: { type: string }
patch:
tags: [Dashboard Status]
operationId: updateBucket
summary: Update bucket settings (toggle public read or rename)
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/UpdateBucketRequest' }
responses:
'200':
description: Bucket updated.
content:
application/json:
schema: { $ref: '#/components/schemas/BucketRecord' }
'400':
description: Invalid request.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'401':
description: Invalid or expired session.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'404':
description: Bucket not found.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'409':
description: Target bucket name conflict.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
delete:
tags: [Dashboard Status]
operationId: deleteBucket
summary: Delete an empty bucket
security:
- bearerAuth: []
responses:
'204':
description: Bucket deleted.
'401':
description: Invalid or expired session.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'404':
description: Bucket not found.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'409':
description: Bucket is not empty.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
/api/import-candidates:
get:
tags: [Dashboard Status]
operationId: listImportCandidates
summary: List Drive folders available for import
security:
- bearerAuth: []
responses:
'200':
description: List of folders under Drive root.
content:
application/json:
schema: { $ref: '#/components/schemas/ImportCandidatesResponse' }
'401':
description: Invalid or expired session.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
/api/import:
post:
tags: [Dashboard Status]
operationId: importBuckets
summary: Import folders from Drive root into storage root folder
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ImportBucketsRequest' }
responses:
'200':
description: Import results.
content:
application/json:
schema: { $ref: '#/components/schemas/ImportResult' }
'400':
description: Invalid body.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
'401':
description: Invalid or expired session.
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
/api/objects:
get:
tags: [Objects API]
operationId: listObjectsApi
summary: List objects and folders in a bucket (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: prefix
schema: { type: string, default: "" }
- in: query
name: delimiter
schema: { type: string, default: "/" }
responses:
'200':
description: Object and folder listing.
content:
application/json:
schema:
type: object
properties:
bucket: { type: string }
prefix: { type: string }
delimiter: { type: string, nullable: true }
folders:
type: array
items:
type: object
properties:
prefix: { type: string }
name: { type: string }
objects:
type: array
items:
type: object
properties:
key: { type: string }
name: { type: string }
size: { type: integer }
contentType: { type: string }
lastModified: { type: string, nullable: true }
etag: { type: string }
truncated: { type: boolean }
'400':
description: Missing query parameters.
'401':
description: Unauthorized.
'404':
description: Bucket not found.
delete:
tags: [Objects API]
operationId: deleteObjectApi
summary: Delete an object (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
responses:
'204':
description: Object deleted.
'401':
description: Unauthorized.
'404':
description: Bucket or object not found.
/api/objects/metadata:
get:
tags: [Objects API]
operationId: getObjectMetadataApi
summary: Get object metadata (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
responses:
'200':
description: Object metadata.
content:
application/json:
schema:
type: object
properties:
key: { type: string }
name: { type: string }
size: { type: integer }
contentType: { type: string }
lastModified: { type: string, nullable: true }
etag: { type: string }
'404':
description: Object not found.
/api/objects/content:
get:
tags: [Objects API]
operationId: getObjectContentApi
summary: Download object content (Dashboard Session Auth or Ticket)
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
- in: query
name: ticket
schema: { type: string }
responses:
'200':
description: Binary object data.
'206':
description: Partial content.
'404':
description: Object not found.
put:
tags: [Objects API]
operationId: putObjectContentApi
summary: Direct single-part upload (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
responses:
'200':
description: Object uploaded.
content:
application/json:
schema:
type: object
properties:
key: { type: string }
etag: { type: string }
size: { type: integer }
/api/objects/folder:
post:
tags: [Objects API]
operationId: createFolderApi
summary: Create a folder (Dashboard Session Auth)
security:
- sessionBearer: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [bucket, prefix]
properties:
bucket: { type: string }
prefix: { type: string }
responses:
'201':
description: Folder created.
'409':
description: Folder already exists.
delete:
tags: [Objects API]
operationId: deleteFolderApi
summary: Delete a folder (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: prefix
required: true
schema: { type: string }
- in: query
name: recursive
schema: { type: string, enum: ["0", "1"] }
responses:
'204':
description: Folder deleted.
'409':
description: Folder is not empty.
/api/objects/download-ticket:
post:
tags: [Objects API]
operationId: createDownloadTicket
summary: Create a temporary single-use download ticket (Dashboard Session Auth)
security:
- sessionBearer: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [bucket, key]
properties:
bucket: { type: string }
key: { type: string }
responses:
'201':
description: Download ticket created.
content:
application/json:
schema:
type: object
properties:
ticket: { type: string }
downloadUrl: { type: string }
expiresIn: { type: integer }
/api/objects/uploads:
post:
tags: [Objects API]
operationId: initiateMultipartApi
summary: Initiate a multipart upload (Dashboard Session Auth)
security:
- sessionBearer: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [bucket, key]
properties:
bucket: { type: string }
key: { type: string }
contentType: { type: string }
responses:
'201':
description: Upload initiated.
content:
application/json:
schema:
type: object
properties:
uploadId: { type: string }
bucket: { type: string }
key: { type: string }
partSize: { type: integer }
delete:
tags: [Objects API]
operationId: abortMultipartApi
summary: Abort a multipart upload (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
- in: query
name: uploadId
required: true
schema: { type: string }
responses:
'204':
description: Upload aborted.
/api/objects/uploads/part:
put:
tags: [Objects API]
operationId: uploadPartApi
summary: Upload a part (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
- in: query
name: uploadId
required: true
schema: { type: string }
- in: query
name: partNumber
required: true
schema: { type: integer }
responses:
'200':
description: Part uploaded.
content:
application/json:
schema:
type: object
properties:
partNumber: { type: integer }
etag: { type: string }
/api/objects/uploads/complete:
post:
tags: [Objects API]
operationId: completeMultipartApi
summary: Complete a multipart upload (Dashboard Session Auth)
security:
- sessionBearer: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [bucket, key, uploadId, parts]
properties:
bucket: { type: string }
key: { type: string }
uploadId: { type: string }
parts:
type: array
items:
type: object
required: [partNumber, etag]
properties:
partNumber: { type: integer }
etag: { type: string }
totalSize: { type: integer }
responses:
'200':
description: Upload completed.
content:
application/json:
schema:
type: object
properties:
key: { type: string }
etag: { type: string }
/api/objects/uploads/parts:
get:
tags: [Objects API]
operationId: listPartsApi
summary: List uploaded parts (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
- in: query
name: uploadId
required: true
schema: { type: string }
responses:
'200':
description: Parts list.
/{bucket}:
parameters:
- $ref: '#/components/parameters/Bucket'
get:
tags: [Buckets]
operationId: listObjects
summary: List objects in a bucket
description: List objects recursively, or use `delimiter=/` to return immediate folders as `CommonPrefixes`.
parameters:
- $ref: '#/components/parameters/Prefix'
- $ref: '#/components/parameters/Delimiter'
responses:
'200':
description: Object listing.
content:
application/xml:
schema: { $ref: '#/components/schemas/ListBucketResult' }
'403': { $ref: '#/components/responses/AccessDenied' }
'405': { $ref: '#/components/responses/MethodNotAllowed' }
head:
tags: [Buckets]
operationId: headBucket
summary: Check bucket access
responses:
'200': { description: The bucket is configured and accessible. }
'403': { $ref: '#/components/responses/AccessDenied' }
'405': { $ref: '#/components/responses/MethodNotAllowed' }
/{bucket}?uploads:
parameters:
- $ref: '#/components/parameters/Bucket'
get:
tags: [Multipart uploads]
operationId: listMultipartUploads
summary: List multipart uploads
description: Always returns an empty list; active multipart uploads cannot be enumerated.
responses:
'200':
description: Empty multipart upload listing.
content:
application/xml:
schema: { $ref: '#/components/schemas/ListMultipartUploadsResult' }
'403': { $ref: '#/components/responses/AccessDenied' }
/{bucket}/{key}:
parameters:
- $ref: '#/components/parameters/Bucket'
- $ref: '#/components/parameters/Key'
put:
tags: [Objects]
operationId: putObject
summary: Create or replace an object
parameters:
- $ref: '#/components/parameters/ContentType'
requestBody:
required: true
content:
application/octet-stream:
schema: { type: string, format: binary }
'*/*':
schema: { type: string, format: binary }
responses:
'200':
description: Object uploaded.
headers:
ETag: { $ref: '#/components/headers/ETag' }
'403': { $ref: '#/components/responses/AccessDenied' }
'501': { $ref: '#/components/responses/NotImplemented' }
get:
tags: [Objects]
operationId: getObject
summary: Download an object
parameters:
- name: Range
in: header
schema: { type: string, example: bytes=0-1023 }
responses:
'200':
description: Full object data.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Content-Length: { $ref: '#/components/headers/ContentLength' }
Last-Modified: { $ref: '#/components/headers/LastModified' }
Accept-Ranges: { schema: { type: string, example: bytes } }
content:
application/octet-stream:
schema: { type: string, format: binary }
'206':
description: Requested byte range.
headers:
Content-Range: { schema: { type: string, example: bytes 0-1023/4096 } }
Content-Length: { $ref: '#/components/headers/ContentLength' }
content:
application/octet-stream:
schema: { type: string, format: binary }
'403': { $ref: '#/components/responses/AccessDenied' }
'404': { $ref: '#/components/responses/NoSuchKey' }
head:
tags: [Objects]
operationId: headObject
summary: Get object metadata
responses:
'200':
description: Object metadata in headers.
headers:
ETag: { $ref: '#/components/headers/ETag' }
Content-Length: { $ref: '#/components/headers/ContentLength' }
Last-Modified: { $ref: '#/components/headers/LastModified' }
Accept-Ranges: { schema: { type: string, example: bytes } }
'403': { $ref: '#/components/responses/AccessDenied' }
'404': { $ref: '#/components/responses/NoSuchKey' }
delete:
tags: [Objects]
operationId: deleteObject
summary: Delete an object
responses:
'204': { description: Object deleted. }
'403': { $ref: '#/components/responses/AccessDenied' }
'404': { $ref: '#/components/responses/NoSuchKey' }
/{bucket}/{key}?uploads:
parameters:
- $ref: '#/components/parameters/Bucket'
- $ref: '#/components/parameters/Key'
post:
tags: [Multipart uploads]
operationId: createMultipartUpload
summary: Initiate a multipart upload
parameters:
- $ref: '#/components/parameters/ContentType'
responses:
'200':
description: Upload initiated.
content:
application/xml:
schema: { $ref: '#/components/schemas/InitiateMultipartUploadResult' }
'403': { $ref: '#/components/responses/AccessDenied' }
'501': { $ref: '#/components/responses/NotImplemented' }
/{bucket}/{key}?uploadId={uploadId}&partNumber={partNumber}:
parameters:
- $ref: '#/components/parameters/Bucket'
- $ref: '#/components/parameters/Key'
- $ref: '#/components/parameters/UploadId'
- $ref: '#/components/parameters/PartNumber'
put:
tags: [Multipart uploads]
operationId: uploadPart
summary: Upload one multipart part
description: Parts must arrive strictly sequentially beginning with part number 1.
requestBody:
required: true
content:
application/octet-stream:
schema: { type: string, format: binary }
responses:
'200':
description: Part accepted.
headers:
ETag: { $ref: '#/components/headers/ETag' }
'400': { $ref: '#/components/responses/InvalidArgument' }
'403': { $ref: '#/components/responses/AccessDenied' }
'404': { $ref: '#/components/responses/NoSuchUpload' }
'503': { $ref: '#/components/responses/SlowDown' }
/{bucket}/{key}?uploadId={uploadId}:
parameters:
- $ref: '#/components/parameters/Bucket'
- $ref: '#/components/parameters/Key'
- $ref: '#/components/parameters/UploadId'
post:
tags: [Multipart uploads]
operationId: completeMultipartUpload
summary: Complete a multipart upload
requestBody:
required: true
content:
application/xml:
schema: { $ref: '#/components/schemas/CompleteMultipartUpload' }
responses:
'200':
description: Upload completed.
content:
application/xml:
schema: { $ref: '#/components/schemas/CompleteMultipartUploadResult' }
'400': { $ref: '#/components/responses/InvalidArgument' }
'403': { $ref: '#/components/responses/AccessDenied' }
'404': { $ref: '#/components/responses/NoSuchUpload' }
get:
tags: [Multipart uploads]
operationId: listParts
summary: List uploaded parts
parameters:
- name: part-number-marker
in: query
schema: { type: integer, minimum: 0, default: 0 }
- name: max-parts
in: query
schema: { type: integer, minimum: 1, maximum: 1000, default: 1000 }
responses:
'200':
description: Current part list.
content:
application/xml:
schema: { $ref: '#/components/schemas/ListPartsResult' }
'400': { $ref: '#/components/responses/InvalidArgument' }
'403': { $ref: '#/components/responses/AccessDenied' }
'404': { $ref: '#/components/responses/NoSuchUpload' }
delete:
tags: [Multipart uploads]
operationId: abortMultipartUpload
summary: Abort a multipart upload
responses:
'204': { description: Upload aborted. }
'403': { $ref: '#/components/responses/AccessDenied' }
'404': { $ref: '#/components/responses/NoSuchUpload' }
components:
securitySchemes:
sigv4:
type: apiKey
in: header
name: Authorization
description: AWS Signature Version 4 header authentication or equivalent `X-Amz-*` presigned query parameters.
bearerAuth:
type: http
scheme: bearer
description: Session token returned from `/auth/login`.
parameters:
Bucket:
name: bucket
in: path
required: true
schema: { type: string }
Key:
name: key
in: path
required: true
schema: { type: string }
Prefix:
name: prefix
in: query
schema: { type: string, default: '' }
Delimiter:
name: delimiter
in: query
schema: { type: string, example: / }
UploadId:
name: uploadId
in: query
required: true
schema: { type: string }
PartNumber:
name: partNumber
in: query
required: true
schema: { type: integer, minimum: 1, maximum: 10000 }
ContentType:
name: Content-Type
in: header
schema: { type: string, example: application/octet-stream }
headers:
ETag:
schema: { type: string, example: '"d41d8cd98f00b204e9800998ecf8427e"' }
ContentLength:
schema: { type: integer, minimum: 0 }
LastModified:
schema: { type: string, format: date-time }
responses:
AccessDenied:
description: Authentication failed, the access key is not recognized, the presigned URL expired, or bucket access is denied.
content: { application/xml: { schema: { $ref: '#/components/schemas/S3Error' } } }
NoSuchKey:
description: The object does not exist.
content: { application/xml: { schema: { $ref: '#/components/schemas/S3Error' } } }
NoSuchUpload:
description: The multipart upload does not exist.
content: { application/xml: { schema: { $ref: '#/components/schemas/S3Error' } } }
InvalidArgument:
description: A required parameter or body is invalid.
content: { application/xml: { schema: { $ref: '#/components/schemas/S3Error' } } }
NotImplemented:
description: This S3 operation is not supported.
content: { application/xml: { schema: { $ref: '#/components/schemas/S3Error' } } }
SlowDown:
description: Parts are out of sequence or the upload is busy; retry later.
content: { application/xml: { schema: { $ref: '#/components/schemas/S3Error' } } }
MethodNotAllowed:
description: The method/path combination is unsupported.
content: { application/xml: { schema: { $ref: '#/components/schemas/S3Error' } } }
schemas:
LoginRequest:
type: object
required: [passwordHash]
properties:
passwordHash:
type: string
description: SHA-256 hash of the dashboard password in lowercase hex.
example: ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f
LoginResponse:
type: object
required: [token, expiresIn]
properties:
token:
type: string
description: Session token.
expiresIn:
type: integer
description: Token TTL in seconds.
example: 43200
GatewayStatus:
type: object
required: [gateway, drive, checkedAt]
properties:
gateway:
type: object
required: [status, region, multipartEnabled, etagStyle, docsEnabled, buckets, publicReadBuckets, rootFolder, corsOrigins, credentials]
properties:
status: { type: string, enum: [ok, degraded] }
region: { type: string, example: auto }
multipartEnabled: { type: boolean }
etagStyle: { type: string, enum: [md5, multipart] }
docsEnabled: { type: boolean }
buckets: { type: array, items: { type: string } }
publicReadBuckets: { type: array, items: { type: string } }
rootFolder:
type: object
required: [name, id, configured]
properties:
name: { type: string, nullable: true }
id: { type: string, nullable: true }
configured: { type: boolean }
corsOrigins: { type: array, items: { type: string } }
credentials:
type: object
required: [s3Keys, googleOAuth, dashboardPassword]
properties:
s3Keys: { type: boolean }
googleOAuth: { type: boolean }
dashboardPassword: { type: boolean }
drive:
type: object
required: [connected, account, quota, error]
properties:
connected: { type: boolean }
account:
type: object
nullable: true
properties:
email: { type: string, nullable: true }
displayName: { type: string, nullable: true }
quota:
type: object
nullable: true
properties:
limit: { type: integer, nullable: true }
usage: { type: integer }
usageInDrive: { type: integer }
usageInDriveTrash: { type: integer }
free: { type: integer, nullable: true }
percentUsed: { type: number, nullable: true }
error: { type: string, nullable: true }
checkedAt:
type: string
format: date-time
BucketStats:
type: object
required: [buckets, totals, cachedAt]
properties:
buckets:
type: array
items:
type: object
required: [name, objectCount, totalSize, lastModified, truncated, publicRead, error]
properties:
name: { type: string }
objectCount: { type: integer }
totalSize: { type: integer }
lastModified: { type: string, format: date-time, nullable: true }
truncated: { type: boolean }
publicRead: { type: boolean }
error: { type: string, nullable: true }
totals:
type: object
required: [buckets, objectCount, totalSize]
properties:
buckets: { type: integer }
objectCount: { type: integer }
totalSize: { type: integer }
cachedAt:
type: string
format: date-time
BucketRecord:
type: object
required: [name, folderId, publicRead, createdTime]
properties:
name: { type: string, example: assets }
folderId: { type: string, example: 1A2b3C4d5E6f }
publicRead: { type: boolean, example: false }
createdTime: { type: string, format: date-time, nullable: true }
CreateBucketRequest:
type: object
required: [name]
properties:
name: { type: string, example: assets }
publicRead: { type: boolean, default: false }
UpdateBucketRequest:
type: object
properties:
publicRead: { type: boolean }
name: { type: string }
ImportCandidate:
type: object
required: [name, folderId, objectCount]
properties:
name: { type: string, example: legacy-photos }
folderId: { type: string, example: 1A2b3C4d5E6f }
objectCount: { type: integer, example: 42 }
ImportCandidatesResponse:
type: object
required: [candidates]
properties:
candidates:
type: array
items: { $ref: '#/components/schemas/ImportCandidate' }
ImportBucketsRequest:
type: object
required: [names]
properties:
names:
type: array
items: { type: string }
ImportResult:
type: object
required: [imported, failed]
properties:
imported:
type: array
items: { type: string }
failed:
type: array
items:
type: object
required: [name, error]
properties:
name: { type: string }
error: { type: string }
AuthError:
type: object
required: [message]
properties:
message:
type: string
example: Invalid password
S3Error:
type: object
xml: { name: Error }
required: [Code, Message, RequestId]
properties:
Code: { type: string, xml: { name: Code } }
Message: { type: string, xml: { name: Message } }
Resource: { type: string, xml: { name: Resource } }
RequestId: { type: string, xml: { name: RequestId } }
Object:
type: object
xml: { name: Contents }
properties:
Key: { type: string }
LastModified: { type: string, format: date-time }
ETag: { type: string }
Size: { type: integer }
StorageClass: { type: string, example: STANDARD }
ListBucketResult:
type: object
xml: { name: ListBucketResult, namespace: 'http://s3.amazonaws.com/doc/2006-03-01/' }
properties:
Name: { type: string }
Prefix: { type: string }
Delimiter: { type: string }
MaxKeys: { type: integer, example: 1000 }
IsTruncated: { type: boolean }
Contents: { type: array, items: { $ref: '#/components/schemas/Object' }, xml: { wrapped: false } }
InitiateMultipartUploadResult:
type: object
xml: { name: InitiateMultipartUploadResult, namespace: 'http://s3.amazonaws.com/doc/2006-03-01/' }
required: [Bucket, Key, UploadId]
properties:
Bucket: { type: string }
Key: { type: string }
UploadId: { type: string }
CompleteMultipartUpload:
type: object
xml: { name: CompleteMultipartUpload }
required: [Part]
properties:
Part:
type: array
minItems: 1
xml: { wrapped: false }
items:
type: object
xml: { name: Part }
required: [PartNumber, ETag]
properties:
PartNumber: { type: integer }
ETag: { type: string }
CompleteMultipartUploadResult:
type: object
xml: { name: CompleteMultipartUploadResult, namespace: 'http://s3.amazonaws.com/doc/2006-03-01/' }
properties:
Location: { type: string }
Bucket: { type: string }
Key: { type: string }
ETag: { type: string }
ListPartsResult:
type: object
xml: { name: ListPartsResult, namespace: 'http://s3.amazonaws.com/doc/2006-03-01/' }
properties:
Bucket: { type: string }
Key: { type: string }
UploadId: { type: string }
NextPartNumberMarker: { type: integer }
IsTruncated: { type: boolean }
Part:
type: array
xml: { wrapped: false }
items:
type: object
properties:
PartNumber: { type: integer }
LastModified: { type: string, format: date-time }
ETag: { type: string }
Size: { type: integer }
ListMultipartUploadsResult:
type: object
xml: { name: ListMultipartUploadsResult, namespace: 'http://s3.amazonaws.com/doc/2006-03-01/' }
properties:
Bucket: { type: string }
KeyMarker: { type: string }
UploadIdMarker: { type: string }
NextKeyMarker: { type: string }
NextUploadIdMarker: { type: string }
MaxUploads: { type: integer, example: 1000 }
IsTruncated: { type: boolean, example: false }