{
  "openapi": "3.0.0",
  "info": {
    "title": "Hostim API",
    "version": "1.0.0",
    "description": "> **Beta.** This API is in beta. Endpoints, request and response fields, and\n> behaviour can change between releases while we stabilise it. This reference\n> always reflects the current API.\n\nThe Hostim public REST API lets you provision and manage projects, apps,\ndatabases (MySQL, Postgres, Redis) and volumes programmatically — from CI/CD\npipelines, scripts, or infrastructure-as-code.\n\n## Base URL\n\n```\nhttps://api.hostim.dev\n```\n\n## Rate limits\n\nAPI traffic is rate limited per token using a token bucket: **20 requests/second\nsustained, with a burst of 60**. Exceeding the limit returns HTTP `429 Too Many\nRequests` with a `Retry-After` header (seconds to wait) and a `GenericMessage`\nbody whose `error` is `rate_limited`. Back off for the `Retry-After` interval\nbefore retrying; a token bucket refills continuously, so steady-state traffic at\nor below the sustained rate is never throttled.\n"
  },
  "servers": [
    {
      "url": "https://api.hostim.dev",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "schemas": {
      "DeviceAuthorization": {
        "type": "object",
        "properties": {
          "deviceCode": {
            "type": "string",
            "description": "Secret held by the client; poll /api/users/device/token with it."
          },
          "userCode": {
            "type": "string",
            "description": "Short code the user types on the approval page."
          },
          "verificationUri": {
            "type": "string",
            "description": "Page where the user approves the request."
          },
          "verificationUriComplete": {
            "type": "string",
            "description": "Same page with the user code pre-filled."
          },
          "expiresIn": {
            "type": "integer",
            "description": "Seconds until the authorization expires."
          },
          "interval": {
            "type": "integer",
            "description": "Minimum seconds between polls."
          }
        },
        "required": [
          "deviceCode",
          "userCode",
          "verificationUri",
          "expiresIn",
          "interval"
        ]
      },
      "DeviceTokenResult": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "approved",
              "denied",
              "expired"
            ]
          },
          "token": {
            "type": "string",
            "description": "Bearer API token; present only when status is approved."
          }
        },
        "required": [
          "status"
        ]
      },
      "GenericMessage": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ]
      },
      "Region": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "ingressIp": {
            "type": "string"
          },
          "bastionHost": {
            "type": "string"
          }
        }
      },
      "Project": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The project friendly name set by the user"
          },
          "region": {
            "type": "string",
            "description": "The project region"
          },
          "id": {
            "type": "string",
            "description": "The project id generated by the system"
          },
          "allTimeCosts": {
            "type": "number",
            "description": "The all time costs of the project"
          },
          "projectedMonthlyCosts": {
            "type": "number",
            "description": "The projected monthly costs of the project"
          },
          "deployedServices": {
            "type": "number",
            "description": "The number of deployed services"
          },
          "sshKeys": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The SSH keys for the project"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "The timestamp when the project was created"
          },
          "trialExpiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "The timestamp when the project trial expires"
          },
          "accessLevel": {
            "type": "string",
            "enum": [
              "owner",
              "maintainer"
            ],
            "description": "The current user's access level to this project"
          }
        },
        "required": [
          "id",
          "sshKeys"
        ]
      },
      "App": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The app name"
          },
          "replicas": {
            "type": "integer",
            "description": "The number of replicas"
          },
          "public": {
            "type": "boolean",
            "description": "Whether the app is public or not",
            "default": false
          },
          "builtInDomain": {
            "type": "string",
            "description": "The built-in domain of the app"
          },
          "domains": {
            "type": "array",
            "description": "The domains of the app",
            "items": {
              "type": "string"
            }
          },
          "httpPort": {
            "type": "integer",
            "description": "The http port",
            "nullable": true
          },
          "healthCheckPath": {
            "type": "string",
            "description": "HTTP path used for the readiness probe. Empty/unset disables it.",
            "nullable": true
          },
          "plan": {
            "type": "string",
            "description": "The plan of the app"
          },
          "type": {
            "type": "string",
            "description": "The type of the app (shared or dedicated)"
          },
          "ram": {
            "type": "number",
            "description": "The amount of RAM"
          },
          "cpu": {
            "type": "number",
            "description": "The amount of CPU"
          },
          "deploymentSource": {
            "type": "object",
            "description": "The deployment source",
            "properties": {
              "type": {
                "type": "string",
                "description": "The deployment source type",
                "enum": [
                  "git",
                  "docker"
                ]
              },
              "docker": {
                "type": "object",
                "description": "The docker deployment source",
                "properties": {
                  "image": {
                    "type": "string",
                    "description": "The docker image"
                  },
                  "username": {
                    "type": "string",
                    "description": "The docker username"
                  },
                  "password": {
                    "type": "string",
                    "writeOnly": true,
                    "description": "The docker registry password. Write-only: accepted on create/update but never returned in cleartext on read; read responses return \"***\" when a password is set. Send \"***\" back unchanged to keep the stored value."
                  },
                  "registry": {
                    "type": "string",
                    "description": "The docker registry host, derived from the image reference. Ignored on create and update: the backend overwrites it with the host parsed out of `image`, so write the registry into the image instead (e.g. `registry.example.com/me/app:1.0`). Not marked readOnly, so clients can send a read app back unchanged."
                  }
                },
                "required": [
                  "image"
                ]
              },
              "git": {
                "type": "object",
                "description": "The git deployment source",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "The git url"
                  },
                  "branch": {
                    "type": "string",
                    "description": "The git branch"
                  },
                  "token": {
                    "type": "string",
                    "writeOnly": true,
                    "description": "The git access token for private repos. Write-only: accepted on create/update but never returned in cleartext on read; read responses return \"***\" when a token is set. Send \"***\" back unchanged to keep the stored value."
                  },
                  "dockerfilepath": {
                    "type": "string",
                    "description": "The path to the dockerfile"
                  }
                },
                "required": [
                  "url"
                ]
              }
            },
            "required": [
              "type"
            ]
          },
          "commandOverride": {
            "type": "string",
            "description": "The command override"
          },
          "volumeMounts": {
            "type": "array",
            "description": "The storage volumes",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "The volume name"
                },
                "mountPath": {
                  "type": "string",
                  "description": "The volume mount path"
                }
              }
            }
          },
          "envVars": {
            "type": "array",
            "description": "The environment variables",
            "items": {
              "$ref": "#/components/schemas/EnvVar"
            }
          },
          "cost": {
            "type": "number",
            "description": "The cost of the app per month"
          }
        },
        "required": [
          "name",
          "replicas",
          "plan",
          "public",
          "domains",
          "deploymentSource",
          "volumeMounts"
        ]
      },
      "AppStatus": {
        "type": "object",
        "properties": {
          "buildStatus": {
            "type": "string",
            "description": "The build status",
            "nullable": true,
            "enum": [
              "running",
              "failed",
              "succeeded"
            ]
          },
          "lastBuiltAt": {
            "type": "string",
            "description": "The last built at",
            "nullable": true,
            "format": "date-time"
          },
          "runtimeStatus": {
            "type": "string",
            "description": "The runtime status",
            "nullable": true,
            "enum": [
              "pending",
              "running",
              "crashing",
              "unhealthy",
              "imagePullBackoff",
              "stopped"
            ]
          },
          "lastDeployedAt": {
            "type": "string",
            "description": "The last deployed at",
            "nullable": true,
            "format": "date-time"
          },
          "internalDNS": {
            "type": "string",
            "description": "The internal DNS",
            "nullable": true
          },
          "gitCommit": {
            "type": "string",
            "description": "The git commit SHA the running image was built from (git apps only)",
            "nullable": true
          },
          "certificates": {
            "description": "Certificates is the status of the certificates",
            "items": {
              "description": "CertificateStatus is the status of the certificate",
              "properties": {
                "domain": {
                  "description": "Domain is the domain of the certificate",
                  "type": "string"
                },
                "status": {
                  "description": "Status is the status of the certificate",
                  "type": "string"
                }
              },
              "required": [
                "domain",
                "status"
              ],
              "type": "object"
            },
            "type": "array"
          }
        }
      },
      "DomainStatus": {
        "type": "object",
        "description": "DNS resolution status of one custom domain",
        "properties": {
          "domain": {
            "type": "string",
            "description": "The domain"
          },
          "expectedIP": {
            "type": "string",
            "description": "The ingress IP the domain must point to"
          },
          "resolvedIPs": {
            "type": "array",
            "description": "The IPs the domain currently resolves to, empty if it does not resolve",
            "items": {
              "type": "string"
            }
          },
          "pointing": {
            "type": "boolean",
            "description": "True if the domain resolves to the expected IP"
          }
        },
        "required": [
          "domain",
          "expectedIP",
          "resolvedIPs",
          "pointing"
        ]
      },
      "AppPricing": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The pricing plan name"
          },
          "price": {
            "type": "number",
            "description": "The price of the app"
          },
          "ram": {
            "type": "integer",
            "description": "The ram of the app"
          },
          "cores": {
            "type": "integer",
            "description": "The cores of the app"
          },
          "type": {
            "type": "string",
            "description": "The type of the app",
            "enum": [
              "shared",
              "dedicated"
            ]
          },
          "available": {
            "type": "boolean",
            "description": "Whether the plan is available or not"
          }
        },
        "required": [
          "name",
          "price",
          "ram",
          "cores",
          "type",
          "available"
        ]
      },
      "Volume": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The volume name"
          },
          "plan": {
            "type": "string",
            "description": "The volume plan"
          },
          "cost": {
            "type": "number",
            "description": "The cost of the volume per month"
          },
          "storageMB": {
            "type": "number",
            "description": "The size of the volume in MB"
          }
        },
        "required": [
          "name",
          "plan"
        ]
      },
      "VolumePricing": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The pricing plan name"
          },
          "price": {
            "type": "number",
            "description": "The price of the volume"
          },
          "storageMB": {
            "type": "integer",
            "description": "The size of the volume in MB"
          },
          "available": {
            "type": "boolean",
            "description": "Whether the volume is available"
          }
        },
        "required": [
          "name",
          "price",
          "storageMB",
          "available"
        ]
      },
      "EnvVar": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The env var name"
          },
          "value": {
            "type": "string",
            "description": "The env var value"
          }
        },
        "required": [
          "name",
          "value"
        ]
      },
      "MySQL": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The MySQL name"
          },
          "plan": {
            "type": "string",
            "description": "The plan of the MySQL instance"
          },
          "cost": {
            "type": "number",
            "description": "The cost of the MySQL instance per month"
          },
          "type": {
            "type": "string",
            "description": "The type of the mysql instance, either shared or dedicated"
          },
          "ram": {
            "type": "number",
            "description": "The amount of RAM in GB"
          },
          "cores": {
            "type": "number",
            "description": "The number of CPU cores"
          },
          "storageMB": {
            "type": "number",
            "description": "The amount of storage in MB"
          }
        },
        "required": [
          "name",
          "plan"
        ]
      },
      "MySQLCredentials": {
        "type": "object",
        "properties": {
          "hostname": {
            "type": "string",
            "description": "The MySQL hostname"
          },
          "port": {
            "type": "string",
            "description": "The MySQL port"
          },
          "username": {
            "type": "string",
            "description": "The MySQL username"
          },
          "password": {
            "type": "string",
            "description": "The MySQL password"
          },
          "database": {
            "type": "string",
            "description": "The MySQL database"
          }
        },
        "required": [
          "username",
          "password",
          "hostname",
          "port",
          "database"
        ]
      },
      "MySQLStatus": {
        "type": "object",
        "properties": {
          "usedMB": {
            "type": "integer",
            "description": "The used storage of mysql database in MB"
          },
          "role": {
            "type": "string",
            "description": "The role of the mysql instance",
            "enum": [
              "standard",
              "cleaner",
              "revoked",
              "reader"
            ]
          },
          "migrationStatus": {
            "type": "string",
            "description": "The migration status of the mysql instance",
            "nullable": true,
            "enum": [
              "None",
              "Scheduled",
              "InProgress",
              "Succeeded",
              "Failed"
            ]
          },
          "created": {
            "type": "boolean",
            "description": "Whether the mysql database instance is created or not"
          }
        },
        "required": [
          "usedMB",
          "role",
          "created"
        ]
      },
      "MySQLPricing": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The pricing plan name"
          },
          "price": {
            "type": "number",
            "description": "The price of the MySQL instance"
          },
          "storageMB": {
            "type": "integer",
            "description": "The storage of the MySQL instance in MB"
          },
          "type": {
            "type": "string",
            "description": "The type of the MySQL instance",
            "enum": [
              "dedicated",
              "shared"
            ]
          },
          "cores": {
            "type": "integer",
            "description": "The cores of the MySQL instance"
          },
          "ram": {
            "type": "integer",
            "description": "The ram of the MySQL instance"
          },
          "available": {
            "type": "boolean",
            "description": "Whether the plan is available or not"
          }
        },
        "required": [
          "name",
          "price",
          "storageMB",
          "type",
          "available"
        ]
      },
      "Postgres": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The PostgreSQL name"
          },
          "plan": {
            "type": "string",
            "description": "The plan of the PostgreSQL instance"
          },
          "cost": {
            "type": "number",
            "description": "The cost of the PostgreSQL instance per month"
          },
          "type": {
            "type": "string",
            "description": "The type of the PostgreSQL instance, either shared or dedicated"
          },
          "ram": {
            "type": "number",
            "description": "The amount of RAM in GB"
          },
          "cores": {
            "type": "number",
            "description": "The number of CPU cores"
          },
          "storageMB": {
            "type": "number",
            "description": "The amount of storage in MB"
          },
          "extensions": {
            "type": "array",
            "description": "Extensions requested for this database. Only names returned by /api/postgres/extensions are accepted. Removing a name does not uninstall the extension.",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "name",
          "plan"
        ]
      },
      "PostgresCredentials": {
        "type": "object",
        "properties": {
          "hostname": {
            "type": "string",
            "description": "The PostgreSQL hostname"
          },
          "port": {
            "type": "string",
            "description": "The PostgreSQL port"
          },
          "username": {
            "type": "string",
            "description": "The PostgreSQL username"
          },
          "password": {
            "type": "string",
            "description": "The PostgreSQL password"
          },
          "database": {
            "type": "string",
            "description": "The PostgreSQL database"
          }
        },
        "required": [
          "username",
          "password",
          "hostname",
          "port",
          "database"
        ]
      },
      "PostgresStatus": {
        "type": "object",
        "properties": {
          "usedMB": {
            "type": "integer",
            "description": "The used storage of PostgreSQL database in MB"
          },
          "role": {
            "type": "string",
            "description": "The role of the PostgreSQL instance",
            "enum": [
              "standard",
              "cleaner",
              "revoked",
              "reader"
            ]
          },
          "migrationStatus": {
            "type": "string",
            "description": "The migration status of the PostgreSQL instance",
            "nullable": true,
            "enum": [
              "None",
              "Scheduled",
              "InProgress",
              "Succeeded",
              "Failed"
            ]
          },
          "created": {
            "type": "boolean",
            "description": "Whether the PostgreSQL database instance is created or not"
          },
          "installedExtensions": {
            "type": "array",
            "description": "Extensions actually installed in the database, including ones installed outside of the requested list",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "usedMB",
          "role",
          "created"
        ]
      },
      "PostgresPricing": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The pricing plan name"
          },
          "price": {
            "type": "number",
            "description": "The price of the PostgreSQL instance"
          },
          "storageMB": {
            "type": "integer",
            "description": "The storage of the PostgreSQL instance in MB"
          },
          "type": {
            "type": "string",
            "description": "The type of the PostgreSQL instance",
            "enum": [
              "dedicated",
              "shared"
            ]
          },
          "cores": {
            "type": "integer",
            "description": "The cores of the PostgreSQL instance"
          },
          "ram": {
            "type": "integer",
            "description": "The RAM of the PostgreSQL instance"
          },
          "available": {
            "type": "boolean",
            "description": "Whether the plan is available or not"
          }
        },
        "required": [
          "name",
          "price",
          "storageMB",
          "type",
          "available"
        ]
      },
      "Redis": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The Redis name"
          },
          "plan": {
            "type": "string",
            "description": "The plan of the Redis instance"
          },
          "cost": {
            "type": "number",
            "description": "The cost of the Redis instance per month"
          },
          "storage": {
            "type": "number",
            "description": "The storage of the Redis instance"
          }
        },
        "required": [
          "name",
          "plan"
        ]
      },
      "RedisCredentials": {
        "type": "object",
        "properties": {
          "hostname": {
            "type": "string",
            "description": "The Redis hostname"
          },
          "port": {
            "type": "integer",
            "description": "The Redis port"
          },
          "password": {
            "type": "string",
            "description": "The Redis password"
          }
        },
        "required": [
          "hostname",
          "port",
          "password"
        ]
      },
      "RedisStatus": {
        "type": "object",
        "properties": {
          "available": {
            "type": "boolean",
            "description": "Whether the redis database instance is available or not"
          }
        },
        "required": [
          "available"
        ]
      },
      "RedisPricing": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The pricing plan name"
          },
          "price": {
            "type": "number",
            "description": "The price of the Redis instance"
          },
          "storage": {
            "type": "string",
            "description": "The storage of the Redis instance"
          },
          "available": {
            "type": "boolean",
            "description": "Whether the plan is available or not"
          }
        },
        "required": [
          "name",
          "price",
          "storage",
          "available"
        ]
      },
      "Event": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "The Kubernetes event type",
            "enum": [
              "Normal",
              "Warning"
            ]
          },
          "reason": {
            "type": "string",
            "description": "A short, machine-understandable reason for the event"
          },
          "message": {
            "type": "string",
            "description": "A human-readable message describing the event"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "When the event occurred"
          },
          "project": {
            "type": "string",
            "description": "The project this event belongs to"
          },
          "source": {
            "type": "string",
            "description": "The origin of the event",
            "enum": [
              "infra",
              "admin"
            ]
          },
          "serviceType": {
            "type": "string",
            "description": "The type of resource this event is about (e.g. app, mysql, postgres, redis)",
            "enum": [
              "app",
              "mysql",
              "postgres",
              "redis"
            ],
            "nullable": true
          },
          "serviceName": {
            "type": "string",
            "description": "Name of the service/app/database this event is related to",
            "nullable": true
          }
        },
        "required": [
          "type",
          "reason",
          "message",
          "timestamp",
          "project",
          "source"
        ]
      },
      "Log": {
        "type": "object",
        "description": "The log object, used for logs",
        "properties": {
          "type": {
            "type": "string",
            "description": "The log type",
            "enum": [
              "http",
              "stdout",
              "build"
            ]
          },
          "message": {
            "type": "string",
            "description": "The log message"
          },
          "timestamp": {
            "type": "string",
            "description": "The log timestamp (Unix timestamp in nanoseconds)"
          }
        },
        "required": [
          "message",
          "timestamp",
          "type"
        ]
      },
      "Template": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "description": "Logical grouping for UI (e.g. 'Examples', 'Open Source', 'Custom')"
          },
          "sourceUrl": {
            "type": "string",
            "format": "uri",
            "description": "Optional link to GitHub or external documentation"
          },
          "notes": {
            "type": "array",
            "description": "Optional setup notes or tips, such as default credentials",
            "items": {
              "type": "string"
            }
          },
          "components": {
            "type": "object",
            "properties": {
              "apps": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/App"
                }
              },
              "volumes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Volume"
                }
              },
              "mysql": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/MySQL"
                }
              },
              "postgres": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Postgres"
                }
              },
              "redis": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Redis"
                }
              }
            },
            "required": [
              "apps",
              "volumes",
              "mysql",
              "postgres",
              "redis"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "components"
        ]
      },
      "BackupItem": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "description": "postgres, mysql or volume"
          },
          "name": {
            "type": "string",
            "description": "Name of the database or volume"
          },
          "phase": {
            "type": "string",
            "description": "Pending, Running, Succeeded or Failed"
          },
          "id": {
            "type": "string",
            "description": "The restic short snapshot ID of this item"
          },
          "sizeBytes": {
            "type": "integer",
            "format": "int64",
            "description": "Full size of the backed up data. Missing for backups made before sizes were recorded."
          },
          "error": {
            "type": "string",
            "description": "The reason the item failed"
          },
          "pruned": {
            "type": "boolean",
            "description": "Restic removed this snapshot under the retention policy; it can no longer be downloaded"
          }
        },
        "required": [
          "kind",
          "name",
          "phase"
        ]
      },
      "BackupRun": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The name of the Backup custom resource"
          },
          "trigger": {
            "type": "string",
            "description": "What created the run"
          },
          "scheduledTime": {
            "type": "string",
            "format": "date-time",
            "description": "The cron tick this run belongs to"
          },
          "phase": {
            "type": "string",
            "description": "Pending, Running, Succeeded, PartiallyFailed or Failed"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the run started"
          },
          "completedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the run reached a terminal phase"
          },
          "items": {
            "type": "array",
            "description": "The state of each database and volume in the run",
            "items": {
              "$ref": "#/components/schemas/BackupItem"
            }
          }
        },
        "required": [
          "name",
          "trigger",
          "phase",
          "items"
        ]
      },
      "BackupRetention": {
        "type": "object",
        "description": "The restic forget policy read from the project, read-only. A field that is not set is not passed to restic.",
        "properties": {
          "keepLast": {
            "type": "integer",
            "description": "Keep the last N snapshots"
          },
          "keepDaily": {
            "type": "integer",
            "description": "Keep the last N daily snapshots"
          },
          "keepWeekly": {
            "type": "integer",
            "description": "Keep the last N weekly snapshots"
          },
          "keepMonthly": {
            "type": "integer",
            "description": "Keep the last N monthly snapshots"
          }
        }
      },
      "BackupResource": {
        "type": "object",
        "description": "One database or volume of a project and the state of its backups.",
        "properties": {
          "kind": {
            "type": "string",
            "description": "postgres, mysql or volume"
          },
          "name": {
            "type": "string",
            "description": "Name of the database or volume"
          },
          "lastBackupTime": {
            "type": "string",
            "format": "date-time",
            "description": "When the last successful backup of this resource ran"
          }
        },
        "required": [
          "kind",
          "name"
        ]
      },
      "BackupOverview": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Whether backups are configured for the project"
          },
          "ready": {
            "type": "boolean",
            "description": "Whether the restic repository is initialized"
          },
          "schedule": {
            "type": "string",
            "description": "The backup cron schedule from the project, UTC"
          },
          "nextRunTime": {
            "type": "string",
            "format": "date-time",
            "description": "When the next scheduled backup runs, omitted when the schedule is empty or invalid"
          },
          "retention": {
            "$ref": "#/components/schemas/BackupRetention"
          },
          "manualRetention": {
            "$ref": "#/components/schemas/BackupRetention"
          },
          "resources": {
            "type": "array",
            "description": "Every database and volume of the project",
            "items": {
              "$ref": "#/components/schemas/BackupResource"
            }
          },
          "runs": {
            "type": "array",
            "description": "The backup runs, newest first",
            "items": {
              "$ref": "#/components/schemas/BackupRun"
            }
          }
        },
        "required": [
          "enabled",
          "ready",
          "schedule",
          "retention",
          "resources",
          "runs"
        ]
      },
      "Backup": {
        "type": "object",
        "description": "One successful backup of a database or volume. The ID is the restic short snapshot ID.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The restic short snapshot ID"
          },
          "time": {
            "type": "string",
            "format": "date-time",
            "description": "When the backup ran"
          },
          "trigger": {
            "type": "string",
            "description": "What created the backup"
          },
          "sizeBytes": {
            "type": "integer",
            "format": "int64",
            "description": "Full size of the backed up data. Missing for backups made before sizes were recorded."
          }
        },
        "required": [
          "id",
          "time",
          "trigger"
        ]
      },
      "BackupList": {
        "type": "object",
        "description": "The backups of one resource, newest first.",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Backup"
            }
          }
        },
        "required": [
          "items"
        ]
      },
      "BackupItemRef": {
        "type": "object",
        "description": "Selects one database or volume for a manual backup. Both fields empty or missing means the whole project.",
        "properties": {
          "kind": {
            "type": "string",
            "x-go-type-skip-optional-pointer": true,
            "enum": [
              "postgres",
              "mysql",
              "volume"
            ]
          },
          "name": {
            "type": "string",
            "x-go-type-skip-optional-pointer": true,
            "description": "Name of the database or volume"
          }
        }
      },
      "BackupDownload": {
        "type": "object",
        "description": "A prepared download of one backed up database or volume.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The restic short snapshot ID of the backup"
          },
          "phase": {
            "type": "string",
            "description": "Pending, Running, Succeeded or Failed"
          },
          "fileName": {
            "type": "string",
            "description": "The name of the prepared download file"
          },
          "sizeBytes": {
            "type": "integer",
            "format": "int64",
            "description": "The size of the prepared download file"
          },
          "url": {
            "type": "string",
            "description": "The pre-signed download URL, valid until expiresAt"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the download URL stops working"
          },
          "error": {
            "type": "string",
            "description": "The reason the download failed"
          }
        },
        "required": [
          "id",
          "phase",
          "fileName"
        ]
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API token",
        "description": "All requests are authenticated with a **Bearer API token**:\n\n```\nAuthorization: Bearer <your-api-token>\n```\n\nMint and revoke tokens in the [Hostim console](https://hostim.dev) under **API tokens**. Treat a token like a password — it carries the full access of your account. Revoke it in the console if it leaks.\n"
      }
    }
  },
  "paths": {
    "/api/users/device/authorize": {
      "post": {
        "summary": "Start a device authorization",
        "description": "Starts a device-code login (RFC 8628). The client shows the user code and verification URI to the user, then polls /api/users/device/token until the user approves.",
        "operationId": "deviceAuthorize",
        "tags": [
          "device"
        ],
        "security": [],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "clientName": {
                    "type": "string",
                    "description": "Human-readable name of the client requesting access."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authorization started",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceAuthorization"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/users/device/token": {
      "post": {
        "summary": "Poll a device authorization",
        "description": "Polls a device authorization. Returns pending until the user approves, then the API token exactly once.",
        "operationId": "deviceToken",
        "tags": [
          "device"
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "deviceCode": {
                    "type": "string"
                  }
                },
                "required": [
                  "deviceCode"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Current state of the authorization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceTokenResult"
                }
              }
            }
          },
          "400": {
            "description": "Unknown or already-consumed device code",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/regions": {
      "get": {
        "summary": "Get all regions",
        "description": "Get all regions from the database",
        "operationId": "getRegions",
        "security": [],
        "tags": [
          "regions"
        ],
        "responses": {
          "200": {
            "description": "Regions found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Regions not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/regions/{regionName}": {
      "get": {
        "summary": "Get a region",
        "description": "Get a region from the database",
        "operationId": "getRegion",
        "tags": [
          "regions"
        ],
        "parameters": [
          {
            "name": "regionName",
            "in": "path",
            "description": "Name of the region to get",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Region found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Region"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Region not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/regions/{regionName}/pricing/apps": {
      "get": {
        "summary": "Get region app pricing",
        "description": "Get region pricing",
        "operationId": "getRegionAppPricing",
        "security": [],
        "tags": [
          "regions"
        ],
        "parameters": [
          {
            "name": "regionName",
            "in": "path",
            "description": "Name of region to get pricing from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Region pricing found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AppPricing"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Region not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/regions/{regionName}/pricing/volume": {
      "get": {
        "summary": "Get region volume pricing",
        "description": "Get region volume pricing",
        "operationId": "getRegionVolumePricing",
        "security": [],
        "tags": [
          "regions"
        ],
        "parameters": [
          {
            "name": "regionName",
            "in": "path",
            "description": "Name of region to get volume pricing from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Region volume pricing found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/VolumePricing"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Region not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/regions/{regionName}/pricing/mysql": {
      "get": {
        "summary": "Get region MySQL pricing",
        "description": "Get region MySQL pricing",
        "operationId": "getRegionMySQLPricing",
        "security": [],
        "tags": [
          "regions"
        ],
        "parameters": [
          {
            "name": "regionName",
            "in": "path",
            "description": "Name of region to get MySQL pricing from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Region MySQL pricing found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MySQLPricing"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Region not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/regions/{regionName}/pricing/postgres": {
      "get": {
        "summary": "Get region PostgreSQL pricing",
        "description": "Get region PostgreSQL pricing",
        "operationId": "getRegionPostgresPricing",
        "security": [],
        "tags": [
          "regions"
        ],
        "parameters": [
          {
            "name": "regionName",
            "in": "path",
            "description": "Name of region to get PostgreSQL pricing from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Region PostgreSQL pricing found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PostgresPricing"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Region not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/regions/{regionName}/pricing/redis": {
      "get": {
        "summary": "Get region Redis pricing",
        "description": "Get region Redis pricing",
        "operationId": "getRegionRedisPricing",
        "security": [],
        "tags": [
          "regions"
        ],
        "parameters": [
          {
            "name": "regionName",
            "in": "path",
            "description": "Name of region to get Redis pricing from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Region Redis pricing found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RedisPricing"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Region not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/postgres/extensions": {
      "get": {
        "summary": "Get available PostgreSQL extensions",
        "description": "Get the PostgreSQL extensions a database may request",
        "operationId": "getPostgresExtensions",
        "security": [],
        "tags": [
          "postgres"
        ],
        "responses": {
          "200": {
            "description": "PostgreSQL extensions found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/templates": {
      "get": {
        "summary": "Get all templates",
        "description": "Get all templates from the database",
        "operationId": "getTemplates",
        "tags": [
          "templates"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Templates found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Template"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Templates not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/templates/docker-compose": {
      "post": {
        "summary": "Parse Docker Compose file into a deployment template",
        "description": "Uploads a Docker Compose YAML file and returns a generated deployment template",
        "operationId": "parseDockerCompose",
        "tags": [
          "templates"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "composeYAML": {
                    "type": "string",
                    "description": "Raw Docker Compose YAML content"
                  }
                },
                "required": [
                  "composeYAML"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Parsed template returned successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                }
              }
            }
          },
          "400": {
            "description": "Invalid file or parsing error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects": {
      "get": {
        "summary": "Get all projects",
        "description": "Get all projects from the database",
        "operationId": "getProjects",
        "tags": [
          "projects"
        ],
        "responses": {
          "200": {
            "description": "Projects found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Project"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Projects not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a project",
        "description": "Create a project gets a region as a query parameter and returns the project",
        "operationId": "createProject",
        "tags": [
          "projects"
        ],
        "parameters": [
          {
            "name": "regionName",
            "in": "query",
            "description": "Name of the region",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "description": "Friendly name of project",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Project created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}": {
      "get": {
        "summary": "Get a project",
        "description": "Get a project from the database",
        "operationId": "getProject",
        "tags": [
          "projects"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Project found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Update a project",
        "description": "Update a project",
        "operationId": "updateProject",
        "tags": [
          "projects"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "ID of project to update",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "description": "Friendly name of project to update",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "sshKeys to update",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Project updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a project",
        "description": "Delete a project",
        "operationId": "deleteProject",
        "tags": [
          "projects"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "ID of project to delete",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Project deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/globalenv": {
      "get": {
        "summary": "Get global environment variables",
        "description": "Get global environment variables",
        "operationId": "getGlobalEnv",
        "tags": [
          "globalenv"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get global environment variables from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EnvVar"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Set global environment variables",
        "description": "Set global environment variables",
        "operationId": "setGlobalEnv",
        "tags": [
          "globalenv"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to update global environment variables in",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Global environment variables to update",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/EnvVar"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Global environment variables updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/apps": {
      "get": {
        "summary": "Get all apps in a project",
        "description": "Get all apps in a project from the database",
        "operationId": "getApps",
        "tags": [
          "apps"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get apps from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Apps found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/App"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Apps not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create an app",
        "description": "Create an app gets a project as a query parameter and returns the app",
        "operationId": "createApp",
        "tags": [
          "apps"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to create app in",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "App to create",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/App"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "App created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/App"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "409": {
            "description": "Domain already in use",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/events": {
      "get": {
        "summary": "Get project events",
        "description": "Get project events",
        "operationId": "getProjectEvents",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Project events found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/events/stream": {
      "get": {
        "summary": "Get project events stream",
        "description": "Establishes a stream of events for a given project",
        "operationId": "streamProjectEvents",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get project events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Project events found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Event"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/apps/{appName}": {
      "delete": {
        "summary": "Delete an app",
        "description": "Delete an app",
        "operationId": "deleteApp",
        "tags": [
          "apps"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to delete app from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to delete",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "App deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/App"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "Get an app",
        "description": "Get an app",
        "operationId": "getApp",
        "tags": [
          "apps"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get app from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to get",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "App found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/App"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Update an app",
        "description": "Update an app",
        "operationId": "updateApp",
        "tags": [
          "apps"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to update app in",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to update",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "App to update",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/App"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "App updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/App"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "409": {
            "description": "Domain already in use",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/apps/{appName}/status": {
      "get": {
        "summary": "Get app status",
        "description": "Get app status",
        "operationId": "getAppStatus",
        "tags": [
          "apps"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get app status from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to get status",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "App status found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppStatus"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/apps/{appName}/restart": {
      "post": {
        "summary": "Restart an app",
        "description": "Restart an app",
        "operationId": "restartApp",
        "tags": [
          "apps"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to restart app in",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to restart",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "App restarted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/apps/{appName}/rebuild": {
      "post": {
        "summary": "Rebuild an app",
        "description": "Rebuild an app",
        "operationId": "rebuildApp",
        "tags": [
          "apps"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to rebuild app in",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to rebuild",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "App rebuilt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/apps/{appName}/env": {
      "get": {
        "summary": "Get environment variables",
        "description": "Get environment variables",
        "operationId": "getAppEnv",
        "tags": [
          "env"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get environment variables from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to get environment variables from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EnvVar"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Set environment variables",
        "description": "Set environment variables",
        "operationId": "setAppEnv",
        "tags": [
          "env"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to update environment variables in",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to update environment variables in",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Environment variables to update",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/EnvVar"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Environment variables updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/apps/{appName}/domain": {
      "post": {
        "summary": "Add domain to app",
        "description": "Add domain to app",
        "operationId": "addDomain",
        "tags": [
          "domain"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to add domain to",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to add domain to",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Domain to add",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Domain added",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "409": {
            "description": "Domain already in use",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Remove domain from app",
        "description": "Remove domain from app",
        "operationId": "removeDomain",
        "tags": [
          "domain"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to remove domain from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to remove domain from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Domain to remove",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Domain removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/apps/{appName}/domain/status": {
      "get": {
        "summary": "Get DNS status of the app domains",
        "description": "Resolve each custom domain of the app and report whether it points to the region ingress IP",
        "operationId": "getDomainStatus",
        "tags": [
          "domain"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project the app belongs to",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to check domains for",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Domain status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/DomainStatus"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/apps/{appName}/events": {
      "get": {
        "summary": "Get app events",
        "description": "Get app events",
        "operationId": "getAppEvents",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get app events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to get events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of events to return, most recent first (default 100, max 1000)",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "App events found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Event"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/apps/{appName}/events/stream": {
      "get": {
        "summary": "Get app events stream",
        "description": "Establishes a stream of events for a given app",
        "operationId": "streamAppEvents",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get app events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to get events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "App events found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Event"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/apps/{appName}/logs": {
      "get": {
        "summary": "Get app logs",
        "description": "Get app logs with cursor-based pagination (infinite scroll).",
        "operationId": "getAppLogs",
        "tags": [
          "logs"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get app logs from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appName",
            "in": "path",
            "description": "Name of app to get logs from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "before",
            "in": "query",
            "description": "The timestamp (nanoseconds) to fetch logs before. If omitted, defaults to Now().",
            "required": false,
            "schema": {
              "type": "string",
              "example": "1769019169435682763"
            }
          },
          {
            "name": "after",
            "in": "query",
            "description": "Fetch logs newer than this timestamp (for polling). Mutually exclusive with 'before'.",
            "required": false,
            "schema": {
              "type": "string",
              "example": "1769019169435682763"
            }
          },
          {
            "name": "logType",
            "in": "query",
            "required": true,
            "description": "The type of the log",
            "schema": {
              "type": "string",
              "enum": [
                "stdout",
                "build"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of logs to return (default 100)",
            "required": true,
            "schema": {
              "type": "integer",
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "App logs found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Log"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "App not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/volumes": {
      "get": {
        "summary": "Get all storage volumes for a project",
        "description": "Get all storage volumes for a project",
        "operationId": "getVolumes",
        "tags": [
          "volume"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get volume from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Volume"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a new storage volume",
        "description": "Create a new storage volume",
        "operationId": "createVolume",
        "tags": [
          "volume"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to create volume in",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Volume volume to create",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Volume"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Volume volume created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/volume/{volumeName}": {
      "get": {
        "summary": "Get a storage volume",
        "description": "Get a storage volume",
        "operationId": "getVolume",
        "tags": [
          "volume"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get volume from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volumeName",
            "in": "path",
            "description": "Name of volume to get",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Volume"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Volume not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Update a storage volume",
        "description": "Update a storage volume",
        "operationId": "updateVolume",
        "tags": [
          "volume"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to update volume in",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volumeName",
            "in": "path",
            "description": "Name of volume to update",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Volume volume to update",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Volume"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Volume volume updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Volume not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a storage volume",
        "description": "Delete a storage volume",
        "operationId": "deleteVolume",
        "tags": [
          "volume"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to delete volume from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "volumeName",
            "in": "path",
            "description": "Name of volume to delete",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Volume volume deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Volume not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/mysqls": {
      "get": {
        "summary": "Get all mysqls in a project",
        "description": "Get all mysqls in a project",
        "operationId": "getMysqls",
        "tags": [
          "mysql"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get mysqls from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MySQL"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a new mysql",
        "description": "Create a new mysql",
        "operationId": "createMysql",
        "tags": [
          "mysql"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to create mysql in",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Mysql to create",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MySQL"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mysql created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/mysqls/{mysqlName}": {
      "get": {
        "summary": "Get a mysql",
        "description": "Get a mysql",
        "operationId": "getMysql",
        "tags": [
          "mysql"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get mysql from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mysqlName",
            "in": "path",
            "description": "Name of mysql to get",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MySQL"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Mysql not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Update a mysql",
        "description": "Update a mysql",
        "operationId": "updateMysql",
        "tags": [
          "mysql"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to update mysql in",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mysqlName",
            "in": "path",
            "description": "Name of mysql to update",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Mysql to update",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MySQL"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mysql updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Mysql not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a mysql",
        "description": "Delete a mysql",
        "operationId": "deleteMysql",
        "tags": [
          "mysql"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to delete mysql from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mysqlName",
            "in": "path",
            "description": "Name of mysql to delete",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Mysql deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Mysql not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/mysqls/{mysqlName}/credentials": {
      "get": {
        "summary": "Get mysql credentials",
        "description": "Get mysql credentials",
        "operationId": "getMysqlCredentials",
        "tags": [
          "mysql"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get mysql credentials from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mysqlName",
            "in": "path",
            "description": "Name of mysql to get credentials from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MySQLCredentials"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Mysql not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/mysqls/{mysqlName}/status": {
      "get": {
        "summary": "Get mysql status",
        "description": "Get mysql status",
        "operationId": "getMysqlStatus",
        "tags": [
          "mysql"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get mysql status from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mysqlName",
            "in": "path",
            "description": "Name of mysql to get status from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MySQLStatus"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Mysql not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/mysqls/{mysqlName}/env": {
      "get": {
        "summary": "Get environment variables for MySQL",
        "description": "Returns environment variables for a specific MySQL instance",
        "operationId": "getMysqlEnv",
        "tags": [
          "mysql",
          "env"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mysqlName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EnvVar"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "MySQL not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/mysqls/{mysqlName}/events": {
      "get": {
        "summary": "Get mysql events",
        "description": "Get mysql events",
        "operationId": "getMySQLEvents",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get mysql events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mysqlName",
            "in": "path",
            "description": "Name of mysql to get events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "MySQL events found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Event"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "MySQL not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/mysqls/{mysqlName}/events/stream": {
      "get": {
        "summary": "Get mysql events stream",
        "description": "Establishes a stream of events for a given mysql",
        "operationId": "streamMySQLEvents",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get mysql events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mysqlName",
            "in": "path",
            "description": "Name of mysql to get events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "MySQL events found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Event"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "MySQL not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/postgres": {
      "get": {
        "summary": "Get all postgres instances in a project",
        "description": "Get all postgres instances in a project",
        "operationId": "getPostgres",
        "tags": [
          "postgres"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Name of project to get postgres instances from"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Postgres"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a new postgres instance",
        "description": "Create a new postgres instance",
        "operationId": "createPostgres",
        "tags": [
          "postgres"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Name of project to create postgres in"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Postgres"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Postgres created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/postgres/{postgresName}": {
      "get": {
        "summary": "Get a postgres instance",
        "operationId": "getPostgresInstance",
        "tags": [
          "postgres"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "postgresName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Postgres"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Postgres not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Update a postgres instance",
        "operationId": "updatePostgres",
        "tags": [
          "postgres"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "postgresName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Postgres"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Postgres updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Postgres not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a postgres instance",
        "operationId": "deletePostgres",
        "tags": [
          "postgres"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "postgresName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Postgres deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Postgres not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/postgres/{postgresName}/credentials": {
      "get": {
        "summary": "Get postgres credentials",
        "operationId": "getPostgresCredentials",
        "tags": [
          "postgres"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "postgresName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostgresCredentials"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Postgres not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/postgres/{postgresName}/status": {
      "get": {
        "summary": "Get postgres status",
        "operationId": "getPostgresStatus",
        "tags": [
          "postgres"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "postgresName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostgresStatus"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Postgres not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/postgres/{postgresName}/env": {
      "get": {
        "summary": "Get environment variables for Postgres",
        "description": "Returns environment variables for a specific Postgres instance",
        "operationId": "getPostgresEnv",
        "tags": [
          "postgres",
          "env"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "postgresName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EnvVar"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Postgres not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/postgres/{postgresName}/events": {
      "get": {
        "summary": "Get postgres events",
        "description": "Get postgres events",
        "operationId": "getPostgresEvents",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get postgres events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "postgresName",
            "in": "path",
            "description": "Name of postgres to get events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Postgres events found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Event"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Postgres not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/postgres/{postgresName}/events/stream": {
      "get": {
        "summary": "Get postgres events stream",
        "description": "Establishes a stream of events for a given postgres",
        "operationId": "streamPostgresEvents",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get postgres events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "postgresName",
            "in": "path",
            "description": "Name of postgres to get events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Postgres events found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Event"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Postgres not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/redises": {
      "get": {
        "summary": "Get redises",
        "description": "Get redises",
        "operationId": "getRedises",
        "tags": [
          "redis"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get redises from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Redis"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a redis",
        "description": "Create a redis",
        "operationId": "createRedis",
        "tags": [
          "redis"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to create redis in",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Redis to create",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Redis"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Redis created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/redises/{redisName}": {
      "get": {
        "summary": "Get redis",
        "description": "Get redis",
        "operationId": "getRedis",
        "tags": [
          "redis"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get redis from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redisName",
            "in": "path",
            "description": "Name of redis to get",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Redis"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Redis not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a redis",
        "description": "Delete a redis",
        "operationId": "deleteRedis",
        "tags": [
          "redis"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to delete redis from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redisName",
            "in": "path",
            "description": "Name of redis to delete",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Redis deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Redis not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Update a redis",
        "description": "Update a redis",
        "operationId": "updateRedis",
        "tags": [
          "redis"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to update redis in",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redisName",
            "in": "path",
            "description": "Name of redis to update",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Redis to update",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Redis"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Redis updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Redis not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/redises/{redisName}/credentials": {
      "get": {
        "summary": "Get redis credentials",
        "description": "Get redis credentials",
        "operationId": "getRedisCredentials",
        "tags": [
          "redis"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get redis credentials from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redisName",
            "in": "path",
            "description": "Name of redis to get credentials from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RedisCredentials"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Redis not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/redises/{redisName}/status": {
      "get": {
        "summary": "Get redis status",
        "description": "Get redis status",
        "operationId": "getRedisStatus",
        "tags": [
          "redis"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get redis status from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redisName",
            "in": "path",
            "description": "Name of redis to get status from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RedisStatus"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Redis not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/redises/{redisName}/env": {
      "get": {
        "summary": "Get environment variables for Redis",
        "description": "Returns environment variables for a specific Redis instance",
        "operationId": "getRedisEnv",
        "tags": [
          "redis",
          "env"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redisName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/EnvVar"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Redis not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/redis/{redisName}/events": {
      "get": {
        "summary": "Get redis events",
        "description": "Get redis events",
        "operationId": "getRedisEvents",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get redis events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redisName",
            "in": "path",
            "description": "Name of redis to get events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Redis events found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Event"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Redis not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/redis/{redisName}/events/stream": {
      "get": {
        "summary": "Get redis events stream",
        "description": "Establishes a stream of events for a given redis",
        "operationId": "streamRedisEvents",
        "tags": [
          "events"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of project to get redis events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redisName",
            "in": "path",
            "description": "Name of redis to get events from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Redis events found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Event"
                  }
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Redis not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/backups": {
      "get": {
        "summary": "Get the backup overview of a project",
        "description": "Returns whether backups are enabled and ready, the schedule and its next run, the retention policy, every database and volume with its last backup, and the backup runs, newest first.",
        "operationId": "getBackupOverview",
        "tags": [
          "backups"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of the project to get backups from",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BackupOverview"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Start a manual backup",
        "description": "Creates a manual backup run of the whole project, or of one database or volume when kind and name are given.",
        "operationId": "createBackup",
        "tags": [
          "backups"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of the project to back up",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "The database or volume to back up. Omit to back up the whole project.",
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BackupItemRef"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Manual backup started",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BackupRun"
                }
              }
            }
          },
          "400": {
            "description": "Invalid kind or name",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project or resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "409": {
            "description": "Backups are not enabled, the repository is not ready, or a manual backup is already running",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/backups/list": {
      "get": {
        "summary": "List the backups of one database or volume",
        "description": "Returns the successful backups of one resource, newest first. Backups that restic has pruned are left out.",
        "operationId": "listBackups",
        "tags": [
          "backups"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of the project",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "description": "Resource kind",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "postgres",
                "mysql",
                "volume"
              ]
            }
          },
          {
            "name": "name",
            "in": "query",
            "description": "Resource name",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BackupList"
                }
              }
            }
          },
          "400": {
            "description": "Missing or unknown kind or name",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectName}/backups/{backupId}/download": {
      "post": {
        "summary": "Prepare a backup download",
        "description": "Creates a BackupDownload custom resource for the given restic snapshot. The operator materializes the file and fills in the pre-signed URL. Returns the existing download when one is already prepared, and 409 when two downloads are already being prepared.",
        "operationId": "createBackupDownload",
        "tags": [
          "backups"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of the project",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "backupId",
            "in": "path",
            "description": "The restic short snapshot ID of the backup",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The download already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BackupDownload"
                }
              }
            }
          },
          "201": {
            "description": "The download is being prepared",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BackupDownload"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project or backup not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "409": {
            "description": "Two downloads are already being prepared",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "Get a prepared backup download",
        "description": "Returns the state of a prepared download, including the pre-signed URL once the operator has finished.",
        "operationId": "getBackupDownload",
        "tags": [
          "backups"
        ],
        "parameters": [
          {
            "name": "projectName",
            "in": "path",
            "description": "Name of the project",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "backupId",
            "in": "path",
            "description": "The restic short snapshot ID of the backup",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BackupDownload"
                }
              }
            }
          },
          "401": {
            "description": "User is not authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "404": {
            "description": "Project or download not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenericMessage"
                }
              }
            }
          }
        }
      }
    }
  }
}
