{
  "openapi": "3.0.0",
  "info": {
    "version": "1.0.0",
    "title": "Nhost Storage API",
    "description": "Nhost Storage API - A service for managing and serving files with powerful access control capabilities",
    "license": {
      "name": "Apache License 2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0"
    },
    "contact": {
      "name": "Nhost Support",
      "email": "support@nhost.io",
      "url": "https://nhost.io"
    }
  },
  "servers": [
    {
      "url": "https://{subdomain}.storage.{region}.nhost.run/v1",
      "description": "Nhost Storage API Server"
    }
  ],
  "tags": [
    {
      "name": "documentation",
      "description": "API documentation"
    },
    {
      "name": "excludeme",
      "description": "Internal operations excluded from public docs"
    },
    {
      "name": "files",
      "description": "File management operations"
    },
    {
      "name": "operations",
      "description": "Administrative operations"
    },
    {
      "name": "storage",
      "description": "Storage operations and presigned URLs"
    },
    {
      "name": "system",
      "description": "System information"
    }
  ],
  "paths": {
    "/files": {
      "post": {
        "summary": "Upload files",
        "description": "Upload one or more files to a specified bucket. Supports batch uploading with optional custom metadata for each file. If uploading multiple files, either provide metadata for all files or none.",
        "operationId": "uploadFiles",
        "tags": [
          "files"
        ],
        "security": [
          {
            "Authorization": []
          }
        ],
        "requestBody": {
          "description": "File upload data including files and optional metadata",
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "bucket-id": {
                    "type": "string",
                    "description": "Target bucket identifier where files will be stored.",
                    "example": "user-uploads"
                  },
                  "metadata[]": {
                    "type": "array",
                    "description": "Optional custom metadata for each uploaded file. Must match the order of the file[] array.",
                    "items": {
                      "$ref": "#/components/schemas/UploadFileMetadata"
                    }
                  },
                  "file[]": {
                    "description": "Array of files to upload.",
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "binary"
                    }
                  }
                },
                "required": [
                  "file[]"
                ]
              },
              "encoding": {
                "metadata[]": {
                  "contentType": "application/json"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Files successfully uploaded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "processedFiles": {
                      "type": "array",
                      "description": "List of successfully processed files with their metadata.",
                      "items": {
                        "$ref": "#/components/schemas/FileMetadata"
                      }
                    }
                  },
                  "required": [
                    "processedFiles"
                  ]
                }
              }
            }
          },
          "default": {
            "description": "Error occurred during upload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseWithProcessedFiles"
                }
              }
            }
          }
        }
      }
    },
    "/files/{id}": {
      "delete": {
        "summary": "Delete file",
        "description": "Permanently delete a file from storage. This removes both the file content and its associated metadata.",
        "operationId": "deleteFile",
        "tags": [
          "files"
        ],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Unique identifier of the file to delete",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "File successfully deleted"
          },
          "default": {
            "description": "Error occurred during file deletion",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "Download file",
        "description": "Retrieve and download the complete file content. Supports conditional requests, image transformations, and range requests for partial downloads.",
        "operationId": "getFile",
        "tags": [
          "files"
        ],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Unique identifier of the file to download",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "if-match",
            "description": "Only return the file if the current ETag matches one of the values provided",
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "if-none-match",
            "description": "Only return the file if the current ETag does not match any of the values provided",
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "if-modified-since",
            "description": "Only return the file if it has been modified after the given date",
            "in": "header",
            "schema": {
              "$ref": "#/components/schemas/RFC2822Date"
            }
          },
          {
            "name": "if-unmodified-since",
            "description": "Only return the file if it has not been modified after the given date",
            "in": "header",
            "schema": {
              "$ref": "#/components/schemas/RFC2822Date"
            }
          },
          {
            "name": "q",
            "description": "Image quality (1-100). Only applies to JPEG, WebP, AVIF and HEIC files",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "h",
            "description": "Maximum height, in pixels, to resize image to while maintaining aspect ratio. Only applies to image files. Values above the server-configured maximum (default 8000) are rejected with a 400 error.",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "w",
            "description": "Maximum width, in pixels, to resize image to while maintaining aspect ratio. Only applies to image files. Values above the server-configured maximum (default 8000) are rejected with a 400 error.",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "b",
            "description": "Blur the image using this sigma value. Only applies to image files. Values above the server-configured maximum (default 250) are rejected with a 400 error.",
            "in": "query",
            "schema": {
              "type": "number",
              "minimum": 0
            }
          },
          {
            "name": "f",
            "description": "Output format for image files. Use 'auto' for content negotiation based on Accept header",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/OutputImageFormat"
            }
          },
          {
            "name": "Range",
            "description": "Range of bytes to retrieve from the file. Format: bytes=start-end",
            "in": "header",
            "schema": {
              "type": "string",
              "pattern": "^bytes=(\\d+-\\d*|\\d*-\\d+)(,(\\d+-\\d*|\\d*-\\d+))*$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File content retrieved successfully",
            "headers": {
              "Cache-Control": {
                "description": "Directives for caching mechanisms",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Type": {
                "description": "MIME type of the file",
                "schema": {
                  "type": "string"
                }
              },
              "Etag": {
                "description": "Entity tag for cache validation",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Disposition": {
                "description": "Indicates if the content should be displayed inline or as an attachment",
                "schema": {
                  "type": "string"
                }
              },
              "Last-Modified": {
                "description": "Date and time the file was last modified",
                "schema": {
                  "$ref": "#/components/schemas/RFC2822Date"
                }
              },
              "Surrogate-Key": {
                "description": "Cache key for surrogate caching",
                "schema": {
                  "type": "string"
                }
              },
              "Surrogate-Control": {
                "description": "Cache control directives for surrogate caching",
                "schema": {
                  "type": "string"
                }
              },
              "Accept-Ranges": {
                "description": "Always set to bytes. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Ranges",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/octet-stream": {}
            }
          },
          "206": {
            "description": "Partial file content retrieved successfully",
            "headers": {
              "Cache-Control": {
                "description": "Directives for caching mechanisms",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Type": {
                "description": "MIME type of the file",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Range": {
                "description": "Range of bytes returned in the response",
                "schema": {
                  "type": "string"
                }
              },
              "Etag": {
                "description": "Entity tag for cache validation",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Disposition": {
                "description": "Indicates if the content should be displayed inline or as an attachment",
                "schema": {
                  "type": "string"
                }
              },
              "Last-Modified": {
                "description": "Date and time the file was last modified",
                "schema": {
                  "$ref": "#/components/schemas/RFC2822Date"
                }
              },
              "Surrogate-Key": {
                "description": "Cache key for surrogate caching",
                "schema": {
                  "type": "string"
                }
              },
              "Surrogate-Control": {
                "description": "Cache control directives for surrogate caching",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/octet-stream": {}
            }
          },
          "304": {
            "description": "File not modified since the condition specified in If-Modified-Since or If-None-Match headers",
            "headers": {
              "Cache-Control": {
                "description": "Directives for caching mechanisms",
                "schema": {
                  "type": "string"
                }
              },
              "Etag": {
                "description": "Entity tag for cache validation",
                "schema": {
                  "type": "string"
                }
              },
              "Surrogate-Control": {
                "description": "Cache control directives for surrogate caching",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "412": {
            "description": "Precondition failed for conditional request headers (If-Match, If-Unmodified-Since, If-None-Match)",
            "headers": {
              "Cache-Control": {
                "description": "Directives for caching mechanisms",
                "schema": {
                  "type": "string"
                }
              },
              "Etag": {
                "description": "Entity tag for cache validation",
                "schema": {
                  "type": "string"
                }
              },
              "Surrogate-Control": {
                "description": "Cache control directives for surrogate caching",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "description": "Error occurred",
            "headers": {
              "X-Error": {
                "description": "Error message details",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "head": {
        "summary": "Check file information",
        "description": "Retrieve file metadata headers without downloading the file content. Supports conditional requests and provides caching information.",
        "operationId": "getFileMetadataHeaders",
        "tags": [
          "files"
        ],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Unique identifier of the file to check",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "if-match",
            "description": "Only return the file if the current ETag matches one of the values provided",
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "if-none-match",
            "description": "Only return the file if the current ETag does not match any of the values provided",
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "if-modified-since",
            "description": "Only return the file if it has been modified after the given date",
            "in": "header",
            "schema": {
              "$ref": "#/components/schemas/RFC2822Date"
            }
          },
          {
            "name": "if-unmodified-since",
            "description": "Only return the file if it has not been modified after the given date",
            "in": "header",
            "schema": {
              "$ref": "#/components/schemas/RFC2822Date"
            }
          },
          {
            "name": "q",
            "description": "Image quality (1-100). Only applies to JPEG, WebP, AVIF and HEIC files",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "h",
            "description": "Maximum height, in pixels, to resize image to while maintaining aspect ratio. Only applies to image files. Values above the server-configured maximum (default 8000) are rejected with a 400 error.",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "w",
            "description": "Maximum width, in pixels, to resize image to while maintaining aspect ratio. Only applies to image files. Values above the server-configured maximum (default 8000) are rejected with a 400 error.",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "b",
            "description": "Blur the image using this sigma value. Only applies to image files. Values above the server-configured maximum (default 250) are rejected with a 400 error.",
            "in": "query",
            "schema": {
              "type": "number",
              "minimum": 0
            }
          },
          {
            "name": "f",
            "description": "Output format for image files. Use 'auto' for content negotiation based on Accept header",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/OutputImageFormat"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File information headers retrieved successfully",
            "headers": {
              "Cache-Control": {
                "description": "Directives for caching mechanisms",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Type": {
                "description": "MIME type of the file",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Length": {
                "description": "Size of the file in bytes",
                "schema": {
                  "type": "integer"
                }
              },
              "Etag": {
                "description": "Entity tag for cache validation",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Disposition": {
                "description": "Indicates if the content should be displayed inline or as an attachment",
                "schema": {
                  "type": "string"
                }
              },
              "Last-Modified": {
                "description": "Date and time the file was last modified",
                "schema": {
                  "$ref": "#/components/schemas/RFC2822Date"
                }
              },
              "Accept-Ranges": {
                "description": "Always set to bytes. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Ranges",
                "schema": {
                  "type": "string"
                }
              },
              "Surrogate-Key": {
                "description": "Cache key for surrogate caching",
                "schema": {
                  "type": "string"
                }
              },
              "Surrogate-Control": {
                "description": "Cache control directives for surrogate caching",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "304": {
            "description": "File not modified since the condition specified in If-Modified-Since or If-None-Match headers",
            "headers": {
              "Cache-Control": {
                "description": "Directives for caching mechanisms",
                "schema": {
                  "type": "string"
                }
              },
              "Etag": {
                "description": "Entity tag for cache validation",
                "schema": {
                  "type": "string"
                }
              },
              "Surrogate-Control": {
                "description": "Cache control directives for surrogate caching",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "412": {
            "description": "Precondition failed for conditional request headers (If-Match, If-Unmodified-Since)",
            "headers": {
              "Cache-Control": {
                "description": "Directives for caching mechanisms",
                "schema": {
                  "type": "string"
                }
              },
              "Etag": {
                "description": "Entity tag for cache validation",
                "schema": {
                  "type": "string"
                }
              },
              "Surrogate-Control": {
                "description": "Cache control directives for surrogate caching",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "description": "Error occurred",
            "headers": {
              "X-Error": {
                "description": "Error message details",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Replace file",
        "description": "Replace an existing file with new content while preserving the file ID. The operation follows these steps:\n1. The isUploaded flag is set to false to mark the file as being updated\n2. The file content is replaced in the storage backend\n3. File metadata is updated (size, mime-type, isUploaded, etc.)\n\nEach step is atomic, but if a step fails, previous steps will not be automatically rolled back.\n",
        "operationId": "replaceFile",
        "tags": [
          "files"
        ],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Unique identifier of the file to replace",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "File replacement data including new file content and optional metadata",
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "metadata": {
                    "$ref": "#/components/schemas/UpdateFileMetadata"
                  },
                  "file": {
                    "description": "New file content to replace the existing file",
                    "type": "string",
                    "format": "binary"
                  }
                }
              },
              "encoding": {
                "metadata": {
                  "contentType": "application/json"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "File successfully replaced",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileMetadata"
                }
              }
            }
          },
          "default": {
            "description": "Error occurred during file replacement",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/files/{id}/presignedurl": {
      "get": {
        "summary": "Retrieve presigned URL to retrieve the file",
        "operationId": "getFilePresignedURL",
        "description": "Retrieve presigned URL to retrieve the file. Expiration of the URL is\ndetermined by bucket configuration\n",
        "tags": [
          "storage"
        ],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Unique identifier of the file",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File gathered successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PresignedURLResponse"
                }
              }
            }
          },
          "default": {
            "description": "Some error occurred",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/files/{id}/presignedurl/contents": {
      "get": {
        "summary": "Retrieve contents of file",
        "operationId": "getFileWithPresignedURL",
        "description": "Retrieve contents of file",
        "tags": [
          "storage",
          "excludeme"
        ],
        "security": [
          {
            "Authorization": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "Unique identifier of the file",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Amz-Algorithm",
            "description": "Use presignedurl endpoint to generate this automatically",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Amz-Credential",
            "description": "Use presignedurl endpoint to generate this automatically",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Amz-Date",
            "description": "Use presignedurl endpoint to generate this automatically",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Amz-Expires",
            "description": "Use presignedurl endpoint to generate this automatically",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Amz-Signature",
            "description": "Use presignedurl endpoint to generate this automatically",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Amz-SignedHeaders",
            "description": "Use presignedurl endpoint to generate this automatically",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Amz-Checksum-Mode",
            "description": "Use presignedurl endpoint to generate this automatically",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Amz-Security-Token",
            "description": "Use presignedurl endpoint to generate this automatically",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-id",
            "description": "Use presignedurl endpoint to generate this automatically",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "if-match",
            "description": "Only return the file if the current ETag matches one of the values provided",
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "if-none-match",
            "description": "Only return the file if the current ETag does not match any of the values provided",
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "if-modified-since",
            "description": "Only return the file if it has been modified after the given date",
            "in": "header",
            "schema": {
              "$ref": "#/components/schemas/RFC2822Date"
            }
          },
          {
            "name": "if-unmodified-since",
            "description": "Only return the file if it has not been modified after the given date",
            "in": "header",
            "schema": {
              "$ref": "#/components/schemas/RFC2822Date"
            }
          },
          {
            "name": "q",
            "description": "Image quality (1-100). Only applies to JPEG, WebP, AVIF and HEIC files",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "h",
            "description": "Maximum height, in pixels, to resize image to while maintaining aspect ratio. Only applies to image files. Values above the server-configured maximum (default 8000) are rejected with a 400 error.",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "w",
            "description": "Maximum width, in pixels, to resize image to while maintaining aspect ratio. Only applies to image files. Values above the server-configured maximum (default 8000) are rejected with a 400 error.",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "b",
            "description": "Blur the image using this sigma value. Only applies to image files. Values above the server-configured maximum (default 250) are rejected with a 400 error.",
            "in": "query",
            "schema": {
              "type": "number",
              "minimum": 0
            }
          },
          {
            "name": "f",
            "description": "Output format for image files. Use 'auto' for content negotiation based on Accept header",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/OutputImageFormat"
            }
          },
          {
            "name": "Range",
            "description": "Range of bytes to retrieve from the file. Format: bytes=start-end",
            "in": "header",
            "schema": {
              "type": "string",
              "pattern": "^bytes=(\\d+-\\d*|\\d*-\\d+)(,(\\d+-\\d*|\\d*-\\d+))*$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File content retrieved successfully",
            "headers": {
              "Cache-Control": {
                "description": "Directives for caching mechanisms",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Type": {
                "description": "MIME type of the file",
                "schema": {
                  "type": "string"
                }
              },
              "Etag": {
                "description": "Entity tag for cache validation",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Disposition": {
                "description": "Indicates if the content should be displayed inline or as an attachment",
                "schema": {
                  "type": "string"
                }
              },
              "Last-Modified": {
                "description": "Date and time the file was last modified",
                "schema": {
                  "$ref": "#/components/schemas/RFC2822Date"
                }
              },
              "Surrogate-Key": {
                "description": "Cache key for surrogate caching",
                "schema": {
                  "type": "string"
                }
              },
              "Surrogate-Control": {
                "description": "Cache control directives for surrogate caching",
                "schema": {
                  "type": "string"
                }
              },
              "Accept-Ranges": {
                "description": "Always set to bytes. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Ranges",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/octet-stream": {}
            }
          },
          "206": {
            "description": "Partial file content retrieved successfully",
            "headers": {
              "Cache-Control": {
                "description": "Directives for caching mechanisms",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Type": {
                "description": "MIME type of the file",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Range": {
                "description": "Range of bytes returned in the response",
                "schema": {
                  "type": "string"
                }
              },
              "Etag": {
                "description": "Entity tag for cache validation",
                "schema": {
                  "type": "string"
                }
              },
              "Content-Disposition": {
                "description": "Indicates if the content should be displayed inline or as an attachment",
                "schema": {
                  "type": "string"
                }
              },
              "Last-Modified": {
                "description": "Date and time the file was last modified",
                "schema": {
                  "$ref": "#/components/schemas/RFC2822Date"
                }
              },
              "Surrogate-Key": {
                "description": "Cache key for surrogate caching",
                "schema": {
                  "type": "string"
                }
              },
              "Surrogate-Control": {
                "description": "Cache control directives for surrogate caching",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/octet-stream": {}
            }
          },
          "304": {
            "description": "File not modified since the condition specified in If-Modified-Since or If-None-Match headers",
            "headers": {
              "Cache-Control": {
                "description": "Directives for caching mechanisms",
                "schema": {
                  "type": "string"
                }
              },
              "Etag": {
                "description": "Entity tag for cache validation",
                "schema": {
                  "type": "string"
                }
              },
              "Surrogate-Control": {
                "description": "Cache control directives for surrogate caching",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "412": {
            "description": "Precondition failed for conditional request headers (If-Match, If-Unmodified-Since, If-None-Match)",
            "headers": {
              "Cache-Control": {
                "description": "Directives for caching mechanisms",
                "schema": {
                  "type": "string"
                }
              },
              "Etag": {
                "description": "Entity tag for cache validation",
                "schema": {
                  "type": "string"
                }
              },
              "Surrogate-Control": {
                "description": "Cache control directives for surrogate caching",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "default": {
            "description": "Error occurred",
            "headers": {
              "X-Error": {
                "description": "Error message details",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/openapi.yaml": {
      "get": {
        "summary": "Get OpenAPI specification",
        "description": "Returns the OpenAPI schema definition for this API, allowing clients to understand the available endpoints and models.",
        "operationId": "getOpenAPISpec",
        "tags": [
          "documentation",
          "excludeme"
        ],
        "responses": {
          "200": {
            "description": "OpenAPI schema definition",
            "content": {
              "application/x-yaml": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "default": {
            "description": "Error occurred",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/ops/delete-broken-metadata": {
      "post": {
        "summary": "Delete broken metadata",
        "operationId": "deleteBrokenMetadata",
        "description": "Broken metadata is defined as metadata that has isUploaded = true but there is no file in the storage matching it. This is an admin operation that requires the Hasura admin secret.",
        "tags": [
          "operations"
        ],
        "security": [
          {
            "X-Hasura-Admin-Secret": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully deleted broken metadata",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "metadata": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FileSummary"
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "En error occured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/ops/delete-orphans": {
      "post": {
        "summary": "Deletes orphaned files",
        "operationId": "deleteOrphanedFiles",
        "description": "Orphaned files are files that are present in the storage but have no associated metadata. This is an admin operation that requires the Hasura admin secret.",
        "tags": [
          "operations"
        ],
        "security": [
          {
            "X-Hasura-Admin-Secret": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully deleted orphaned files",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "files": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "En error occured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/ops/list-broken-metadata": {
      "post": {
        "summary": "Lists broken metadata",
        "operationId": "listBrokenMetadata",
        "description": "Broken metadata is defined as metadata that has isUploaded = true but there is no file in the storage matching it. This is an admin operation that requires the Hasura admin secret.",
        "tags": [
          "operations"
        ],
        "security": [
          {
            "X-Hasura-Admin-Secret": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully computed broken metadata",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "metadata": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FileSummary"
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "En error occured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/ops/list-not-uploaded": {
      "post": {
        "summary": "Lists files that haven't been uploaded",
        "operationId": "listFilesNotUploaded",
        "description": "That is, metadata that has isUploaded = false. This is an admin operation that requires the Hasura admin secret.",
        "tags": [
          "operations"
        ],
        "security": [
          {
            "X-Hasura-Admin-Secret": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully checked files not uploaded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "metadata": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FileSummary"
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "En error occured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/ops/list-orphans": {
      "post": {
        "summary": "Lists orphaned files",
        "operationId": "listOrphanedFiles",
        "description": "Orphaned files are files that are present in the storage but have no associated metadata. This is an admin operation that requires the Hasura admin secret.",
        "tags": [
          "operations"
        ],
        "security": [
          {
            "X-Hasura-Admin-Secret": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully computed orphaned files",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "files": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "description": "En error occured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/version": {
      "get": {
        "summary": "Get service version information",
        "description": "Retrieves build and version information about the storage service. Useful for monitoring and debugging.",
        "operationId": "getVersion",
        "tags": [
          "system"
        ],
        "responses": {
          "200": {
            "description": "Version information successfully retrieved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionInformation"
                }
              }
            }
          },
          "default": {
            "description": "Error occurred",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "Authorization": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "API key to authorize requests."
      },
      "X-Hasura-Admin-Secret": {
        "type": "apiKey",
        "name": "X-Hasura-Admin-Secret",
        "in": "header",
        "description": "Hasura admin secret key for backend/administrative operations."
      }
    },
    "schemas": {
      "RFC2822Date": {
        "type": "string",
        "description": "Date in RFC 2822 format",
        "pattern": "^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), \\d{1,2} (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \\d{4} \\d{2}:\\d{2}:\\d{2} \\w+$",
        "example": "Tue, 12 Aug 2025 12:03:50 GMT",
        "x-go-type": "Time"
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Error information returned by the API.",
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "description": "Error details.",
            "properties": {
              "message": {
                "type": "string",
                "description": "Human-readable error message.",
                "example": "File not found"
              },
              "data": {
                "type": "object",
                "additionalProperties": true,
                "description": "Additional data related to the error, if any."
              }
            },
            "required": [
              "message"
            ]
          }
        },
        "additionalProperties": false
      },
      "ErrorResponseWithProcessedFiles": {
        "type": "object",
        "description": "Error information returned by the API.",
        "properties": {
          "processedFiles": {
            "type": "array",
            "description": "List of files that were successfully processed before the error occurred.",
            "items": {
              "$ref": "#/components/schemas/FileMetadata"
            }
          },
          "error": {
            "type": "object",
            "additionalProperties": false,
            "description": "Error details.",
            "properties": {
              "message": {
                "type": "string",
                "description": "Human-readable error message.",
                "example": "File not found"
              },
              "data": {
                "type": "object",
                "additionalProperties": true,
                "description": "Additional data related to the error, if any."
              }
            },
            "required": [
              "message"
            ]
          }
        },
        "additionalProperties": false
      },
      "FileMetadata": {
        "type": "object",
        "description": "Comprehensive metadata information about a file in storage.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the file.",
            "example": "d5e76ceb-77a2-4153-b7da-1f7c115b2ff2"
          },
          "name": {
            "type": "string",
            "description": "Name of the file including extension.",
            "example": "profile-picture.jpg"
          },
          "size": {
            "description": "Size of the file in bytes.",
            "type": "integer",
            "format": "int64",
            "example": 245678
          },
          "bucketId": {
            "type": "string",
            "description": "ID of the bucket containing the file.",
            "example": "users-bucket"
          },
          "etag": {
            "type": "string",
            "description": "Entity tag for cache validation.",
            "example": "\"a1b2c3d4e5f6\""
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the file was created.",
            "example": "2023-01-15T12:34:56Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the file was last updated.",
            "example": "2023-01-16T09:45:32Z"
          },
          "isUploaded": {
            "type": "boolean",
            "description": "Whether the file has been successfully uploaded.",
            "example": true
          },
          "mimeType": {
            "type": "string",
            "description": "MIME type of the file.",
            "example": "image/jpeg"
          },
          "uploadedByUserId": {
            "type": "string",
            "description": "ID of the user who uploaded the file.",
            "example": "abc123def456"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "description": "Custom metadata associated with the file.",
            "example": {
              "alt": "Profile picture",
              "category": "avatar"
            }
          }
        },
        "required": [
          "id",
          "name",
          "size",
          "bucketId",
          "etag",
          "createdAt",
          "updatedAt",
          "isUploaded",
          "mimeType"
        ],
        "additionalProperties": false
      },
      "FileSummary": {
        "type": "object",
        "description": "Basic information about a file in storage.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier for the file.",
            "example": "d5e76ceb-77a2-4153-b7da-1f7c115b2ff2"
          },
          "name": {
            "type": "string",
            "description": "Name of the file including extension.",
            "example": "profile-picture.jpg"
          },
          "bucketId": {
            "type": "string",
            "description": "ID of the bucket containing the file.",
            "example": "users-bucket"
          },
          "isUploaded": {
            "type": "boolean",
            "description": "Whether the file has been successfully uploaded.",
            "example": true
          }
        },
        "additionalProperties": false,
        "required": [
          "id",
          "name",
          "bucketId",
          "isUploaded"
        ]
      },
      "PresignedURLResponse": {
        "type": "object",
        "description": "Contains a presigned URL for direct file operations.",
        "properties": {
          "url": {
            "type": "string",
            "description": "The presigned URL for file operations.",
            "example": "https://storage.example.com/files/abc123?signature=xyz"
          },
          "expiration": {
            "type": "integer",
            "description": "The time in seconds until the URL expires.",
            "example": 3600
          }
        },
        "required": [
          "url",
          "expiration"
        ],
        "additionalProperties": false
      },
      "UpdateFileMetadata": {
        "type": "object",
        "description": "Metadata that can be updated for an existing file.",
        "properties": {
          "name": {
            "type": "string",
            "description": "New name to assign to the file.",
            "example": "renamed-file.jpg"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "description": "Updated custom metadata to associate with the file.",
            "example": {
              "alt": "Updated image description",
              "category": "profile"
            }
          }
        },
        "additionalProperties": false
      },
      "UploadFileMetadata": {
        "type": "object",
        "description": "Metadata provided when uploading a new file.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Optional custom ID for the file. If not provided, a UUID will be generated.",
            "example": "custom-id-123"
          },
          "name": {
            "type": "string",
            "description": "Name to assign to the file. If not provided, the original filename will be used.",
            "example": "custom-filename.png"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "description": "Custom metadata to associate with the file.",
            "example": {
              "alt": "Custom image",
              "category": "document"
            }
          }
        },
        "additionalProperties": false
      },
      "VersionInformation": {
        "type": "object",
        "description": "Contains version information about the storage service.",
        "additionalProperties": false,
        "properties": {
          "buildVersion": {
            "type": "string",
            "description": "The version number of the storage service build.",
            "example": "1.2.3"
          }
        },
        "required": [
          "buildVersion"
        ]
      },
      "OutputImageFormat": {
        "type": "string",
        "description": "Output format for image files. Use 'auto' for content negotiation based on Accept header",
        "default": "same",
        "enum": [
          "auto",
          "same",
          "jpeg",
          "webp",
          "png",
          "avif",
          "heic"
        ],
        "example": "same"
      }
    }
  }
}
