{
  "components": {
    "headers": {
      "IdempotencyReplayed": {
        "description": "true for a retained response, false for a newly committed keyed operation. Absent when no receipt is used.",
        "schema": {
          "enum": [
            "true",
            "false"
          ],
          "type": "string"
        }
      },
      "RequestId": {
        "description": "Correlation identifier for this request.",
        "schema": {
          "type": "string"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying a rate-limited request.",
        "schema": {
          "minimum": 1,
          "type": "integer"
        }
      }
    },
    "parameters": {
      "csrf": {
        "description": "Required on browser-session writes: obtain csrfToken from /api/bootstrap and retain its cookies. Not required for a validated bearer key.",
        "in": "header",
        "name": "X-CSRFToken",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      "cursor": {
        "description": "Opaque nextCursor returned by the previous page. Reuse with the same endpoint and query; do not parse or construct it.",
        "in": "query",
        "name": "cursor",
        "required": false,
        "schema": {
          "type": "string"
        }
      },
      "deploymentId": {
        "description": "Deployment UUID in this service.",
        "in": "path",
        "name": "deploymentId",
        "required": true,
        "schema": {
          "format": "uuid",
          "type": "string"
        }
      },
      "idempotency": {
        "description": "Optional retry key of visible ASCII characters without spaces. Successful responses are retained for 24 hours, scoped to workspace, actor, credential, method and path. Changed payload with the same key returns 409 idempotency_conflict. If body requestId is supplied it must match.",
        "in": "header",
        "name": "Idempotency-Key",
        "required": false,
        "schema": {
          "maxLength": 160,
          "minLength": 1,
          "pattern": "^[!-~]+$",
          "type": "string"
        }
      },
      "limit": {
        "description": "Page size. Supplying limit or cursor enables pagination for legacy unbounded lists.",
        "in": "query",
        "name": "limit",
        "required": false,
        "schema": {
          "default": 100,
          "maximum": 200,
          "minimum": 1,
          "type": "integer"
        }
      },
      "operationId": {
        "description": "Operation UUID in this service.",
        "in": "path",
        "name": "operationId",
        "required": true,
        "schema": {
          "format": "uuid",
          "type": "string"
        }
      },
      "projectId": {
        "description": "Project UUID in this workspace.",
        "in": "path",
        "name": "projectId",
        "required": true,
        "schema": {
          "format": "uuid",
          "type": "string"
        }
      },
      "requestId": {
        "description": "Optional correlation identifier; invalid values are replaced. The accepted/generated value is returned in X-Request-ID and error body requestId. This is not an idempotency key.",
        "in": "header",
        "name": "X-Request-ID",
        "required": false,
        "schema": {
          "maxLength": 64,
          "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$",
          "type": "string"
        }
      },
      "serviceId": {
        "description": "Service UUID in this workspace.",
        "in": "path",
        "name": "serviceId",
        "required": true,
        "schema": {
          "format": "uuid",
          "type": "string"
        }
      },
      "variableId": {
        "description": "Variable UUID in this service.",
        "in": "path",
        "name": "variableId",
        "required": true,
        "schema": {
          "format": "uuid",
          "type": "string"
        }
      },
      "workspaceId": {
        "description": "Workspace UUID; it must match the bearer key scope.",
        "in": "path",
        "name": "workspaceId",
        "required": true,
        "schema": {
          "format": "uuid",
          "type": "string"
        }
      }
    },
    "responses": {
      "400": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        },
        "description": "Invalid JSON, values, cursor, confirmation or operation.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          }
        }
      },
      "401": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        },
        "description": "Authentication is missing, invalid or expired.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          }
        }
      },
      "403": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        },
        "description": "Role, key scope, email verification, MFA or browser CSRF checks failed.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          }
        }
      },
      "404": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        },
        "description": "Resource does not exist or is outside the caller workspace membership.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          }
        }
      },
      "405": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        },
        "description": "HTTP method is not supported.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          }
        }
      },
      "409": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        },
        "description": "Resource conflict, idempotency_conflict, idempotency_legacy_conflict, or engine_unavailable. For a legacy deployment key without a receipt, inspect the existing deployment; do not automatically start another attempt.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          }
        }
      },
      "413": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        },
        "description": "Request body exceeds 262144 bytes.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          }
        }
      },
      "429": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        },
        "description": "Request rate limit reached; respect Retry-After.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          },
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          }
        }
      },
      "500": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        },
        "description": "Unexpected server failure; use requestId when contacting support.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          }
        }
      }
    },
    "schemas": {
      "ActionResponse": {
        "description": "restart/suspend/resume return queued and operation. deploy/clear-cache return deployment.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/QueuedOperation"
          },
          {
            "$ref": "#/components/schemas/DeploymentResponse"
          }
        ]
      },
      "CancelResponse": {
        "properties": {
          "cancelRequested": {
            "const": true,
            "type": "boolean"
          }
        },
        "required": [
          "cancelRequested"
        ],
        "type": "object"
      },
      "CanvasEdge": {
        "description": "Configured metadata only, not evidence of live traffic. Reference edges point from consumer to provider and expose variable names only. Environment-group edges point from the group node to a linked service.",
        "properties": {
          "id": {
            "type": "string"
          },
          "keys": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "kind": {
            "enum": [
              "reference",
              "environment-group"
            ],
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "target": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "source",
          "target",
          "kind"
        ],
        "type": "object"
      },
      "CanvasGroup": {
        "properties": {
          "environmentId": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "id": {
            "pattern": "^group:",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "serviceIds": {
            "items": {
              "format": "uuid",
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "id",
          "name",
          "environmentId",
          "serviceIds"
        ],
        "type": "object"
      },
      "CanvasLayout": {
        "additionalProperties": false,
        "properties": {
          "positions": {
            "additionalProperties": {
              "additionalProperties": false,
              "properties": {
                "x": {
                  "maximum": 10000000,
                  "minimum": -10000000,
                  "type": "number"
                },
                "y": {
                  "maximum": 10000000,
                  "minimum": -10000000,
                  "type": "number"
                }
              },
              "required": [
                "x",
                "y"
              ],
              "type": "object"
            },
            "maxProperties": 2000,
            "propertyNames": {
              "pattern": "^(group:)?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
            },
            "type": "object"
          },
          "revision": {
            "maximum": 9007199254740991,
            "minimum": 0,
            "type": "integer"
          },
          "viewport": {
            "anyOf": [
              {
                "additionalProperties": false,
                "properties": {
                  "x": {
                    "maximum": 10000000,
                    "minimum": -10000000,
                    "type": "number"
                  },
                  "y": {
                    "maximum": 10000000,
                    "minimum": -10000000,
                    "type": "number"
                  },
                  "zoom": {
                    "maximum": 4,
                    "minimum": 0.1,
                    "type": "number"
                  }
                },
                "required": [
                  "x",
                  "y",
                  "zoom"
                ],
                "type": "object"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "revision",
          "positions",
          "viewport"
        ],
        "type": "object"
      },
      "CanvasLayoutUpdate": {
        "additionalProperties": false,
        "description": "Replace the visual layout for this scope using its current revision. Empty positions and null viewport reset the layout. Node IDs must be present in the current canvas. No connection, service or infrastructure configuration is changed.",
        "properties": {
          "positions": {
            "additionalProperties": {
              "additionalProperties": false,
              "properties": {
                "x": {
                  "maximum": 10000000,
                  "minimum": -10000000,
                  "type": "number"
                },
                "y": {
                  "maximum": 10000000,
                  "minimum": -10000000,
                  "type": "number"
                }
              },
              "required": [
                "x",
                "y"
              ],
              "type": "object"
            },
            "maxProperties": 2000,
            "propertyNames": {
              "pattern": "^(group:)?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
            },
            "type": "object"
          },
          "revision": {
            "maximum": 9007199254740990,
            "minimum": 0,
            "type": "integer"
          },
          "viewport": {
            "anyOf": [
              {
                "additionalProperties": false,
                "properties": {
                  "x": {
                    "maximum": 10000000,
                    "minimum": -10000000,
                    "type": "number"
                  },
                  "y": {
                    "maximum": 10000000,
                    "minimum": -10000000,
                    "type": "number"
                  },
                  "zoom": {
                    "maximum": 4,
                    "minimum": 0.1,
                    "type": "number"
                  }
                },
                "required": [
                  "x",
                  "y",
                  "zoom"
                ],
                "type": "object"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "revision",
          "positions",
          "viewport"
        ],
        "type": "object"
      },
      "CanvasResponse": {
        "properties": {
          "edges": {
            "items": {
              "$ref": "#/components/schemas/CanvasEdge"
            },
            "maxItems": 10000,
            "type": "array"
          },
          "groups": {
            "items": {
              "$ref": "#/components/schemas/CanvasGroup"
            },
            "maxItems": 2000,
            "type": "array"
          },
          "layout": {
            "$ref": "#/components/schemas/CanvasLayout"
          },
          "nodes": {
            "items": {
              "$ref": "#/components/schemas/Service"
            },
            "maxItems": 2000,
            "type": "array"
          },
          "scope": {
            "properties": {
              "environmentId": {
                "anyOf": [
                  {
                    "format": "uuid",
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "projectId": {
                "anyOf": [
                  {
                    "format": "uuid",
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "projectId",
              "environmentId"
            ],
            "type": "object"
          }
        },
        "required": [
          "nodes",
          "groups",
          "edges",
          "layout",
          "scope"
        ],
        "type": "object"
      },
      "Catalog": {
        "properties": {
          "capabilities": {
            "additionalProperties": {
              "type": "boolean"
            },
            "type": "object"
          },
          "databasePlans": {
            "items": {
              "properties": {
                "backupRetentionDays": {
                  "type": "integer"
                },
                "buildMinutes": {
                  "type": "number"
                },
                "cpu": {
                  "type": "number"
                },
                "id": {
                  "type": "string"
                },
                "kinds": {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "logDays": {
                  "type": "number"
                },
                "maxConnections": {
                  "type": "integer"
                },
                "memoryMb": {
                  "type": "number"
                },
                "name": {
                  "type": "string"
                },
                "ngn": {
                  "type": "number"
                },
                "storageGb": {
                  "type": "number"
                },
                "transferGb": {
                  "type": "number"
                },
                "usd": {
                  "type": "number"
                },
                "workspaceLimit": {
                  "type": "integer"
                }
              },
              "required": [
                "id",
                "name",
                "usd",
                "ngn"
              ],
              "type": "object"
            },
            "type": "array"
          },
          "defaults": {
            "$ref": "#/components/schemas/ServiceConfiguration"
          },
          "plans": {
            "items": {
              "properties": {
                "backupRetentionDays": {
                  "type": "integer"
                },
                "buildMinutes": {
                  "type": "number"
                },
                "cpu": {
                  "type": "number"
                },
                "id": {
                  "type": "string"
                },
                "kinds": {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "logDays": {
                  "type": "number"
                },
                "maxConnections": {
                  "type": "integer"
                },
                "memoryMb": {
                  "type": "number"
                },
                "name": {
                  "type": "string"
                },
                "ngn": {
                  "type": "number"
                },
                "storageGb": {
                  "type": "number"
                },
                "transferGb": {
                  "type": "number"
                },
                "usd": {
                  "type": "number"
                },
                "workspaceLimit": {
                  "type": "integer"
                }
              },
              "required": [
                "id",
                "name",
                "usd",
                "ngn"
              ],
              "type": "object"
            },
            "type": "array"
          },
          "pricesAreEstimates": {
            "type": "boolean"
          },
          "regions": {
            "items": {
              "properties": {
                "description": {
                  "type": "string"
                },
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "name",
                "description"
              ],
              "type": "object"
            },
            "type": "array"
          },
          "runtimes": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "serviceTypes": {
            "items": {
              "properties": {
                "description": {
                  "type": "string"
                },
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "plural": {
                  "type": "string"
                },
                "runtime": {
                  "type": "boolean"
                }
              },
              "required": [
                "id",
                "name",
                "plural",
                "description",
                "runtime"
              ],
              "type": "object"
            },
            "type": "array"
          }
        },
        "required": [
          "serviceTypes",
          "plans",
          "databasePlans",
          "regions",
          "runtimes",
          "defaults",
          "capabilities",
          "pricesAreEstimates"
        ],
        "type": "object"
      },
      "ConfirmRequest": {
        "properties": {
          "confirm": {
            "minLength": 1,
            "type": "string"
          },
          "requestId": {
            "description": "Legacy alias of Idempotency-Key. If both are supplied they must agree. This is distinct from the requestId on an error response.",
            "maxLength": 160,
            "minLength": 1,
            "pattern": "^[!-~]+$",
            "type": "string"
          }
        },
        "required": [
          "confirm"
        ],
        "type": "object"
      },
      "Deleted": {
        "properties": {
          "deleted": {
            "type": "boolean"
          },
          "operation": {
            "$ref": "#/components/schemas/Operation"
          },
          "queued": {
            "type": "boolean"
          }
        },
        "required": [
          "deleted"
        ],
        "type": "object"
      },
      "Deployment": {
        "properties": {
          "actor": {
            "type": "string"
          },
          "blockedReason": {
            "type": "string"
          },
          "branch": {
            "type": "string"
          },
          "canRollback": {
            "type": "boolean"
          },
          "cancelRequested": {
            "type": "boolean"
          },
          "commitMessage": {
            "type": "string"
          },
          "commitSha": {
            "type": "string"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "error": {
            "type": "string"
          },
          "finishedAt": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "sourceDeploymentId": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "startedAt": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "$ref": "#/components/schemas/DeploymentStatus"
          },
          "steps": {
            "items": {
              "properties": {
                "finishedAt": {
                  "format": "date-time",
                  "type": "string"
                },
                "name": {
                  "$ref": "#/components/schemas/DeploymentStatus"
                },
                "startedAt": {
                  "format": "date-time",
                  "type": "string"
                }
              },
              "required": [
                "name",
                "startedAt"
              ],
              "type": "object"
            },
            "type": "array"
          },
          "trigger": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "trigger",
          "blockedReason",
          "commitSha",
          "commitMessage",
          "branch",
          "createdAt",
          "startedAt",
          "finishedAt",
          "actor",
          "cancelRequested",
          "error",
          "steps",
          "canRollback",
          "sourceDeploymentId"
        ],
        "type": "object"
      },
      "DeploymentCreate": {
        "properties": {
          "commitSha": {
            "description": "Optional full commit SHA. Omit to resolve the configured branch.",
            "pattern": "^([0-9a-f]{40,64})?$",
            "type": "string"
          },
          "requestId": {
            "description": "Legacy alias of Idempotency-Key. If both are supplied they must agree. This is distinct from the requestId on an error response.",
            "maxLength": 160,
            "minLength": 1,
            "pattern": "^[!-~]+$",
            "type": "string"
          }
        },
        "type": "object"
      },
      "DeploymentList": {
        "properties": {
          "available": {
            "type": "boolean"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/Deployment"
            },
            "type": "array"
          },
          "page": {
            "$ref": "#/components/schemas/Page"
          },
          "reason": {
            "type": "string"
          }
        },
        "required": [
          "available",
          "items",
          "page"
        ],
        "type": "object"
      },
      "DeploymentResponse": {
        "examples": [
          {
            "deployment": {
              "actor": "developer@example.com",
              "blockedReason": "",
              "branch": "main",
              "canRollback": false,
              "cancelRequested": false,
              "commitMessage": "",
              "commitSha": "",
              "createdAt": "2026-09-25T12:00:00Z",
              "error": "",
              "finishedAt": null,
              "id": "00000000-0000-4000-8000-000000000001",
              "sourceDeploymentId": null,
              "startedAt": null,
              "status": "queued",
              "steps": [],
              "trigger": "manual"
            }
          }
        ],
        "properties": {
          "deployment": {
            "$ref": "#/components/schemas/Deployment"
          }
        },
        "required": [
          "deployment"
        ],
        "type": "object"
      },
      "DeploymentStatus": {
        "description": "Current release states. live, failed, cancelled and superseded are terminal; queued is not deployment success. Clients should tolerate future response states.",
        "enum": [
          "queued",
          "preparing",
          "cloning",
          "building",
          "predeploy",
          "deploying",
          "checking",
          "live",
          "failed",
          "cancelled",
          "superseded"
        ],
        "type": "string"
      },
      "Environment": {
        "properties": {
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "isolated": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "projectId": {
            "format": "uuid",
            "type": "string"
          },
          "protected": {
            "type": "boolean"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "id",
          "createdAt",
          "updatedAt",
          "projectId",
          "name",
          "protected",
          "isolated"
        ],
        "type": "object"
      },
      "Error": {
        "properties": {
          "code": {
            "minLength": 1,
            "type": "string"
          },
          "field": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "message",
          "code"
        ],
        "type": "object"
      },
      "ErrorResponse": {
        "examples": [
          {
            "errors": [
              {
                "code": "idempotency_conflict",
                "message": "This idempotency key was already used with different request values."
              }
            ],
            "requestId": "client-trace-01"
          }
        ],
        "properties": {
          "errors": {
            "items": {
              "$ref": "#/components/schemas/Error"
            },
            "minItems": 1,
            "type": "array"
          },
          "requestId": {
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "errors",
          "requestId"
        ],
        "type": "object"
      },
      "Estimate": {
        "properties": {
          "ngn": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          },
          "priced": {
            "type": "boolean"
          },
          "usd": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "usd",
          "ngn",
          "priced"
        ],
        "type": "object"
      },
      "LogLine": {
        "properties": {
          "id": {
            "minimum": 1,
            "type": "integer"
          },
          "level": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "source": {
            "enum": [
              "build",
              "runtime",
              "system"
            ],
            "type": "string"
          },
          "timestamp": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "id",
          "timestamp",
          "source",
          "message",
          "level"
        ],
        "type": "object"
      },
      "LogList": {
        "description": "Available streams include cursor, hasMore and limit. An unprovisioned service with hosting disabled returns available:false, empty items and reason. cursor is the numeric tail position for the next after query, not an opaque collection cursor.",
        "examples": [
          {
            "available": true,
            "cursor": 42,
            "hasMore": false,
            "items": [
              {
                "id": 42,
                "level": "info",
                "message": "Application ready",
                "source": "runtime",
                "timestamp": "2026-09-25T12:00:00Z"
              }
            ],
            "limit": 500
          }
        ],
        "properties": {
          "available": {
            "type": "boolean"
          },
          "cursor": {
            "minimum": 0,
            "type": "integer"
          },
          "hasMore": {
            "type": "boolean"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/LogLine"
            },
            "type": "array"
          },
          "limit": {
            "maximum": 500,
            "minimum": 1,
            "type": "integer"
          },
          "reason": {
            "type": "string"
          }
        },
        "required": [
          "available",
          "items"
        ],
        "type": "object"
      },
      "Operation": {
        "description": "Safe job metadata only. Internal payload, results and error details are not included. Tolerate future operation status values.",
        "properties": {
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "status": {
            "enum": [
              "queued",
              "running",
              "complete",
              "failed"
            ],
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "id",
          "createdAt",
          "updatedAt",
          "kind",
          "status"
        ],
        "type": "object"
      },
      "OperationResponse": {
        "properties": {
          "operation": {
            "$ref": "#/components/schemas/Operation"
          }
        },
        "required": [
          "operation"
        ],
        "type": "object"
      },
      "OptionalRequest": {
        "properties": {
          "requestId": {
            "description": "Legacy alias of Idempotency-Key. If both are supplied they must agree. This is distinct from the requestId on an error response.",
            "maxLength": 160,
            "minLength": 1,
            "pattern": "^[!-~]+$",
            "type": "string"
          }
        },
        "type": "object"
      },
      "Page": {
        "properties": {
          "hasMore": {
            "type": "boolean"
          },
          "limit": {
            "maximum": 200,
            "minimum": 1,
            "type": "integer"
          },
          "nextCursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "limit",
          "nextCursor",
          "hasMore"
        ],
        "type": "object"
      },
      "Project": {
        "properties": {
          "color": {
            "enum": [
              "violet",
              "blue",
              "green",
              "orange",
              "pink",
              "gray"
            ],
            "type": "string"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "description": {
            "maxLength": 500,
            "type": "string"
          },
          "environments": {
            "items": {
              "$ref": "#/components/schemas/Environment"
            },
            "type": "array"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "maxLength": 80,
            "minLength": 1,
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "id",
          "createdAt",
          "updatedAt",
          "name",
          "description",
          "color",
          "environments"
        ],
        "type": "object"
      },
      "ProjectCreate": {
        "properties": {
          "color": {
            "enum": [
              "violet",
              "blue",
              "green",
              "orange",
              "pink",
              "gray"
            ],
            "type": "string"
          },
          "description": {
            "maxLength": 500,
            "type": "string"
          },
          "name": {
            "maxLength": 80,
            "minLength": 1,
            "type": "string"
          },
          "requestId": {
            "description": "Legacy alias of Idempotency-Key. If both are supplied they must agree. This is distinct from the requestId on an error response.",
            "maxLength": 160,
            "minLength": 1,
            "pattern": "^[!-~]+$",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "type": "object"
      },
      "ProjectList": {
        "examples": [
          {
            "page": {
              "hasMore": false,
              "limit": 100,
              "nextCursor": null
            },
            "projects": [
              {
                "color": "violet",
                "createdAt": "2026-09-25T12:00:00Z",
                "description": "",
                "environments": [],
                "id": "00000000-0000-4000-8000-000000000001",
                "name": "API platform",
                "updatedAt": "2026-09-25T12:00:00Z"
              }
            ]
          }
        ],
        "properties": {
          "page": {
            "$ref": "#/components/schemas/Page"
          },
          "projects": {
            "items": {
              "$ref": "#/components/schemas/Project"
            },
            "type": "array"
          }
        },
        "required": [
          "projects"
        ],
        "type": "object"
      },
      "ProjectResponse": {
        "examples": [
          {
            "project": {
              "color": "violet",
              "createdAt": "2026-09-25T12:00:00Z",
              "description": "",
              "environments": [],
              "id": "00000000-0000-4000-8000-000000000001",
              "name": "API platform",
              "updatedAt": "2026-09-25T12:00:00Z"
            }
          }
        ],
        "properties": {
          "project": {
            "$ref": "#/components/schemas/Project"
          }
        },
        "required": [
          "project"
        ],
        "type": "object"
      },
      "ProjectUpdate": {
        "properties": {
          "color": {
            "enum": [
              "violet",
              "blue",
              "green",
              "orange",
              "pink",
              "gray"
            ],
            "type": "string"
          },
          "description": {
            "maxLength": 500,
            "type": "string"
          },
          "name": {
            "maxLength": 80,
            "minLength": 1,
            "type": "string"
          },
          "requestId": {
            "description": "Legacy alias of Idempotency-Key. If both are supplied they must agree. This is distinct from the requestId on an error response.",
            "maxLength": 160,
            "minLength": 1,
            "pattern": "^[!-~]+$",
            "type": "string"
          }
        },
        "type": "object"
      },
      "QueuedOperation": {
        "examples": [
          {
            "operation": {
              "createdAt": "2026-09-25T12:00:00Z",
              "id": "00000000-0000-4000-8000-000000000001",
              "kind": "restart",
              "status": "queued",
              "updatedAt": "2026-09-25T12:00:00Z"
            },
            "queued": true
          }
        ],
        "properties": {
          "operation": {
            "$ref": "#/components/schemas/Operation"
          },
          "queued": {
            "const": true,
            "type": "boolean"
          }
        },
        "required": [
          "queued",
          "operation"
        ],
        "type": "object"
      },
      "RevealedVariable": {
        "properties": {
          "value": {
            "description": "Secret value; do not persist in client diagnostics.",
            "type": "string"
          }
        },
        "required": [
          "value"
        ],
        "type": "object"
      },
      "Service": {
        "properties": {
          "archived": {
            "type": "boolean"
          },
          "configuration": {
            "$ref": "#/components/schemas/ServiceConfiguration"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "deletedAt": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "deletionRequestedAt": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "deployedBranch": {
            "type": "string"
          },
          "deployedCommitSha": {
            "description": "Commit of the currently activated release, independent of later failed builds.",
            "type": "string"
          },
          "deployedRepository": {
            "type": "string"
          },
          "deploymentId": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "deploymentUpdatedAt": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "displayStatus": {
            "type": "string"
          },
          "environmentGroupIds": {
            "items": {
              "format": "uuid",
              "type": "string"
            },
            "type": "array"
          },
          "environmentId": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "estimatedMonthly": {
            "$ref": "#/components/schemas/Estimate"
          },
          "healthCheckedAt": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "healthStatus": {
            "description": "Last readiness observation, or unknown after five minutes without a fresh observation.",
            "enum": [
              "ready",
              "unavailable",
              "degraded",
              "unknown"
            ],
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "internalHost": {
            "type": "string"
          },
          "internalPort": {
            "anyOf": [
              {
                "maximum": 65535,
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "kind": {
            "enum": [
              "static",
              "web",
              "private",
              "worker",
              "cron",
              "postgres",
              "mysql",
              "redis",
              "workflow"
            ],
            "type": "string"
          },
          "lifecycleStatus": {
            "type": "string"
          },
          "liveDeploymentId": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "name": {
            "maxLength": 63,
            "minLength": 1,
            "pattern": "^[a-z0-9][a-z0-9-]*$",
            "type": "string"
          },
          "projectId": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "runtimeDetail": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "createdAt",
          "updatedAt",
          "name",
          "kind",
          "projectId",
          "environmentId",
          "configuration",
          "status",
          "archived",
          "displayStatus",
          "lifecycleStatus",
          "deletionRequestedAt",
          "deletedAt",
          "healthStatus",
          "healthCheckedAt",
          "deploymentId",
          "deploymentUpdatedAt",
          "estimatedMonthly",
          "url",
          "internalHost",
          "liveDeploymentId",
          "deployedCommitSha",
          "deployedBranch",
          "deployedRepository",
          "internalPort",
          "runtimeDetail",
          "environmentGroupIds"
        ],
        "type": "object"
      },
      "ServiceAction": {
        "properties": {
          "action": {
            "enum": [
              "restart",
              "suspend",
              "resume",
              "deploy",
              "clear-cache"
            ],
            "type": "string"
          },
          "requestId": {
            "description": "Legacy alias of Idempotency-Key. If both are supplied they must agree. This is distinct from the requestId on an error response.",
            "maxLength": 160,
            "minLength": 1,
            "pattern": "^[!-~]+$",
            "type": "string"
          }
        },
        "required": [
          "action"
        ],
        "type": "object"
      },
      "ServiceConfiguration": {
        "additionalProperties": true,
        "description": "Resolved service configuration. Clients must tolerate additive response fields. Creation and update validate ServiceConfigurationInput.",
        "properties": {
          "autoDeploy": {
            "default": "off",
            "enum": [
              "off",
              "commit",
              "checks"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "backupEnabled": {
            "default": true,
            "type": "boolean"
          },
          "backupRetentionDays": {
            "default": 7,
            "description": "MySQL Free supports 1\u20137 days; other database plans support 1\u201330 days.",
            "maximum": 30,
            "minimum": 1,
            "type": "integer"
          },
          "branch": {
            "default": "main",
            "maxLength": 2000,
            "type": "string"
          },
          "buildCommand": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "buildMethod": {
            "default": "railpack",
            "enum": [
              "railpack",
              "dockerfile",
              "image"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "cacheProfile": {
            "default": "none",
            "enum": [
              "none",
              "safe",
              "static"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "databaseName": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "databaseUser": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "databaseVersion": {
            "default": "17",
            "description": "PostgreSQL supports 16, 17 and 18. MySQL supports 8.4 LTS and defaults to 8.4. Existing managed databases cannot change major versions in place.",
            "enum": [
              "16",
              "17",
              "18",
              "8.4"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "description": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "dockerContext": {
            "default": ".",
            "description": "Relative repository path without backslashes or parent traversal.",
            "maxLength": 255,
            "type": "string"
          },
          "dockerfilePath": {
            "default": "Dockerfile",
            "description": "Relative repository path without backslashes or parent traversal.",
            "maxLength": 255,
            "type": "string"
          },
          "evictionPolicy": {
            "default": "allkeys-lru",
            "enum": [
              "allkeys-lru",
              "allkeys-lfu",
              "volatile-lru",
              "noeviction"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "healthCheckPath": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "ignorePaths": {
            "default": [],
            "items": {
              "maxLength": 255,
              "type": "string"
            },
            "maxItems": 50,
            "type": "array"
          },
          "image": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "includePaths": {
            "default": [],
            "items": {
              "maxLength": 255,
              "type": "string"
            },
            "maxItems": 50,
            "type": "array"
          },
          "ipAllowList": {
            "default": [],
            "items": {
              "maxLength": 255,
              "type": "string"
            },
            "maxItems": 50,
            "type": "array"
          },
          "maintenance": {
            "default": false,
            "type": "boolean"
          },
          "maintenancePage": {
            "default": "",
            "description": "Empty or an HTTPS URL without embedded credentials.",
            "maxLength": 1000,
            "type": "string"
          },
          "maxConcurrency": {
            "default": 1,
            "maximum": 100,
            "minimum": 1,
            "type": "integer"
          },
          "maxReplicas": {
            "default": 3,
            "maximum": 20,
            "minimum": 1,
            "type": "integer"
          },
          "maxRetries": {
            "default": 3,
            "maximum": 10,
            "minimum": 0,
            "type": "integer"
          },
          "minReplicas": {
            "default": 1,
            "maximum": 20,
            "minimum": 1,
            "type": "integer"
          },
          "notifications": {
            "default": "workspace",
            "enum": [
              "workspace",
              "all",
              "failure",
              "none"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "plan": {
            "default": "builder",
            "description": "MySQL defaults to mysql-free: one database per workspace, 768 MiB RAM, 0.25 shared CPU, 2 GiB persistent storage, 25 connections and up to 7 days of backups, with no card or expiry. PostgreSQL uses postgres-* plans; MySQL uses mysql-* plans; other kinds use compute plans. The free compute plan supports web/static only. Paid services require a confirmed service-month purchase through hosted checkout.",
            "enum": [
              "free",
              "starter",
              "builder",
              "growth",
              "scale",
              "postgres-starter",
              "postgres-standard",
              "mysql-free",
              "mysql-starter",
              "mysql-standard"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "platformDomainEnabled": {
            "default": true,
            "type": "boolean"
          },
          "port": {
            "default": 8000,
            "maximum": 65535,
            "minimum": 1,
            "type": "integer"
          },
          "preDeployCommand": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "previewExpiryHours": {
            "default": 72,
            "maximum": 720,
            "minimum": 1,
            "type": "integer"
          },
          "previewMode": {
            "default": "off",
            "enum": [
              "off",
              "manual",
              "automatic"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "privateNetworking": {
            "default": true,
            "type": "boolean"
          },
          "publishDirectory": {
            "default": "dist",
            "description": "Relative repository path without backslashes or parent traversal.",
            "maxLength": 255,
            "type": "string"
          },
          "region": {
            "default": "auto",
            "enum": [
              "auto",
              "eu"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "registryId": {
            "default": "",
            "description": "Empty or the UUID of a registry integration in this workspace.",
            "maxLength": 2000,
            "type": "string"
          },
          "replicas": {
            "default": 1,
            "maximum": 20,
            "minimum": 1,
            "type": "integer"
          },
          "repository": {
            "default": "",
            "description": "Empty or an HTTPS URL without embedded credentials.",
            "maxLength": 1000,
            "type": "string"
          },
          "rootDirectory": {
            "default": "",
            "description": "Relative repository path without backslashes or parent traversal.",
            "maxLength": 255,
            "type": "string"
          },
          "runtime": {
            "default": "auto",
            "description": "auto detects the application. Railpack is the default build method.",
            "enum": [
              "auto",
              "docker",
              "node",
              "python",
              "go",
              "php",
              "java",
              "ruby",
              "rust",
              "elixir",
              "deno",
              "dotnet",
              "gleam",
              "cpp",
              "static",
              "shell"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "scaling": {
            "default": "manual",
            "enum": [
              "manual",
              "automatic"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "schedule": {
            "default": "0 * * * *",
            "description": "Cron expression validated for cron services; timezone uses an IANA identifier.",
            "maxLength": 2000,
            "type": "string"
          },
          "sourceType": {
            "default": "repository",
            "enum": [
              "repository",
              "image",
              "none"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "startCommand": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "targetCpu": {
            "default": 70,
            "maximum": 100,
            "minimum": 1,
            "type": "integer"
          },
          "targetMemory": {
            "default": 80,
            "maximum": 100,
            "minimum": 1,
            "type": "integer"
          },
          "timeoutSeconds": {
            "default": 3600,
            "description": "Cron services have a lower maximum of 43200 seconds.",
            "maximum": 86400,
            "minimum": 1,
            "type": "integer"
          },
          "timezone": {
            "default": "UTC",
            "maxLength": 2000,
            "type": "string"
          }
        },
        "type": "object"
      },
      "ServiceConfigurationInput": {
        "additionalProperties": false,
        "description": "Partial configuration on create/update; omitted fields retain defaults/current values. Constraints also depend on service kind, plan and workspace entitlements. Unknown configuration keys are rejected. Credentials belong in encrypted variables/secret files.",
        "properties": {
          "autoDeploy": {
            "default": "off",
            "enum": [
              "off",
              "commit",
              "checks"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "backupEnabled": {
            "default": true,
            "type": "boolean"
          },
          "backupRetentionDays": {
            "default": 7,
            "description": "MySQL Free supports 1\u20137 days; other database plans support 1\u201330 days.",
            "maximum": 30,
            "minimum": 1,
            "type": "integer"
          },
          "branch": {
            "default": "main",
            "maxLength": 2000,
            "type": "string"
          },
          "buildCommand": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "buildMethod": {
            "default": "railpack",
            "enum": [
              "railpack",
              "dockerfile",
              "image"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "cacheProfile": {
            "default": "none",
            "enum": [
              "none",
              "safe",
              "static"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "databaseName": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "databaseUser": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "databaseVersion": {
            "default": "17",
            "description": "PostgreSQL supports 16, 17 and 18. MySQL supports 8.4 LTS and defaults to 8.4. Existing managed databases cannot change major versions in place.",
            "enum": [
              "16",
              "17",
              "18",
              "8.4"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "description": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "dockerContext": {
            "default": ".",
            "description": "Relative repository path without backslashes or parent traversal.",
            "maxLength": 255,
            "type": "string"
          },
          "dockerfilePath": {
            "default": "Dockerfile",
            "description": "Relative repository path without backslashes or parent traversal.",
            "maxLength": 255,
            "type": "string"
          },
          "evictionPolicy": {
            "default": "allkeys-lru",
            "enum": [
              "allkeys-lru",
              "allkeys-lfu",
              "volatile-lru",
              "noeviction"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "healthCheckPath": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "ignorePaths": {
            "default": [],
            "items": {
              "maxLength": 255,
              "type": "string"
            },
            "maxItems": 50,
            "type": "array"
          },
          "image": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "includePaths": {
            "default": [],
            "items": {
              "maxLength": 255,
              "type": "string"
            },
            "maxItems": 50,
            "type": "array"
          },
          "ipAllowList": {
            "default": [],
            "items": {
              "maxLength": 255,
              "type": "string"
            },
            "maxItems": 50,
            "type": "array"
          },
          "maintenance": {
            "default": false,
            "type": "boolean"
          },
          "maintenancePage": {
            "default": "",
            "description": "Empty or an HTTPS URL without embedded credentials.",
            "maxLength": 1000,
            "type": "string"
          },
          "maxConcurrency": {
            "default": 1,
            "maximum": 100,
            "minimum": 1,
            "type": "integer"
          },
          "maxReplicas": {
            "default": 3,
            "maximum": 20,
            "minimum": 1,
            "type": "integer"
          },
          "maxRetries": {
            "default": 3,
            "maximum": 10,
            "minimum": 0,
            "type": "integer"
          },
          "minReplicas": {
            "default": 1,
            "maximum": 20,
            "minimum": 1,
            "type": "integer"
          },
          "notifications": {
            "default": "workspace",
            "enum": [
              "workspace",
              "all",
              "failure",
              "none"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "plan": {
            "default": "builder",
            "description": "MySQL defaults to mysql-free: one database per workspace, 768 MiB RAM, 0.25 shared CPU, 2 GiB persistent storage, 25 connections and up to 7 days of backups, with no card or expiry. PostgreSQL uses postgres-* plans; MySQL uses mysql-* plans; other kinds use compute plans. The free compute plan supports web/static only. Paid services require a confirmed service-month purchase through hosted checkout.",
            "enum": [
              "free",
              "starter",
              "builder",
              "growth",
              "scale",
              "postgres-starter",
              "postgres-standard",
              "mysql-free",
              "mysql-starter",
              "mysql-standard"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "platformDomainEnabled": {
            "default": true,
            "type": "boolean"
          },
          "port": {
            "default": 8000,
            "maximum": 65535,
            "minimum": 1,
            "type": "integer"
          },
          "preDeployCommand": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "previewExpiryHours": {
            "default": 72,
            "maximum": 720,
            "minimum": 1,
            "type": "integer"
          },
          "previewMode": {
            "default": "off",
            "enum": [
              "off",
              "manual",
              "automatic"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "privateNetworking": {
            "default": true,
            "type": "boolean"
          },
          "publishDirectory": {
            "default": "dist",
            "description": "Relative repository path without backslashes or parent traversal.",
            "maxLength": 255,
            "type": "string"
          },
          "region": {
            "default": "auto",
            "enum": [
              "auto",
              "eu"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "registryId": {
            "default": "",
            "description": "Empty or the UUID of a registry integration in this workspace.",
            "maxLength": 2000,
            "type": "string"
          },
          "replicas": {
            "default": 1,
            "maximum": 20,
            "minimum": 1,
            "type": "integer"
          },
          "repository": {
            "default": "",
            "description": "Empty or an HTTPS URL without embedded credentials.",
            "maxLength": 1000,
            "type": "string"
          },
          "rootDirectory": {
            "default": "",
            "description": "Relative repository path without backslashes or parent traversal.",
            "maxLength": 255,
            "type": "string"
          },
          "runtime": {
            "default": "auto",
            "description": "auto detects the application. Railpack is the default build method.",
            "enum": [
              "auto",
              "docker",
              "node",
              "python",
              "go",
              "php",
              "java",
              "ruby",
              "rust",
              "elixir",
              "deno",
              "dotnet",
              "gleam",
              "cpp",
              "static",
              "shell"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "scaling": {
            "default": "manual",
            "enum": [
              "manual",
              "automatic"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "schedule": {
            "default": "0 * * * *",
            "description": "Cron expression validated for cron services; timezone uses an IANA identifier.",
            "maxLength": 2000,
            "type": "string"
          },
          "sourceType": {
            "default": "repository",
            "enum": [
              "repository",
              "image",
              "none"
            ],
            "maxLength": 2000,
            "type": "string"
          },
          "startCommand": {
            "default": "",
            "maxLength": 2000,
            "type": "string"
          },
          "targetCpu": {
            "default": 70,
            "maximum": 100,
            "minimum": 1,
            "type": "integer"
          },
          "targetMemory": {
            "default": 80,
            "maximum": 100,
            "minimum": 1,
            "type": "integer"
          },
          "timeoutSeconds": {
            "default": 3600,
            "description": "Cron services have a lower maximum of 43200 seconds.",
            "maximum": 86400,
            "minimum": 1,
            "type": "integer"
          },
          "timezone": {
            "default": "UTC",
            "maxLength": 2000,
            "type": "string"
          }
        },
        "type": "object"
      },
      "ServiceCreate": {
        "properties": {
          "automaticPaymentConsent": {
            "deprecated": true,
            "description": "Legacy field. Automatic monetary collection is disabled. Purchase service months through the dashboard.",
            "type": "string"
          },
          "billingConsent": {
            "deprecated": true,
            "description": "Legacy field. Paid compute now requires a settled prepaid service term purchased in the dashboard; this field cannot grant access.",
            "type": "string"
          },
          "configuration": {
            "$ref": "#/components/schemas/ServiceConfigurationInput"
          },
          "deploy": {
            "default": false,
            "description": "If true, queue a real deployment in the same creation transaction. Failure rolls creation back.",
            "type": "boolean"
          },
          "disk": {
            "properties": {
              "configuration": {
                "properties": {
                  "mountPath": {
                    "type": "string"
                  },
                  "sizeGb": {
                    "maximum": 1000,
                    "minimum": 5,
                    "type": "integer"
                  }
                },
                "type": "object"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "name"
            ],
            "type": "object"
          },
          "environmentId": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "kind": {
            "enum": [
              "static",
              "web",
              "private",
              "worker",
              "cron",
              "postgres",
              "mysql",
              "redis",
              "workflow"
            ],
            "type": "string"
          },
          "name": {
            "maxLength": 63,
            "minLength": 1,
            "pattern": "^[a-z0-9][a-z0-9-]*$",
            "type": "string"
          },
          "projectId": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "requestId": {
            "description": "Legacy alias of Idempotency-Key. If both are supplied they must agree. This is distinct from the requestId on an error response.",
            "maxLength": 160,
            "minLength": 1,
            "pattern": "^[!-~]+$",
            "type": "string"
          },
          "secretFiles": {
            "items": {
              "properties": {
                "key": {
                  "maxLength": 255,
                  "type": "string"
                },
                "value": {
                  "description": "UTF-8 text, at most 65536 bytes. Never returned by CRUD responses.",
                  "type": "string",
                  "writeOnly": true
                }
              },
              "required": [
                "key",
                "value"
              ],
              "type": "object"
            },
            "maxItems": 20,
            "type": "array"
          },
          "variables": {
            "items": {
              "$ref": "#/components/schemas/VariableCreate"
            },
            "maxItems": 100,
            "type": "array"
          }
        },
        "required": [
          "name",
          "kind"
        ],
        "type": "object"
      },
      "ServiceList": {
        "properties": {
          "page": {
            "$ref": "#/components/schemas/Page"
          },
          "services": {
            "items": {
              "$ref": "#/components/schemas/Service"
            },
            "type": "array"
          }
        },
        "required": [
          "services"
        ],
        "type": "object"
      },
      "ServiceResponse": {
        "properties": {
          "service": {
            "$ref": "#/components/schemas/Service"
          }
        },
        "required": [
          "service"
        ],
        "type": "object"
      },
      "ServiceUpdate": {
        "description": "PATCH merges supplied configuration fields. kind is immutable; send the current value or omit it.",
        "properties": {
          "configuration": {
            "$ref": "#/components/schemas/ServiceConfigurationInput"
          },
          "environmentId": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "kind": {
            "enum": [
              "static",
              "web",
              "private",
              "worker",
              "cron",
              "postgres",
              "mysql",
              "redis",
              "workflow"
            ],
            "type": "string"
          },
          "name": {
            "maxLength": 63,
            "minLength": 1,
            "pattern": "^[a-z0-9][a-z0-9-]*$",
            "type": "string"
          },
          "projectId": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "requestId": {
            "description": "Legacy alias of Idempotency-Key. If both are supplied they must agree. This is distinct from the requestId on an error response.",
            "maxLength": 160,
            "minLength": 1,
            "pattern": "^[!-~]+$",
            "type": "string"
          }
        },
        "type": "object"
      },
      "Variable": {
        "properties": {
          "configured": {
            "const": true,
            "type": "boolean"
          },
          "createdAt": {
            "format": "date-time",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "key": {
            "type": "string"
          },
          "kind": {
            "const": "variable",
            "type": "string"
          },
          "updatedAt": {
            "format": "date-time",
            "type": "string"
          },
          "value": {
            "type": "null"
          }
        },
        "required": [
          "id",
          "createdAt",
          "updatedAt",
          "key",
          "kind",
          "value",
          "configured"
        ],
        "type": "object"
      },
      "VariableCreate": {
        "properties": {
          "key": {
            "maxLength": 255,
            "pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
            "type": "string"
          },
          "requestId": {
            "description": "Legacy alias of Idempotency-Key. If both are supplied they must agree. This is distinct from the requestId on an error response.",
            "maxLength": 160,
            "minLength": 1,
            "pattern": "^[!-~]+$",
            "type": "string"
          },
          "value": {
            "description": "UTF-8 text, at most 65536 bytes. Never returned by CRUD responses.",
            "type": "string",
            "writeOnly": true
          }
        },
        "required": [
          "key",
          "value"
        ],
        "type": "object"
      },
      "VariableList": {
        "properties": {
          "page": {
            "$ref": "#/components/schemas/Page"
          },
          "variables": {
            "items": {
              "$ref": "#/components/schemas/Variable"
            },
            "type": "array"
          }
        },
        "required": [
          "variables"
        ],
        "type": "object"
      },
      "VariableResponse": {
        "examples": [
          {
            "variable": {
              "configured": true,
              "createdAt": "2026-09-25T12:00:00Z",
              "id": "00000000-0000-4000-8000-000000000001",
              "key": "APP_ENV",
              "kind": "variable",
              "updatedAt": "2026-09-25T12:00:00Z",
              "value": null
            }
          }
        ],
        "properties": {
          "variable": {
            "$ref": "#/components/schemas/Variable"
          }
        },
        "required": [
          "variable"
        ],
        "type": "object"
      },
      "VariableUpdate": {
        "properties": {
          "key": {
            "maxLength": 255,
            "pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
            "type": "string"
          },
          "requestId": {
            "description": "Legacy alias of Idempotency-Key. If both are supplied they must agree. This is distinct from the requestId on an error response.",
            "maxLength": 160,
            "minLength": 1,
            "pattern": "^[!-~]+$",
            "type": "string"
          },
          "value": {
            "description": "UTF-8 text, at most 65536 bytes. Never returned by CRUD responses.",
            "type": "string",
            "writeOnly": true
          }
        },
        "type": "object"
      },
      "Workspace": {
        "properties": {
          "billing": {
            "description": "Visible fields depend on the caller role.",
            "type": "object"
          },
          "configuration": {
            "properties": {
              "allowOverages": {
                "default": false,
                "type": "boolean"
              },
              "avatarColor": {
                "default": "#e6daff",
                "maxLength": 2000,
                "type": "string"
              },
              "backupNotifications": {
                "default": true,
                "type": "boolean"
              },
              "budget": {
                "default": 0,
                "maximum": 100000000,
                "minimum": 0,
                "type": "integer"
              },
              "budgetAlerts": {
                "default": true,
                "type": "boolean"
              },
              "buildConcurrency": {
                "default": 1,
                "maximum": 10,
                "minimum": 1,
                "type": "integer"
              },
              "currency": {
                "default": "USD",
                "maxLength": 2000,
                "type": "string"
              },
              "defaultRegion": {
                "default": "auto",
                "maxLength": 2000,
                "type": "string"
              },
              "deployNotifications": {
                "default": "failure",
                "maxLength": 2000,
                "type": "string"
              },
              "description": {
                "default": "",
                "maxLength": 2000,
                "type": "string"
              },
              "includePreviewLogs": {
                "default": true,
                "type": "boolean"
              },
              "notificationEmail": {
                "default": "",
                "maxLength": 2000,
                "type": "string"
              },
              "overlappingDeploys": {
                "default": "cancel",
                "maxLength": 2000,
                "type": "string"
              },
              "previewNotifications": {
                "default": false,
                "type": "boolean"
              },
              "requireMfa": {
                "default": false,
                "type": "boolean"
              },
              "securityContact": {
                "default": "",
                "maxLength": 2000,
                "type": "string"
              },
              "timezone": {
                "default": "Africa/Lagos",
                "maxLength": 2000,
                "type": "string"
              }
            },
            "type": "object"
          },
          "entitlements": {
            "type": "object"
          },
          "id": {
            "format": "uuid",
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "plan": {
            "type": "string"
          },
          "role": {
            "enum": [
              "viewer",
              "developer",
              "admin",
              "owner"
            ],
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "role",
          "plan",
          "entitlements",
          "configuration",
          "billing"
        ],
        "type": "object"
      },
      "WorkspaceResponse": {
        "properties": {
          "workspace": {
            "$ref": "#/components/schemas/Workspace"
          }
        },
        "required": [
          "workspace"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "bearerFormat": "Openstead API key",
        "description": "Workspace-scoped rnv_ API key. Read scope allows GET; write scope is additionally constrained by current membership, role, email verification, expiry and workspace MFA policy.",
        "scheme": "bearer",
        "type": "http"
      },
      "browserSession": {
        "description": "Authenticated Django browser session. Mutating requests also require the X-CSRFToken header and runivo_csrf cookie from /api/bootstrap.",
        "in": "cookie",
        "name": "runivo_session",
        "type": "apiKey"
      }
    }
  },
  "info": {
    "description": "Supported public core of the Openstead managed hosting API. This contract covers catalog, workspace reads, project canvases, projects, services, variables, deployments and logs; it is not a complete listing of dashboard, billing, account, CLI authorization or internal operations endpoints. All resource access is authorized in Django. HTTP 200 on a queued operation is acceptance, not proof of live infrastructure.",
    "title": "Openstead Core API",
    "version": "1.0.0"
  },
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
  "openapi": "3.1.0",
  "paths": {
    "/catalog": {
      "get": {
        "description": "Requires authentication. Read capabilities from this environment; workerOnline reports recent worker readiness. Listed service types are not a guarantee of available capacity. Prices are estimates.",
        "operationId": "getCatalog",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Catalog"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Get supported configuration and runtime capabilities",
        "tags": [
          "Catalog"
        ],
        "x-idempotency-supported": false
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApiSchema",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "required": [
                    "openapi",
                    "info",
                    "paths"
                  ],
                  "type": "object"
                }
              }
            },
            "description": "OpenAPI 3.1 JSON document. No authentication required."
          }
        },
        "security": [],
        "summary": "Get this public core API contract",
        "tags": [
          "Catalog"
        ]
      }
    },
    "/workspaces/{workspaceId}": {
      "get": {
        "description": "",
        "operationId": "getWorkspace",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Get a workspace",
        "tags": [
          "Workspaces"
        ],
        "x-idempotency-supported": false
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        }
      ]
    },
    "/workspaces/{workspaceId}/canvas": {
      "get": {
        "description": "Readers can view the workspace, one project across its environments, or one project environment. Only active service records and valid scoped reference/group connections are shown; archived and deleting/deleted services are excluded. Manual secret values are never inspected. Layouts are independent per scope. Unsaved layouts have revision 0. No pagination or silent truncation: scopes beyond 2000 total nodes or 10000 reference records/edges return 413 canvas_too_large.",
        "operationId": "getWorkspaceCanvas",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "description": "Optional project in this workspace; omit for all workspace services.",
            "in": "query",
            "name": "projectId",
            "required": false,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Optional environment; requires projectId and must belong to that project.",
            "in": "query",
            "name": "environmentId",
            "required": false,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CanvasResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Get scoped service topology and shared layout",
        "tags": [
          "Canvas"
        ],
        "x-idempotency-supported": false
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        }
      ],
      "patch": {
        "description": "Developer, admin or owner required, including in protected environments because this changes visual state only. Replaces all saved positions and viewport for the selected scope. A stale revision returns 409 canvas_revision_conflict; GET the latest canvas before retrying. Unknown or no-longer-visible node IDs return 400 canvas_invalid_node. Unknown scope parameters, duplicate/empty scope values and unsupported fields are rejected. Maximum request body is 256 KiB. Uses optimistic revision control, not Idempotency-Key replay.",
        "operationId": "saveWorkspaceCanvas",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "description": "Optional project in this workspace; omit for all workspace services.",
            "in": "query",
            "name": "projectId",
            "required": false,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Optional environment; requires projectId and must belong to that project.",
            "in": "query",
            "name": "environmentId",
            "required": false,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "positions": {},
                "revision": 0,
                "viewport": null
              },
              "schema": {
                "$ref": "#/components/schemas/CanvasLayoutUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CanvasResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Save the shared visual layout",
        "tags": [
          "Canvas"
        ],
        "x-idempotency-supported": false
      }
    },
    "/workspaces/{workspaceId}/projects": {
      "get": {
        "description": "Legacy requests without limit/cursor return the complete list. Opt in to bounded pages with limit or cursor.",
        "operationId": "listProjects",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectList"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "List projects",
        "tags": [
          "Projects"
        ],
        "x-idempotency-supported": false
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        }
      ],
      "post": {
        "description": "",
        "operationId": "createProject",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "color": "violet",
                "name": "API platform"
              },
              "schema": {
                "$ref": "#/components/schemas/ProjectCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Create a project and its Production environment",
        "tags": [
          "Projects"
        ],
        "x-idempotency-supported": true
      }
    },
    "/workspaces/{workspaceId}/projects/{projectId}": {
      "delete": {
        "description": "Admin or owner required. Move/delete services and scoped environment groups first. confirm must exactly match the project name.",
        "operationId": "deleteProject",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "confirm": "API platform"
              },
              "schema": {
                "$ref": "#/components/schemas/ConfirmRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Delete an empty project",
        "tags": [
          "Projects"
        ],
        "x-idempotency-supported": true
      },
      "get": {
        "description": "",
        "operationId": "getProject",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Get a project",
        "tags": [
          "Projects"
        ],
        "x-idempotency-supported": false
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/projectId"
        }
      ],
      "patch": {
        "description": "",
        "operationId": "updateProject",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "description": "Public API and workers"
              },
              "schema": {
                "$ref": "#/components/schemas/ProjectUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Update a project",
        "tags": [
          "Projects"
        ],
        "x-idempotency-supported": true
      }
    },
    "/workspaces/{workspaceId}/services": {
      "get": {
        "description": "Includes archived services. Legacy requests without limit/cursor return the complete list.",
        "operationId": "listServices",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceList"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "List services",
        "tags": [
          "Services"
        ],
        "x-idempotency-supported": false
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        }
      ],
      "post": {
        "description": "Creation saves configuration by default. deploy:true also queues real execution if enabled and authorized. Project placement requires an environment belonging to that project. Protected environments require admin access. API keys cannot grant paid-compute or automatic-payment consent.",
        "operationId": "createService",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "configuration": {
                  "buildMethod": "railpack",
                  "plan": "free",
                  "port": 8000,
                  "repository": "https://github.com/your-team/your-app",
                  "runtime": "auto",
                  "sourceType": "repository"
                },
                "deploy": false,
                "kind": "web",
                "name": "my-api",
                "variables": [
                  {
                    "key": "APP_ENV",
                    "value": "production"
                  }
                ]
              },
              "schema": {
                "$ref": "#/components/schemas/ServiceCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Create a service",
        "tags": [
          "Services"
        ],
        "x-idempotency-supported": true
      }
    },
    "/workspaces/{workspaceId}/services/{serviceId}": {
      "delete": {
        "description": "Without runtime infrastructure returns deleted:true. With runtime infrastructure archives the service and queues deletion, returning deleted:false, queued:true. HTTP 200 is preserved; queued does not mean deletion finished.",
        "operationId": "deleteService",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "confirm": "my-api"
              },
              "schema": {
                "$ref": "#/components/schemas/ConfirmRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Delete a service or queue infrastructure deletion",
        "tags": [
          "Services"
        ],
        "x-idempotency-supported": true
      },
      "get": {
        "description": "",
        "operationId": "getService",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Get service configuration and runtime state",
        "tags": [
          "Services"
        ],
        "x-idempotency-supported": false
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/serviceId"
        }
      ],
      "patch": {
        "description": "Merges configuration fields; does not start a new deployment. Some routing settings enqueue routing reconciliation. A service kind cannot change. Environment moves must preserve valid variable-group scope.",
        "operationId": "updateService",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "configuration": {
                  "healthCheckPath": "/health"
                }
              },
              "schema": {
                "$ref": "#/components/schemas/ServiceUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Update service configuration",
        "tags": [
          "Services"
        ],
        "x-idempotency-supported": true
      }
    },
    "/workspaces/{workspaceId}/services/{serviceId}/actions": {
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/serviceId"
        }
      ],
      "post": {
        "description": "restart, suspend and resume return queued:true and a pollable operation. deploy and clear-cache return a deployment. Hosting must be enabled; runtime actions require an existing provisioned runtime. HTTP 200 does not mean execution has completed.",
        "operationId": "runServiceAction",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "action": "restart"
              },
              "schema": {
                "$ref": "#/components/schemas/ServiceAction"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActionResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Queue a service action",
        "tags": [
          "Services"
        ],
        "x-idempotency-supported": true
      }
    },
    "/workspaces/{workspaceId}/services/{serviceId}/archive": {
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/serviceId"
        }
      ],
      "post": {
        "description": "Sets archived:true and prevents deployment. This is not a runtime suspend or infrastructure deletion operation.",
        "operationId": "archiveService",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {},
              "schema": {
                "$ref": "#/components/schemas/OptionalRequest"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Archive service configuration",
        "tags": [
          "Services"
        ],
        "x-idempotency-supported": true
      }
    },
    "/workspaces/{workspaceId}/services/{serviceId}/deploys": {
      "get": {
        "description": "Bounded by default to 100; maximum limit 200. Follow page.nextCursor for older deployments. Hosting disabled with no runtime returns available:false and empty items.",
        "operationId": "listDeployments",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeploymentList"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "List deployments, newest first",
        "tags": [
          "Deployments"
        ],
        "x-idempotency-supported": false
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/serviceId"
        }
      ],
      "post": {
        "description": "Creates a durable deployment/job when hosting is enabled, subject to capacity, billing and source validation. The initial status is queued. Poll getDeployment for progress; use getService for the serving release. A replay returns the original successful response, not the latest status.",
        "operationId": "createDeployment",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {},
              "schema": {
                "$ref": "#/components/schemas/DeploymentCreate"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeploymentResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Queue a deployment",
        "tags": [
          "Deployments"
        ],
        "x-idempotency-supported": true
      }
    },
    "/workspaces/{workspaceId}/services/{serviceId}/deploys/{deploymentId}": {
      "get": {
        "description": "",
        "operationId": "getDeployment",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeploymentResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Get deployment progress",
        "tags": [
          "Deployments"
        ],
        "x-idempotency-supported": false
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/serviceId"
        },
        {
          "$ref": "#/components/parameters/deploymentId"
        }
      ]
    },
    "/workspaces/{workspaceId}/services/{serviceId}/deploys/{deploymentId}/cancel": {
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/serviceId"
        },
        {
          "$ref": "#/components/parameters/deploymentId"
        }
      ],
      "post": {
        "description": "Terminal deployments reject new cancellation requests. cancelRequested:true acknowledges the request; a running worker must still stop safely. Poll the deployment for its terminal state.",
        "operationId": "cancelDeployment",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {},
              "schema": {
                "$ref": "#/components/schemas/OptionalRequest"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Request deployment cancellation",
        "tags": [
          "Deployments"
        ],
        "x-idempotency-supported": true
      }
    },
    "/workspaces/{workspaceId}/services/{serviceId}/deploys/{deploymentId}/rollback": {
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/serviceId"
        },
        {
          "$ref": "#/components/parameters/deploymentId"
        }
      ],
      "post": {
        "description": "The source must be a live deployment of this service with a retained image. Reuses its configuration and encrypted secret snapshot to queue a new deployment. confirm is the service name. This is not an in-place status edit.",
        "operationId": "rollbackDeployment",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "confirm": "my-api"
              },
              "schema": {
                "$ref": "#/components/schemas/ConfirmRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeploymentResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Queue a rollback to a successful release",
        "tags": [
          "Deployments"
        ],
        "x-idempotency-supported": true
      }
    },
    "/workspaces/{workspaceId}/services/{serviceId}/logs": {
      "get": {
        "description": "Without after returns the newest retained batch in ascending numeric ID order. With after returns later lines in ascending ID order. Continue with response cursor; this is not opaque collection pagination. Retention depends on the plan, and search is limited to 200 characters.",
        "operationId": "listServiceLogs",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "description": "Numeric log cursor from the previous response.",
            "in": "query",
            "name": "after",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "Maximum lines per batch.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 500,
              "maximum": 500,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Filter by deployment in this service.",
            "in": "query",
            "name": "deployment",
            "required": false,
            "schema": {
              "format": "uuid",
              "type": "string"
            }
          },
          {
            "description": "Log source.",
            "in": "query",
            "name": "source",
            "required": false,
            "schema": {
              "enum": [
                "build",
                "runtime",
                "system"
              ],
              "type": "string"
            }
          },
          {
            "description": "Case-insensitive message substring.",
            "in": "query",
            "name": "search",
            "required": false,
            "schema": {
              "maxLength": 200,
              "type": "string"
            }
          },
          {
            "description": "Lookback window, clamped to at least one hour and the plan retention limit.",
            "in": "query",
            "name": "hours",
            "required": false,
            "schema": {
              "default": 24,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LogList"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Read or tail service logs",
        "tags": [
          "Logs"
        ],
        "x-idempotency-supported": false
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/serviceId"
        }
      ]
    },
    "/workspaces/{workspaceId}/services/{serviceId}/operations/{operationId}": {
      "get": {
        "description": "Returns the actual queued/running/complete/failed state of a job belonging to this workspace and service. Internal payloads and error details are not exposed.",
        "operationId": "getServiceOperation",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperationResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Get service operation progress",
        "tags": [
          "Services"
        ],
        "x-idempotency-supported": false
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/serviceId"
        },
        {
          "$ref": "#/components/parameters/operationId"
        }
      ]
    },
    "/workspaces/{workspaceId}/services/{serviceId}/restore": {
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/serviceId"
        }
      ],
      "post": {
        "description": "Sets archived:false; does not automatically deploy or resume infrastructure.",
        "operationId": "restoreService",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {},
              "schema": {
                "$ref": "#/components/schemas/OptionalRequest"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Restore archived service configuration",
        "tags": [
          "Services"
        ],
        "x-idempotency-supported": true
      }
    },
    "/workspaces/{workspaceId}/services/{serviceId}/variables": {
      "get": {
        "description": "Values are always null. Legacy requests without limit/cursor return all variables.",
        "operationId": "listServiceVariables",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VariableList"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "List masked variable metadata",
        "tags": [
          "Variables"
        ],
        "x-idempotency-supported": false
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/serviceId"
        }
      ],
      "post": {
        "description": "The stored value is encrypted. The response contains only masked metadata.",
        "operationId": "createServiceVariable",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "key": "APP_ENV",
                "value": "production"
              },
              "schema": {
                "$ref": "#/components/schemas/VariableCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VariableResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Create an encrypted variable",
        "tags": [
          "Variables"
        ],
        "x-idempotency-supported": true
      }
    },
    "/workspaces/{workspaceId}/services/{serviceId}/variables/{variableId}": {
      "delete": {
        "description": "",
        "operationId": "deleteServiceVariable",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {},
              "schema": {
                "$ref": "#/components/schemas/OptionalRequest"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Delete a variable",
        "tags": [
          "Variables"
        ],
        "x-idempotency-supported": true
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/serviceId"
        },
        {
          "$ref": "#/components/parameters/variableId"
        }
      ],
      "patch": {
        "description": "",
        "operationId": "updateServiceVariable",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          },
          {
            "$ref": "#/components/parameters/idempotency"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "value": "production"
              },
              "schema": {
                "$ref": "#/components/schemas/VariableUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VariableResponse"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "Idempotency-Replayed": {
                "$ref": "#/components/headers/IdempotencyReplayed"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Update a variable name or encrypted value",
        "tags": [
          "Variables"
        ],
        "x-idempotency-supported": true
      }
    },
    "/workspaces/{workspaceId}/services/{serviceId}/variables/{variableId}/reveal": {
      "parameters": [
        {
          "$ref": "#/components/parameters/workspaceId"
        },
        {
          "$ref": "#/components/parameters/serviceId"
        },
        {
          "$ref": "#/components/parameters/variableId"
        }
      ],
      "post": {
        "description": "Developer role or above, plus protected-environment checks. This secret-bearing operation is explicitly excluded from idempotent replay; sending an idempotency key is rejected. Never log this response.",
        "operationId": "revealServiceVariable",
        "parameters": [
          {
            "$ref": "#/components/parameters/requestId"
          },
          {
            "$ref": "#/components/parameters/csrf"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevealedVariable"
                }
              }
            },
            "description": "Success. Creates and queued operations intentionally retain HTTP 200.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "405": {
            "$ref": "#/components/responses/405"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "413": {
            "$ref": "#/components/responses/413"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "summary": "Reveal a variable with an audit event",
        "tags": [
          "Variables"
        ],
        "x-idempotency-supported": false
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    },
    {
      "browserSession": []
    }
  ],
  "servers": [
    {
      "description": "Same origin as this document; supported through the dashboard proxy or configured API origin.",
      "url": "/api/v1"
    }
  ],
  "tags": [
    {
      "name": "Catalog"
    },
    {
      "name": "Workspaces"
    },
    {
      "name": "Canvas"
    },
    {
      "name": "Projects"
    },
    {
      "name": "Services"
    },
    {
      "name": "Variables"
    },
    {
      "name": "Deployments"
    },
    {
      "name": "Logs"
    }
  ],
  "x-compatibility-policy": "docs/api-compatibility.md"
}
