{
  "openapi": "3.1.0",
  "info": {
    "title": "SpringRoll API",
    "version": "0.2.0",
    "summary": "The Control Plane and App Portal for AI-built Applications",
    "description": "Deploy AI-built applications safely, connect them to approved company data, and make them available to the right people.\n\nSpringRoll currently deploys to managed Vercel and Cloudflare.\n\nSpringRoll compares eligible Vercel and Cloudflare plans, selects the lowest-cost qualified fit, and records the estimate, assumptions, and limits.\n\n**Most agents should use MCP instead of this API.** The remote MCP endpoint at `/api/mcp` speaks Streamable HTTP, advertises its own authorization server, and exposes the same control plane as 19 tools with the workflow already encoded. See the Server Card at `/.well-known/mcp/server-card.json`. This document exists for integrations that cannot speak MCP.\n\nEvery endpoint answers a single error envelope (`components/schemas/Error`) with a stable `code`, a `correlationId`, and, when the failure is recoverable, a `nextActions` list. Branch on `code`, never on prose.\n\nManifest contract: `springboard.dev/v1alpha1`. Fetch `/api/v1/capabilities` for the current schema and a worked example.\n\n**Rate limits.** Every rate-limited response carries `RateLimit` and `RateLimit-Policy` (structured fields), the `RateLimit-Limit`/`-Remaining`/`-Reset` triplet, and `X-RateLimit-*`; a 429 adds `Retry-After`. Per 60-second window: 600 reads, 120 writes, 20 deployments, 30 unauthenticated requests. Limits are keyed on the authenticated identity where there is one and the network address otherwise.\n\n**Versioning.** The major version is the first path segment after `/api`; `v1` is current and changes only additively, so treat unknown response fields as forward compatibility. A retired version answers with `Deprecation` (RFC 9745) and `Sunset` (RFC 8594) headers for at least 365 days before it stops, then 410 Gone. Full policy: `/docs/api`.",
    "contact": {
      "name": "SpringRoll (M Intelligence Co., Ltd.)",
      "url": "https://springroll.dev/contact"
    },
    "termsOfService": "https://springroll.dev/terms",
    "x-api-lifecycle": {
      "scheme": "url-path",
      "description": "The major version is the first path segment after /api. A breaking change gets a new segment; within a version, only additive changes are made: new fields, new optional parameters, new endpoints. Treat unknown response fields as forward compatibility, not as an error.",
      "current": "v1",
      "versions": [
        {
          "version": "v1",
          "status": "current",
          "basePath": "/api/v1",
          "deprecationDate": null,
          "sunsetDate": null,
          "successor": null
        }
      ],
      "deprecation": {
        "noticeDays": 365,
        "description": "A deprecated version keeps answering for at least 365 days after it is announced. From the moment it is deprecated, every response from it carries a Deprecation header (RFC 9745) with the date it was deprecated, a Sunset header (RFC 8594) with the date it stops answering, and a Link header with rel=\"deprecation\" pointing at this policy and rel=\"successor-version\" pointing at what to move to. After the sunset date the version answers 410 Gone with the standard error envelope.",
        "headers": [
          "Deprecation",
          "Sunset",
          "Link"
        ],
        "policy": "https://springroll.dev/docs/api"
      },
      "mcp": {
        "description": "MCP tool names are versioned by the server version, not by a path. A renamed or removed tool fails on tools/call rather than aliasing silently, because MCP has no deprecation channel for a tool name, and a silent alias would leave an agent using a vocabulary the documentation no longer describes. Read tools/list at the start of a session rather than hard-coding names.",
        "serverCard": "https://springroll.dev/.well-known/mcp/server-card.json"
      }
    }
  },
  "servers": [
    {
      "url": "https://springroll.dev",
      "description": "Production."
    }
  ],
  "externalDocs": {
    "url": "https://springroll.dev/docs/api",
    "description": "The SpringRoll API reference: authentication, rate limits, versioning and deprecation, and the error envelope."
  },
  "tags": [
    {
      "name": "Discovery",
      "description": "Unauthenticated endpoints describing this deployment."
    },
    {
      "name": "Applications",
      "description": "Register and inspect applications."
    },
    {
      "name": "Releases",
      "description": "Immutable release bundles."
    },
    {
      "name": "Deployments",
      "description": "Deploy, promote, and roll back."
    },
    {
      "name": "Approvals",
      "description": "Decisions that require a person."
    },
    {
      "name": "Data access",
      "description": "Governed access to company data."
    },
    {
      "name": "Audit",
      "description": "The append-only record of governed actions."
    },
    {
      "name": "MCP",
      "description": "The Model Context Protocol surface."
    }
  ],
  "security": [
    {
      "agentToken": []
    }
  ],
  "paths": {
    "/api/v1": {
      "get": {
        "operationId": "getApiIndex",
        "summary": "API index",
        "description": "Unauthenticated index of every documented entry point on this deployment: the OpenAPI document, the MCP endpoint and manifest, the agent instructions, and how to authenticate. Start here.",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "The index.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "name",
                    "version",
                    "documentation",
                    "authentication",
                    "endpoints"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "documentation": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string",
                        "format": "uri"
                      },
                      "description": "Absolute URLs for every machine-readable document."
                    },
                    "authentication": {
                      "type": "object",
                      "description": "How to obtain a credential, for both agents and integrations.",
                      "additionalProperties": true
                    },
                    "endpoints": {
                      "type": "array",
                      "description": "Documented endpoints, each with its method, path, and whether it needs a credential.",
                      "items": {
                        "type": "object",
                        "required": [
                          "method",
                          "path",
                          "description",
                          "authenticated"
                        ],
                        "properties": {
                          "method": {
                            "type": "string"
                          },
                          "path": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "authenticated": {
                            "type": "boolean"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/capabilities": {
      "get": {
        "operationId": "getCapabilities",
        "summary": "Capabilities",
        "description": "Unauthenticated description of what this deployment can do: every MCP tool with its title, summary, and whether it is read-only, plus the current application manifest contract and a worked example. An agent can read this before authenticating to decide whether SpringRoll is the right tool.",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "The capability description.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "mcp",
                    "manifest"
                  ],
                  "properties": {
                    "mcp": {
                      "type": "object",
                      "required": [
                        "endpoint",
                        "transport",
                        "tools"
                      ],
                      "properties": {
                        "endpoint": {
                          "type": "string",
                          "format": "uri"
                        },
                        "transport": {
                          "type": "string",
                          "enum": [
                            "streamable-http"
                          ]
                        },
                        "protocolVersion": {
                          "type": "string"
                        },
                        "tools": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "required": [
                              "name",
                              "description",
                              "readOnly"
                            ],
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "title": {
                                "type": "string"
                              },
                              "description": {
                                "type": "string"
                              },
                              "readOnly": {
                                "type": "boolean",
                                "description": "A read-only tool changes nothing and is always safe to call."
                              }
                            }
                          }
                        }
                      }
                    },
                    "manifest": {
                      "type": "object",
                      "required": [
                        "apiVersion"
                      ],
                      "description": "The application manifest contract, with an example document.",
                      "properties": {
                        "apiVersion": {
                          "type": "string"
                        },
                        "exampleMediaType": {
                          "type": "string",
                          "enum": [
                            "application/yaml"
                          ]
                        },
                        "example": {
                          "type": "string",
                          "description": "A complete example manifest, as YAML."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Liveness and readiness",
        "description": "Unauthenticated probe. Reports whether the process can reach its database and whether secret encryption and the auth secret are configured. Answers 503 when the database is unreachable. Reveals nothing else.",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "checks"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok",
                        "degraded"
                      ]
                    },
                    "checks": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "fail",
                          "not_configured"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Degraded: the database is unreachable.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "checks"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "degraded"
                      ]
                    },
                    "checks": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "fail",
                          "not_configured"
                        ]
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps": {
      "get": {
        "operationId": "listApplications",
        "summary": "List applications",
        "description": "Applications in this organization that the caller is permitted to see, filtered in SQL. Retired applications are excluded unless asked for.",
        "tags": [
          "Applications"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Free-text match on name and slug.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "lifecycleStatus",
            "in": "query",
            "required": false,
            "description": "Repeatable. Restricts results to these lifecycle statuses.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "DEV",
                  "UAT",
                  "PRODUCTION",
                  "SUSPENDED",
                  "DEPRECATED",
                  "RETIRED"
                ]
              }
            }
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "description": "Repeatable. All supplied tags must be present.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Ordering.",
            "schema": {
              "type": "string",
              "enum": [
                "name",
                "recent",
                "lastDeployed",
                "risk"
              ]
            }
          },
          {
            "name": "includeRetired",
            "in": "query",
            "required": false,
            "description": "Include retired applications, which are excluded by default.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum records to return.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Records to skip.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of applications.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "total",
                    "items"
                  ],
                  "properties": {
                    "total": {
                      "type": "integer",
                      "description": "Total matching records, ignoring limit and offset."
                    },
                    "items": {
                      "type": "array",
                      "description": "The matching applications.",
                      "items": {
                        "type": "object",
                        "description": "A registered application.",
                        "required": [
                          "id",
                          "slug",
                          "name",
                          "lifecycleStatus"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Opaque server-assigned identifier. Do not construct one."
                          },
                          "slug": {
                            "type": "string",
                            "description": "Stable, URL-safe name, unique inside the organization."
                          },
                          "name": {
                            "type": "string",
                            "description": "Display name."
                          },
                          "description": {
                            "type": "string"
                          },
                          "lifecycleStatus": {
                            "type": "string",
                            "enum": [
                              "DEV",
                              "UAT",
                              "PRODUCTION",
                              "SUSPENDED",
                              "DEPRECATED",
                              "RETIRED"
                            ],
                            "description": "Where the application is in its life: only PRODUCTION and DEPRECATED appear in the App Portal."
                          },
                          "dataClassification": {
                            "type": "string",
                            "enum": [
                              "public",
                              "internal",
                              "confidential",
                              "restricted"
                            ],
                            "description": "The most sensitive class of data the application is cleared for."
                          },
                          "ownerEmail": {
                            "type": "string",
                            "format": "email"
                          },
                          "supportContact": {
                            "type": "string"
                          },
                          "tags": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "RFC 3339 timestamp, always UTC."
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "RFC 3339 timestamp, always UTC."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      },
      "post": {
        "operationId": "createApplication",
        "summary": "Register an application",
        "description": "Registers a new application, or applies a manifest to create one. Requires the app:create permission. Send an Idempotency-Key so a retried registration does not create a duplicate.",
        "tags": [
          "Applications"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Replays safely: the same key with the same body returns the original result, and with a different body returns IDEMPOTENCY_CONFLICT. Send one on every write an agent might retry.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The application to register.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Display name."
                  },
                  "slug": {
                    "description": "URL-safe name. Derived from the name when omitted.",
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "ownerEmail": {
                    "description": "The person accountable for this application.",
                    "type": "string"
                  },
                  "supportContact": {
                    "type": "string"
                  },
                  "dataClassification": {
                    "type": "string"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The registered application.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A registered application.",
                  "required": [
                    "id",
                    "slug",
                    "name",
                    "lifecycleStatus"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "slug": {
                      "type": "string",
                      "description": "Stable, URL-safe name, unique inside the organization."
                    },
                    "name": {
                      "type": "string",
                      "description": "Display name."
                    },
                    "description": {
                      "type": "string"
                    },
                    "lifecycleStatus": {
                      "type": "string",
                      "enum": [
                        "DEV",
                        "UAT",
                        "PRODUCTION",
                        "SUSPENDED",
                        "DEPRECATED",
                        "RETIRED"
                      ],
                      "description": "Where the application is in its life: only PRODUCTION and DEPRECATED appear in the App Portal."
                    },
                    "dataClassification": {
                      "type": "string",
                      "enum": [
                        "public",
                        "internal",
                        "confidential",
                        "restricted"
                      ],
                      "description": "The most sensitive class of data the application is cleared for."
                    },
                    "ownerEmail": {
                      "type": "string",
                      "format": "email"
                    },
                    "supportContact": {
                      "type": "string"
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}": {
      "get": {
        "operationId": "getApplication",
        "summary": "Get an application",
        "description": "One application by id or slug, including its current lifecycle status, owner, and support contact.",
        "tags": [
          "Applications"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The application.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A registered application.",
                  "required": [
                    "id",
                    "slug",
                    "name",
                    "lifecycleStatus"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "slug": {
                      "type": "string",
                      "description": "Stable, URL-safe name, unique inside the organization."
                    },
                    "name": {
                      "type": "string",
                      "description": "Display name."
                    },
                    "description": {
                      "type": "string"
                    },
                    "lifecycleStatus": {
                      "type": "string",
                      "enum": [
                        "DEV",
                        "UAT",
                        "PRODUCTION",
                        "SUSPENDED",
                        "DEPRECATED",
                        "RETIRED"
                      ],
                      "description": "Where the application is in its life: only PRODUCTION and DEPRECATED appear in the App Portal."
                    },
                    "dataClassification": {
                      "type": "string",
                      "enum": [
                        "public",
                        "internal",
                        "confidential",
                        "restricted"
                      ],
                      "description": "The most sensitive class of data the application is cleared for."
                    },
                    "ownerEmail": {
                      "type": "string",
                      "format": "email"
                    },
                    "supportContact": {
                      "type": "string"
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      },
      "patch": {
        "operationId": "updateApplication",
        "summary": "Update an application",
        "description": "Changes application metadata. An ownership change and a tenant-wide visibility change each require an approval, so this can answer 409 with APPROVAL_REQUIRED rather than applying the edit.",
        "tags": [
          "Applications"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Only the supplied fields change.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "ownerEmail": {
                    "type": "string"
                  },
                  "supportContact": {
                    "type": "string"
                  },
                  "dataClassification": {
                    "type": "string"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated application.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A registered application.",
                  "required": [
                    "id",
                    "slug",
                    "name",
                    "lifecycleStatus"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "slug": {
                      "type": "string",
                      "description": "Stable, URL-safe name, unique inside the organization."
                    },
                    "name": {
                      "type": "string",
                      "description": "Display name."
                    },
                    "description": {
                      "type": "string"
                    },
                    "lifecycleStatus": {
                      "type": "string",
                      "enum": [
                        "DEV",
                        "UAT",
                        "PRODUCTION",
                        "SUSPENDED",
                        "DEPRECATED",
                        "RETIRED"
                      ],
                      "description": "Where the application is in its life: only PRODUCTION and DEPRECATED appear in the App Portal."
                    },
                    "dataClassification": {
                      "type": "string",
                      "enum": [
                        "public",
                        "internal",
                        "confidential",
                        "restricted"
                      ],
                      "description": "The most sensitive class of data the application is cleared for."
                    },
                    "ownerEmail": {
                      "type": "string",
                      "format": "email"
                    },
                    "supportContact": {
                      "type": "string"
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/arrivals": {
      "get": {
        "operationId": "getAppArrival",
        "summary": "Read the first app milestone",
        "description": "Returns this member's verified first app arrival and persisted acknowledgment. Does not advance deployment state.",
        "tags": [
          "Applications"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Verified member arrival or null.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "arrival": {
                      "type": [
                        "object",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}/presentation": {
      "get": {
        "operationId": "getPresentationDraft",
        "summary": "Read private app presentation",
        "description": "Returns draft, revision, selected media, publication state and icon-job progress to authorized app managers. Storage locators are never returned.",
        "tags": [
          "Applications"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application UUID.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Private presentation editor model.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "presentation": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      },
      "put": {
        "operationId": "savePresentationDraft",
        "summary": "Save private app presentation",
        "description": "Saves a revision-checked draft with its audit record. Existing public snapshots are unchanged. Only an owner or administrator can publish through the human review action.",
        "tags": [
          "Applications"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application UUID.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Reviewed draft content and last read revision.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "draft": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                      },
                      "tagline": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 160
                      },
                      "description": {
                        "default": "",
                        "type": "string",
                        "maxLength": 4000
                      },
                      "creator": {
                        "default": "",
                        "type": "string",
                        "maxLength": 100
                      },
                      "iconAssetId": {
                        "default": null,
                        "anyOf": [
                          {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "screenshots": {
                        "default": [],
                        "maxItems": 6,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "assetId": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "caption": {
                              "default": "",
                              "type": "string",
                              "maxLength": 180
                            }
                          },
                          "required": [
                            "assetId"
                          ]
                        }
                      },
                      "shareText": {
                        "default": "",
                        "type": "string",
                        "maxLength": 240
                      }
                    },
                    "required": [
                      "name",
                      "tagline"
                    ]
                  },
                  "revision": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "draft",
                  "revision"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated private editor model.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "presentation": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}/presentation/icon": {
      "post": {
        "operationId": "generatePresentationIcon",
        "summary": "Request an app icon draft",
        "description": "Queues a deduplicated, tenant-limited icon job. Optional Gateway configuration and image failures never affect app deployment. Poll the presentation endpoint for its result.",
        "tags": [
          "Applications"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application UUID.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The app's reviewed purpose.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "purpose": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  }
                },
                "required": [
                  "purpose"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Queued icon request.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "generation": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}/presentation/media": {
      "post": {
        "operationId": "uploadPresentationMedia",
        "summary": "Upload a private app image",
        "description": "Accepts raw PNG, JPEG or WebP bytes (8 MB, 24 megapixels maximum). Strips metadata and creates optimized images. Uploads remain private until chosen in a published snapshot.",
        "tags": [
          "Applications"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application UUID.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": true,
            "description": "Whether this is app artwork or a real screenshot.",
            "schema": {
              "type": "string",
              "enum": [
                "icon",
                "screenshot"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "image/png": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/jpeg": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/webp": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Uploaded image metadata without storage locators.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "asset": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Opaque server-assigned identifier. Do not construct one."
                        },
                        "width": {
                          "type": "integer"
                        },
                        "height": {
                          "type": "integer"
                        },
                        "kind": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}/presentation/media/{assetId}": {
      "get": {
        "operationId": "getPrivatePresentationMedia",
        "summary": "Read an authorized app image",
        "description": "App managers may read draft artwork. Other members must have catalog access and the image must belong to the approved published snapshot. Media is served with no-store headers.",
        "tags": [
          "Applications"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application UUID.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "assetId",
            "in": "path",
            "required": true,
            "description": "Image UUID.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "thumbnail",
            "in": "query",
            "description": "Use 1 to read the optimized thumbnail.",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized WebP image.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}/build-registries": {
      "get": {
        "operationId": "listBuildRegistries",
        "summary": "List private package access",
        "tags": [
          "Releases"
        ],
        "description": "Lists configured package scopes for an app manager. Credentials and encrypted envelopes are never returned.",
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configured registries without credentials.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "registries": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Opaque server-assigned identifier. Do not construct one."
                          },
                          "registryHost": {
                            "type": "string"
                          },
                          "packageScope": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "RFC 3339 timestamp, always UTC."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      },
      "post": {
        "operationId": "saveBuildRegistry",
        "summary": "Save private package read access",
        "tags": [
          "Releases"
        ],
        "description": "App managers can add or rotate an encrypted read token for an npm or GitHub Packages namespace. Only GET/HEAD requests to that namespace receive credentials, outside the build VM. No token is passed to customer commands, job payloads or runtime settings. Requires the managed isolated builder. Configure the scope's registry in .npmrc without an authentication token.",
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Package namespace and its read credential.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "registryHost",
                  "packageScope",
                  "token"
                ],
                "additionalProperties": false,
                "properties": {
                  "registryHost": {
                    "type": "string",
                    "enum": [
                      "registry.npmjs.org",
                      "npm.pkg.github.com"
                    ]
                  },
                  "packageScope": {
                    "type": "string",
                    "pattern": "^@[a-z0-9][a-z0-9._-]{0,99}$"
                  },
                  "token": {
                    "type": "string",
                    "format": "password",
                    "writeOnly": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved metadata; no credential is returned.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "registryHost": {
                      "type": "string"
                    },
                    "packageScope": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}/build-registries/{credentialId}": {
      "delete": {
        "operationId": "removeBuildRegistry",
        "summary": "Remove private package access",
        "tags": [
          "Releases"
        ],
        "description": "Removes an app's saved package credential for future builds. A build already running may finish. Allowed for retired apps so credentials can still be removed.",
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "credentialId",
            "in": "path",
            "required": true,
            "description": "Saved package credential id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Package access removed.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "removed": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}/source-import": {
      "post": {
        "operationId": "importGitHubSource",
        "summary": "Import a fixed GitHub source snapshot",
        "tags": [
          "Releases"
        ],
        "description": "Imports an authorized private or public repository at a resolved commit, then selects the stored files for the application's next release. The GitHub token is used only for this request; it is never persisted or passed to a builder. Running deployments are unchanged. Submodules, Git LFS and private package authentication are not resolved.",
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Repository, revision and a repository-scoped read credential.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "repositoryUrl",
                  "ref",
                  "token"
                ],
                "additionalProperties": false,
                "properties": {
                  "repositoryUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "ref": {
                    "type": "string",
                    "description": "Branch, tag or full commit SHA."
                  },
                  "token": {
                    "type": "string",
                    "format": "password",
                    "writeOnly": true,
                    "description": "GitHub fine-grained token with Contents: read permission for this repository."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The existing snapshot was selected.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "bundle",
                    "created",
                    "repositoryUrl",
                    "revision",
                    "warnings"
                  ],
                  "properties": {
                    "bundle": {
                      "type": "object",
                      "required": [
                        "bundleId",
                        "applicationId",
                        "digest",
                        "format",
                        "sizeBytes",
                        "fileCount",
                        "createdAt",
                        "createdByActorType"
                      ],
                      "properties": {
                        "bundleId": {
                          "type": "string",
                          "description": "Opaque server-assigned identifier. Do not construct one."
                        },
                        "applicationId": {
                          "type": "string",
                          "description": "Opaque server-assigned identifier. Do not construct one."
                        },
                        "digest": {
                          "type": "string"
                        },
                        "format": {
                          "type": "string",
                          "enum": [
                            "filemap"
                          ]
                        },
                        "sizeBytes": {
                          "type": "integer"
                        },
                        "fileCount": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "RFC 3339 timestamp, always UTC."
                        },
                        "createdByActorType": {
                          "type": "string"
                        }
                      }
                    },
                    "created": {
                      "type": "boolean"
                    },
                    "repositoryUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "revision": {
                      "type": "string",
                      "pattern": "^[a-f0-9]{40}$"
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "The source snapshot was stored and selected.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "bundle",
                    "created",
                    "repositoryUrl",
                    "revision",
                    "warnings"
                  ],
                  "properties": {
                    "bundle": {
                      "type": "object",
                      "required": [
                        "bundleId",
                        "applicationId",
                        "digest",
                        "format",
                        "sizeBytes",
                        "fileCount",
                        "createdAt",
                        "createdByActorType"
                      ],
                      "properties": {
                        "bundleId": {
                          "type": "string",
                          "description": "Opaque server-assigned identifier. Do not construct one."
                        },
                        "applicationId": {
                          "type": "string",
                          "description": "Opaque server-assigned identifier. Do not construct one."
                        },
                        "digest": {
                          "type": "string"
                        },
                        "format": {
                          "type": "string",
                          "enum": [
                            "filemap"
                          ]
                        },
                        "sizeBytes": {
                          "type": "integer"
                        },
                        "fileCount": {
                          "type": "integer"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "RFC 3339 timestamp, always UTC."
                        },
                        "createdByActorType": {
                          "type": "string"
                        }
                      }
                    },
                    "created": {
                      "type": "boolean"
                    },
                    "repositoryUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "revision": {
                      "type": "string",
                      "pattern": "^[a-f0-9]{40}$"
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}/bundles": {
      "get": {
        "operationId": "listBundles",
        "summary": "List releases",
        "description": "Immutable releases for this application, newest first.",
        "tags": [
          "Releases"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum records to return.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Records to skip.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of releases.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "total",
                    "items"
                  ],
                  "properties": {
                    "total": {
                      "type": "integer",
                      "description": "Total matching records, ignoring limit and offset."
                    },
                    "items": {
                      "type": "array",
                      "description": "The releases.",
                      "items": {
                        "type": "object",
                        "description": "An immutable release. Once created its contents and digest never change, which is what makes a promotion auditable.",
                        "required": [
                          "id",
                          "digest"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Opaque server-assigned identifier. Do not construct one."
                          },
                          "digest": {
                            "type": "string",
                            "description": "Content hash of the uploaded archive. Verify this rather than trusting the id."
                          },
                          "version": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "RFC 3339 timestamp, always UTC."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      },
      "post": {
        "operationId": "createBundle",
        "summary": "Create a release",
        "description": "Uploads an archive and freezes it as an immutable release with a content digest. Nothing about it can change afterwards; a later promotion references this release rather than rebuilding.",
        "tags": [
          "Releases"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Replays safely: the same key with the same body returns the original result, and with a different body returns IDEMPOTENCY_CONFLICT. Send one on every write an agent might retry.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The release to freeze.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "archive"
                ],
                "properties": {
                  "archive": {
                    "type": "string",
                    "description": "Base64-encoded tar archive of the built application."
                  },
                  "version": {
                    "type": "string",
                    "description": "Your own version label."
                  },
                  "manifest": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "The application manifest, apiVersion springboard.dev/v1alpha1."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The frozen release.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "An immutable release. Once created its contents and digest never change, which is what makes a promotion auditable.",
                  "required": [
                    "id",
                    "digest"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "digest": {
                      "type": "string",
                      "description": "Content hash of the uploaded archive. Verify this rather than trusting the id."
                    },
                    "version": {
                      "type": "string"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "501": {
            "$ref": "#/components/responses/Error501"
          },
          "502": {
            "$ref": "#/components/responses/Error502"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}/bundles/{bundleId}/files/{path}": {
      "get": {
        "operationId": "getBundleFile",
        "summary": "Read a file from a release",
        "description": "Serves one file out of a frozen release. Useful for verifying what was actually deployed rather than what a branch currently contains.",
        "tags": [
          "Releases"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bundleId",
            "in": "path",
            "required": true,
            "description": "Release id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "path",
            "in": "path",
            "required": true,
            "description": "Path inside the archive. May contain slashes.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The file, with the content type inferred from its extension.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}/placement": {
      "get": {
        "operationId": "getPlacement",
        "summary": "Where an application runs",
        "description": "The current placement of every environment of this application, and any pending migration recommendation. Recommendations ride along with the placements rather than living at their own URL, because they are only ever read in the context of where an application is now, and a separate endpoint would mean a client that forgot to call it never learned a cheaper option existed.",
        "tags": [
          "Deployments"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Placements and recommendations.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "applicationId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "environments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "environmentType": {
                            "type": "string",
                            "enum": [
                              "development",
                              "uat",
                              "production"
                            ]
                          },
                          "environmentId": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "placement": {
                            "type": "object",
                            "description": "Where SpringRoll decided to run this application, and why. Null for an application on a runtime the organization configured for itself, and for every deployment that predates automatic placement.",
                            "properties": {
                              "references": {
                                "type": "object",
                                "description": "Immutable references for the decision, independent recommendation, and exact managed runtime configuration.",
                                "properties": {
                                  "decisionId": {
                                    "type": "string",
                                    "format": "uuid"
                                  },
                                  "recommendationId": {
                                    "type": "string",
                                    "format": "uuid",
                                    "nullable": true
                                  },
                                  "runtimeConfigurationId": {
                                    "type": "string",
                                    "format": "uuid",
                                    "nullable": true
                                  }
                                }
                              },
                              "recommended": {
                                "type": "object",
                                "properties": {
                                  "provider": {
                                    "type": "string",
                                    "enum": [
                                      "vercel",
                                      "cloudflare"
                                    ]
                                  },
                                  "providerName": {
                                    "type": "string"
                                  },
                                  "plan": {
                                    "type": "string"
                                  },
                                  "planName": {
                                    "type": "string"
                                  }
                                }
                              },
                              "executed": {
                                "type": "object",
                                "properties": {
                                  "provider": {
                                    "type": "string",
                                    "enum": [
                                      "vercel",
                                      "cloudflare"
                                    ]
                                  },
                                  "providerName": {
                                    "type": "string"
                                  },
                                  "plan": {
                                    "type": "string"
                                  },
                                  "planName": {
                                    "type": "string"
                                  },
                                  "runtimeConfigurationId": {
                                    "type": "string",
                                    "format": "uuid",
                                    "nullable": true
                                  }
                                }
                              },
                              "provider": {
                                "type": "string",
                                "description": "Provider identifier."
                              },
                              "providerName": {
                                "type": "string",
                                "description": "Provider name, for display."
                              },
                              "plan": {
                                "type": "string",
                                "description": "The plan on that provider."
                              },
                              "servedByInstead": {
                                "type": "object",
                                "nullable": true,
                                "description": "Historical compatibility only. New deployments never switch providers without a new approved placement decision.",
                                "properties": {
                                  "provider": {
                                    "type": "string"
                                  },
                                  "providerName": {
                                    "type": "string"
                                  }
                                }
                              },
                              "free": {
                                "type": "boolean",
                                "description": "True when adding this application to the account costs nothing more. It means the marginal cost is known to be zero, not that the plan has a zero price and not that the numbers were unreadable."
                              },
                              "estimatedMonthlyCost": {
                                "type": "object",
                                "nullable": true,
                                "description": "What adding this application costs beyond the subscription SpringRoll already pays. A range, never a single number: a metered plan's bill depends on traffic nobody has measured yet, and one figure gets quoted back as a price. Null when the cost could not be worked out at all.",
                                "properties": {
                                  "minUsd": {
                                    "type": "number"
                                  },
                                  "maxUsd": {
                                    "type": "number"
                                  },
                                  "currency": {
                                    "type": "string"
                                  },
                                  "confidence": {
                                    "type": "string",
                                    "enum": [
                                      "HIGH",
                                      "MEDIUM",
                                      "LOW",
                                      "UNKNOWN"
                                    ],
                                    "description": "How much the estimate is worth. There is no path to HIGH on a first placement."
                                  },
                                  "confidenceMeans": {
                                    "type": "string"
                                  }
                                }
                              },
                              "bestAvailable": {
                                "type": "boolean",
                                "description": "Whether SpringRoll will stand behind the claim that this is the best available placement. False when the price list was stale or the plan's price could not be read. The placement still happened; the superlative did not survive."
                              },
                              "pricing": {
                                "type": "object",
                                "description": "The price list this decision was scored against, so it can be replayed.",
                                "properties": {
                                  "version": {
                                    "type": "string"
                                  },
                                  "stale": {
                                    "type": "boolean"
                                  }
                                }
                              },
                              "meterBreakdown": {
                                "type": "array",
                                "description": "Request, bandwidth, compute, memory, storage, and build evidence behind the estimate. An incomplete required meter prevents a lowest-cost claim.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "meter": {
                                      "type": "string",
                                      "enum": [
                                        "requests",
                                        "bandwidth",
                                        "compute",
                                        "memory",
                                        "storage",
                                        "build",
                                        "database",
                                        "cache",
                                        "storage-operations"
                                      ]
                                    },
                                    "required": {
                                      "type": "boolean"
                                    },
                                    "expectedUsage": {
                                      "type": "number",
                                      "nullable": true
                                    },
                                    "unit": {
                                      "type": "string"
                                    },
                                    "includedUsage": {
                                      "nullable": true
                                    },
                                    "excessUsage": {
                                      "type": "number",
                                      "nullable": true
                                    },
                                    "rateUsd": {
                                      "type": "number",
                                      "nullable": true
                                    },
                                    "rateUnit": {
                                      "type": "string",
                                      "nullable": true
                                    },
                                    "estimatedCostUsd": {
                                      "type": "number",
                                      "nullable": true
                                    },
                                    "complete": {
                                      "type": "boolean"
                                    },
                                    "limitation": {
                                      "type": "string",
                                      "nullable": true
                                    }
                                  }
                                }
                              },
                              "pricingSources": {
                                "type": "array",
                                "description": "Public evidence frozen with the catalog version, including observation and effective dates.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "kind": {
                                      "type": "string",
                                      "enum": [
                                        "pricing",
                                        "terms"
                                      ]
                                    },
                                    "url": {
                                      "type": "string",
                                      "format": "uri"
                                    },
                                    "observedAt": {
                                      "type": "string",
                                      "format": "date-time",
                                      "nullable": true
                                    },
                                    "effectiveAt": {
                                      "type": "string",
                                      "format": "date-time",
                                      "nullable": true
                                    }
                                  }
                                }
                              },
                              "limitations": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "decidedBy": {
                                "type": "object",
                                "properties": {
                                  "source": {
                                    "type": "string",
                                    "enum": [
                                      "AUTOMATIC",
                                      "ADMIN_OVERRIDE",
                                      "LEGACY_BACKFILL",
                                      "MIGRATION"
                                    ]
                                  },
                                  "means": {
                                    "type": "string"
                                  }
                                }
                              },
                              "assumptions": {
                                "type": "array",
                                "description": "One entry per field SpringRoll had to guess, with the evidence it used. A value the caller declared never appears here, so a reader can always tell measurement from inference.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "field": {
                                      "type": "string"
                                    },
                                    "value": {
                                      "type": "string"
                                    },
                                    "because": {
                                      "type": "string"
                                    }
                                  }
                                }
                              },
                              "limits": {
                                "type": "array",
                                "description": "Every way this plan is worse than paying: sleeping when idle, stopping at a usage cap, cold starts, no backups, no availability commitment. Tell the user these before they rely on the application.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "kind": {
                                      "type": "string"
                                    },
                                    "means": {
                                      "type": "string"
                                    },
                                    "detail": {
                                      "type": "string"
                                    }
                                  }
                                }
                              },
                              "notChosen": {
                                "type": "array",
                                "description": "Every candidate that lost, with the first reason it lost. This is the half that makes the receipt an argument a reader can check rather than an assertion, so it is worth rendering rather than ignoring.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "provider": {
                                      "type": "string"
                                    },
                                    "plan": {
                                      "type": "string"
                                    },
                                    "reason": {
                                      "type": "string",
                                      "enum": [
                                        "TERMS_INELIGIBLE",
                                        "UNSUITABLE_ENVIRONMENT",
                                        "NO_MANAGED_CAPACITY",
                                        "RUNTIME_UNSUPPORTED",
                                        "UNMET_REQUIREMENT",
                                        "UNSUPPORTED_SOURCE",
                                        "INVALID_REGION",
                                        "DATA_POLICY_CONFLICT",
                                        "OVER_BUDGET"
                                      ]
                                    },
                                    "means": {
                                      "type": "string"
                                    },
                                    "detail": {
                                      "type": "string"
                                    }
                                  }
                                }
                              },
                              "billingOwner": {
                                "type": "object",
                                "description": "Who pays the provider for the plan this receipt describes. Released placements use SpringRoll-managed Vercel and Cloudflare accounts.",
                                "properties": {
                                  "owner": {
                                    "type": "string",
                                    "enum": [
                                      "SPRINGROLL",
                                      "CUSTOMER"
                                    ]
                                  },
                                  "means": {
                                    "type": "string"
                                  }
                                }
                              },
                              "recommendedInstead": {
                                "type": "object",
                                "nullable": true,
                                "description": "Historical compatibility only. New placements bind recommendation and execution to the same exact managed target.",
                                "properties": {
                                  "provider": {
                                    "type": "string"
                                  },
                                  "providerName": {
                                    "type": "string"
                                  },
                                  "plan": {
                                    "type": "string"
                                  },
                                  "planName": {
                                    "type": "string"
                                  },
                                  "readiness": {
                                    "type": "string",
                                    "enum": [
                                      "managed_ready",
                                      "managed_activation_required",
                                      "connection_required",
                                      "connected",
                                      "upgrade_required",
                                      "verified",
                                      "deployable",
                                      "invalid_connection",
                                      "unavailable"
                                    ]
                                  },
                                  "means": {
                                    "type": "string"
                                  },
                                  "action": {
                                    "type": "string",
                                    "nullable": true,
                                    "description": "What makes the recommended plan deployable, when something does."
                                  }
                                }
                              },
                              "executionReadiness": {
                                "type": "object",
                                "description": "Whether this organization could execute a deployment onto the described plan when the receipt was written. An action vocabulary, not a verdict: connection_required means connect an account to deploy, never rejected. On a recorded deployment this is always an executable state, because a decision only ever binds a target that could actually deploy.",
                                "properties": {
                                  "state": {
                                    "type": "string",
                                    "enum": [
                                      "managed_ready",
                                      "managed_activation_required",
                                      "connection_required",
                                      "connected",
                                      "upgrade_required",
                                      "verified",
                                      "deployable",
                                      "invalid_connection",
                                      "unavailable"
                                    ]
                                  },
                                  "means": {
                                    "type": "string"
                                  },
                                  "action": {
                                    "type": "string",
                                    "nullable": true
                                  }
                                }
                              },
                              "alternatives": {
                                "type": "array",
                                "description": "Ranked also-eligible active Vercel and Cloudflare plans, best first. Managed-account readiness never removes or reorders an entry, and it cannot promote an alternative into execution.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "provider": {
                                      "type": "string"
                                    },
                                    "providerName": {
                                      "type": "string"
                                    },
                                    "plan": {
                                      "type": "string"
                                    },
                                    "planName": {
                                      "type": "string"
                                    },
                                    "free": {
                                      "type": "boolean"
                                    },
                                    "estimatedMonthlyCost": {
                                      "type": "object",
                                      "nullable": true,
                                      "properties": {
                                        "minUsd": {
                                          "type": "number"
                                        },
                                        "maxUsd": {
                                          "type": "number"
                                        }
                                      }
                                    },
                                    "eligibility": {
                                      "type": "string",
                                      "enum": [
                                        "eligible",
                                        "ineligible",
                                        "unknown",
                                        "quote_required"
                                      ]
                                    },
                                    "billingOwner": {
                                      "type": "string",
                                      "enum": [
                                        "SPRINGROLL",
                                        "CUSTOMER"
                                      ]
                                    },
                                    "readiness": {
                                      "type": "string",
                                      "enum": [
                                        "managed_ready",
                                        "managed_activation_required",
                                        "connection_required",
                                        "connected",
                                        "upgrade_required",
                                        "verified",
                                        "deployable",
                                        "invalid_connection",
                                        "unavailable"
                                      ]
                                    },
                                    "action": {
                                      "type": "string",
                                      "nullable": true
                                    },
                                    "meterBreakdown": {
                                      "type": "array",
                                      "items": {
                                        "type": "object"
                                      }
                                    },
                                    "billingProjection": {
                                      "type": "object",
                                      "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                                      "required": [
                                        "version",
                                        "basis",
                                        "components",
                                        "unmodeledCharges"
                                      ],
                                      "properties": {
                                        "version": {
                                          "type": "integer",
                                          "enum": [
                                            1
                                          ]
                                        },
                                        "basis": {
                                          "type": "string",
                                          "enum": [
                                            "monthly-usage-before-allowances-and-credits"
                                          ]
                                        },
                                        "builderBackend": {
                                          "type": "string",
                                          "enum": [
                                            "vercel-sandbox",
                                            "external"
                                          ],
                                          "description": "Build service used when the cost snapshot was calculated."
                                        },
                                        "artifactStore": {
                                          "type": "string",
                                          "enum": [
                                            "vercel-blob",
                                            "filesystem",
                                            "unknown"
                                          ],
                                          "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                                        },
                                        "components": {
                                          "type": "array",
                                          "items": {
                                            "type": "object",
                                            "properties": {
                                              "key": {
                                                "type": "string"
                                              },
                                              "label": {
                                                "type": "string"
                                              },
                                              "unit": {
                                                "type": "string"
                                              },
                                              "billingScope": {
                                                "type": "string",
                                                "enum": [
                                                  "vercel-infrastructure",
                                                  "neon-integration",
                                                  "upstash-integration",
                                                  "cloudflare-account",
                                                  "external-or-unverified"
                                                ],
                                                "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                                              },
                                              "expectedUsage": {
                                                "type": [
                                                  "number",
                                                  "null"
                                                ]
                                              },
                                              "rateMinUsd": {
                                                "type": [
                                                  "number",
                                                  "null"
                                                ]
                                              },
                                              "rateMaxUsd": {
                                                "type": [
                                                  "number",
                                                  "null"
                                                ]
                                              },
                                              "grossMinUsd": {
                                                "type": [
                                                  "number",
                                                  "null"
                                                ]
                                              },
                                              "grossMaxUsd": {
                                                "type": [
                                                  "number",
                                                  "null"
                                                ]
                                              },
                                              "observedAt": {
                                                "type": [
                                                  "string",
                                                  "null"
                                                ],
                                                "format": "date-time"
                                              },
                                              "source": {
                                                "type": "string",
                                                "format": "uri"
                                              },
                                              "limitation": {
                                                "type": [
                                                  "string",
                                                  "null"
                                                ]
                                              }
                                            }
                                          }
                                        },
                                        "unmodeledCharges": {
                                          "type": "array",
                                          "items": {
                                            "type": "string"
                                          }
                                        }
                                      }
                                    },
                                    "pricingSources": {
                                      "type": "array",
                                      "items": {
                                        "type": "object"
                                      }
                                    },
                                    "limitations": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "migrationRecommendations": {
                      "type": "array",
                      "description": "Proposed moves that cleared both thresholds: at least 20 percent and at least 5 US dollars a month, with no loss of compliance. An administrator has to approve one before anything moves.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "environmentId": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "toProvider": {
                            "type": "string"
                          },
                          "toPlan": {
                            "type": "string"
                          },
                          "currentUsdPerMonth": {
                            "type": "number"
                          },
                          "candidateUsdPerMonth": {
                            "type": "number"
                          },
                          "savingUsdPerMonth": {
                            "type": "number"
                          },
                          "savingFraction": {
                            "type": "number"
                          },
                          "status": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      },
      "post": {
        "operationId": "previewPlacement",
        "summary": "Preview where an application would run",
        "description": "Scores a placement without writing anything. It shares its implementation with the deploy path, so what it returns is what a deploy would actually do. Use it to put runtime fit, cost range, confidence, assumptions, limitations, evidence dates, and rejected alternatives in front of a person before deploying. Vercel and Cloudflare are SpringRoll-managed; provider credentials never enter the request or response. POST rather than GET because the hints are a structured body; it writes nothing.",
        "tags": [
          "Deployments"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "description": "Which environment to score for, and any hints.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "environmentType": {
                    "type": "string",
                    "enum": [
                      "development",
                      "uat",
                      "production"
                    ],
                    "default": "production"
                  },
                  "placement": {
                    "type": "object",
                    "description": "Optional hints about what this application needs. SpringRoll chooses the provider and plan; these only inform that choice. Omitted monthly billing quantities remain unknown; ordinary workload hints are inferred from the source and named on the receipt.",
                    "properties": {
                      "monthlyUsage": {
                        "type": "object",
                        "properties": {
                          "worker": {
                            "type": "object",
                            "properties": {
                              "dispatchRequests": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Workers for Platforms billable dispatch-chain requests, not all HTTP requests or sampled Worker analytics."
                              },
                              "cpuMilliseconds": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Billable Worker CPU milliseconds, separate from container vCPU time."
                              }
                            },
                            "additionalProperties": false
                          },
                          "runtime": {
                            "type": "object",
                            "properties": {
                              "activeCpuHours": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Total active CPU-hours across runtime instances. Excludes idle and I/O wait; not allocated vCPU multiplied by elapsed time."
                              },
                              "provisionedMemoryGbHours": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Total billable provisioned memory GB-hours, including billable wait time across all runtime instances."
                              },
                              "invocations": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Billable function invocations per month; distinct from edge HTTP requests."
                              },
                              "originTransferGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Monthly GB transferred between the origin and edge; distinct from internet egress."
                              }
                            },
                            "additionalProperties": false
                          },
                          "build": {
                            "type": "object",
                            "properties": {
                              "minutes": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Build minutes for products billed per minute. Does not substitute for Sandbox CPU or memory usage."
                              },
                              "activeCpuHours": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Total active CPU-hours across all isolated builds in the month."
                              },
                              "provisionedMemoryGbHours": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Total billed build memory GB-hours, including provider minimum duration and rounding."
                              },
                              "starts": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Number of isolated build environments created during the month."
                              },
                              "dataTransferGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Monthly build data transfer in billable GB."
                              },
                              "registryStorageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Container image storage retained in the selected runtime provider's registry, averaged over the month in GB-months. Include all retained revisions, not just the newest image; exclude private build-artifact storage."
                              },
                              "artifactStorageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Private immutable build outputs retained by SpringRoll, averaged over the month in GB-months. Include all retained build revisions, including OCI layouts; exclude provider-registry images and customer object storage."
                              },
                              "artifactSimpleOperations": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed simple operations on private build artifacts, such as HEAD; do not infer this from build starts."
                              },
                              "artifactAdvancedOperations": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed advanced operations on private build artifacts, including uploads and multipart parts; do not infer this from build starts."
                              },
                              "artifactDataTransferGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed GB transferred when private build artifacts are read; separate from Sandbox build transfer and customer file delivery."
                              }
                            },
                            "additionalProperties": false
                          },
                          "container": {
                            "type": "object",
                            "properties": {
                              "billedVcpuSeconds": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare container active vCPU-seconds after the provider's 10ms billing increments, separate from provisioned memory and disk time."
                              },
                              "billedMemoryGibSeconds": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare container allocated GiB-seconds after provider billing increments."
                              },
                              "billedDiskGbSeconds": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare container allocated disk GB-seconds after provider billing increments; local disk remains ephemeral."
                              },
                              "egressNaEuGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare container egress GB delivered to North America or Europe."
                              },
                              "egressOceaniaKoreaTaiwanGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare container egress GB delivered to Oceania, Korea or Taiwan."
                              },
                              "egressOtherGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare container egress GB delivered to other destinations."
                              }
                            },
                            "additionalProperties": false
                          },
                          "database": {
                            "type": "object",
                            "properties": {
                              "computeCuHours": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Monthly database compute-unit hours, distinct from application CPU-hours."
                              },
                              "storageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Database storage averaged over the month, in GB-months."
                              },
                              "restoreHistoryGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Neon Instant Restore change history retained over the month, in GB-months; separate from database storage."
                              },
                              "extraBranchMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Neon branch-months above the plan's simultaneous included branch allowance, prorated for partial months; do not count included branches."
                              },
                              "extraBranchHours": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Neon billed branch-hours above the plan's simultaneous included branch allowance. The rate varies with the billing month's length; do not also provide extraBranchMonths."
                              },
                              "snapshotStorageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Neon manual or scheduled snapshot storage averaged over the month, in GB-months; separate from database storage and restore history."
                              },
                              "publicDataTransferGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Neon public network egress in GB for the month, including the per-project included quantity; separate from application and object delivery."
                              },
                              "rowsRead": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Database rows scanned, including provider-billed index reads; not rows returned or SQL query count."
                              },
                              "rowsWritten": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Database rows written, including provider-billed index writes; not SQL query count."
                              }
                            },
                            "additionalProperties": false
                          },
                          "cache": {
                            "type": "object",
                            "properties": {
                              "commands": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed cache commands per month, including realtime polling and internal commands."
                              },
                              "storageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cache storage averaged over the month in GB-months, including replicas and read regions; separate from database and object storage."
                              },
                              "dataTransferGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed cache bandwidth in GB per month, including replication traffic; separate from app and object delivery."
                              }
                            },
                            "additionalProperties": false
                          },
                          "durableObject": {
                            "type": "object",
                            "properties": {
                              "billableRequests": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Durable Object billable request units, including metered WebSocket messages where applicable."
                              },
                              "durationGbSeconds": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Durable Object billable GB-seconds, separate from container allocation."
                              },
                              "rowsRead": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Durable Object SQLite rows read, including billed index scans."
                              },
                              "rowsWritten": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Durable Object SQLite rows written, including billed index writes."
                              },
                              "storageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Durable Object SQLite storage GB-months."
                              }
                            },
                            "additionalProperties": false
                          },
                          "kv": {
                            "type": "object",
                            "properties": {
                              "reads": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Workers KV billable reads, including application routing reads."
                              },
                              "writes": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Workers KV billable writes, including application routing updates."
                              },
                              "deletes": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Workers KV billable deletes."
                              },
                              "lists": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Workers KV billable list operations."
                              },
                              "storageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Workers KV storage GB-months used by this application."
                              }
                            },
                            "additionalProperties": false
                          },
                          "objectStorage": {
                            "type": "object",
                            "properties": {
                              "storageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Object storage averaged over the month, in GB-months. Separate from local disk and database storage."
                              },
                              "simpleOperations": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed simple object operations per month (for example Blob reads)."
                              },
                              "advancedOperations": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed advanced object operations per month (for example Blob writes and lists)."
                              },
                              "dataTransferGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Billable object delivery GB per month, separate from application and build transfer."
                              }
                            },
                            "additionalProperties": false
                          }
                        },
                        "additionalProperties": false,
                        "description": "Optional expected monthly billing quantities. Missing values remain unknown; zero is explicit. On redeploy the supplied object replaces the previous forecast; omit it to retain the forecast. Resource sizes do not establish CPU time or memory duration."
                      },
                      "needs": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "enum": [
                            "static",
                            "serverless",
                            "server",
                            "container",
                            "database",
                            "postgres",
                            "auth",
                            "storage",
                            "realtime",
                            "edge-functions"
                          ]
                        },
                        "description": "Everything the application needs, in one list: at most one workload shape, plus any services it needs beside its own code. A provider that cannot supply an entry is excluded."
                      },
                      "expectedRequestsPerMonth": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "expectedBandwidthGb": {
                        "type": "number",
                        "minimum": 0
                      },
                      "computeVcpu": {
                        "type": "number",
                        "minimum": 0
                      },
                      "memoryMb": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "storageGb": {
                        "type": "number",
                        "minimum": 0
                      },
                      "region": {
                        "type": "string"
                      },
                      "coldStartTolerant": {
                        "type": "boolean"
                      },
                      "needsWebSockets": {
                        "type": "boolean"
                      },
                      "needsBackgroundWork": {
                        "type": "boolean"
                      },
                      "needsPersistentDisk": {
                        "type": "boolean"
                      },
                      "productionCritical": {
                        "type": "boolean"
                      },
                      "budgetUsdPerMonth": {
                        "type": "number",
                        "minimum": 0,
                        "description": "A real ceiling, if there is one. Omit it otherwise: a budget of zero that nobody asked for would exclude every qualified plan with a non-zero estimate."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "What a deploy would choose.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "applicationId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "environmentType": {
                      "type": "string",
                      "enum": [
                        "development",
                        "uat",
                        "production"
                      ]
                    },
                    "placement": {
                      "type": "object",
                      "description": "Where SpringRoll decided to run this application, and why. Null for an application on a runtime the organization configured for itself, and for every deployment that predates automatic placement.",
                      "properties": {
                        "references": {
                          "type": "object",
                          "description": "Immutable references for the decision, independent recommendation, and exact managed runtime configuration.",
                          "properties": {
                            "decisionId": {
                              "type": "string",
                              "format": "uuid"
                            },
                            "recommendationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            },
                            "runtimeConfigurationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            }
                          }
                        },
                        "recommended": {
                          "type": "object",
                          "properties": {
                            "provider": {
                              "type": "string",
                              "enum": [
                                "vercel",
                                "cloudflare"
                              ]
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            }
                          }
                        },
                        "executed": {
                          "type": "object",
                          "properties": {
                            "provider": {
                              "type": "string",
                              "enum": [
                                "vercel",
                                "cloudflare"
                              ]
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            },
                            "runtimeConfigurationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            }
                          }
                        },
                        "provider": {
                          "type": "string",
                          "description": "Provider identifier."
                        },
                        "providerName": {
                          "type": "string",
                          "description": "Provider name, for display."
                        },
                        "plan": {
                          "type": "string",
                          "description": "The plan on that provider."
                        },
                        "servedByInstead": {
                          "type": "object",
                          "nullable": true,
                          "description": "Historical compatibility only. New deployments never switch providers without a new approved placement decision.",
                          "properties": {
                            "provider": {
                              "type": "string"
                            },
                            "providerName": {
                              "type": "string"
                            }
                          }
                        },
                        "free": {
                          "type": "boolean",
                          "description": "True when adding this application to the account costs nothing more. It means the marginal cost is known to be zero, not that the plan has a zero price and not that the numbers were unreadable."
                        },
                        "estimatedMonthlyCost": {
                          "type": "object",
                          "nullable": true,
                          "description": "What adding this application costs beyond the subscription SpringRoll already pays. A range, never a single number: a metered plan's bill depends on traffic nobody has measured yet, and one figure gets quoted back as a price. Null when the cost could not be worked out at all.",
                          "properties": {
                            "minUsd": {
                              "type": "number"
                            },
                            "maxUsd": {
                              "type": "number"
                            },
                            "currency": {
                              "type": "string"
                            },
                            "confidence": {
                              "type": "string",
                              "enum": [
                                "HIGH",
                                "MEDIUM",
                                "LOW",
                                "UNKNOWN"
                              ],
                              "description": "How much the estimate is worth. There is no path to HIGH on a first placement."
                            },
                            "confidenceMeans": {
                              "type": "string"
                            }
                          }
                        },
                        "bestAvailable": {
                          "type": "boolean",
                          "description": "Whether SpringRoll will stand behind the claim that this is the best available placement. False when the price list was stale or the plan's price could not be read. The placement still happened; the superlative did not survive."
                        },
                        "pricing": {
                          "type": "object",
                          "description": "The price list this decision was scored against, so it can be replayed.",
                          "properties": {
                            "version": {
                              "type": "string"
                            },
                            "stale": {
                              "type": "boolean"
                            }
                          }
                        },
                        "meterBreakdown": {
                          "type": "array",
                          "description": "Request, bandwidth, compute, memory, storage, and build evidence behind the estimate. An incomplete required meter prevents a lowest-cost claim.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "meter": {
                                "type": "string",
                                "enum": [
                                  "requests",
                                  "bandwidth",
                                  "compute",
                                  "memory",
                                  "storage",
                                  "build",
                                  "database",
                                  "cache",
                                  "storage-operations"
                                ]
                              },
                              "required": {
                                "type": "boolean"
                              },
                              "expectedUsage": {
                                "type": "number",
                                "nullable": true
                              },
                              "unit": {
                                "type": "string"
                              },
                              "includedUsage": {
                                "nullable": true
                              },
                              "excessUsage": {
                                "type": "number",
                                "nullable": true
                              },
                              "rateUsd": {
                                "type": "number",
                                "nullable": true
                              },
                              "rateUnit": {
                                "type": "string",
                                "nullable": true
                              },
                              "estimatedCostUsd": {
                                "type": "number",
                                "nullable": true
                              },
                              "complete": {
                                "type": "boolean"
                              },
                              "limitation": {
                                "type": "string",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "pricingSources": {
                          "type": "array",
                          "description": "Public evidence frozen with the catalog version, including observation and effective dates.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "pricing",
                                  "terms"
                                ]
                              },
                              "url": {
                                "type": "string",
                                "format": "uri"
                              },
                              "observedAt": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                              },
                              "effectiveAt": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "limitations": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "decidedBy": {
                          "type": "object",
                          "properties": {
                            "source": {
                              "type": "string",
                              "enum": [
                                "AUTOMATIC",
                                "ADMIN_OVERRIDE",
                                "LEGACY_BACKFILL",
                                "MIGRATION"
                              ]
                            },
                            "means": {
                              "type": "string"
                            }
                          }
                        },
                        "assumptions": {
                          "type": "array",
                          "description": "One entry per field SpringRoll had to guess, with the evidence it used. A value the caller declared never appears here, so a reader can always tell measurement from inference.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string"
                              },
                              "value": {
                                "type": "string"
                              },
                              "because": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "limits": {
                          "type": "array",
                          "description": "Every way this plan is worse than paying: sleeping when idle, stopping at a usage cap, cold starts, no backups, no availability commitment. Tell the user these before they rely on the application.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string"
                              },
                              "means": {
                                "type": "string"
                              },
                              "detail": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "notChosen": {
                          "type": "array",
                          "description": "Every candidate that lost, with the first reason it lost. This is the half that makes the receipt an argument a reader can check rather than an assertion, so it is worth rendering rather than ignoring.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "provider": {
                                "type": "string"
                              },
                              "plan": {
                                "type": "string"
                              },
                              "reason": {
                                "type": "string",
                                "enum": [
                                  "TERMS_INELIGIBLE",
                                  "UNSUITABLE_ENVIRONMENT",
                                  "NO_MANAGED_CAPACITY",
                                  "RUNTIME_UNSUPPORTED",
                                  "UNMET_REQUIREMENT",
                                  "UNSUPPORTED_SOURCE",
                                  "INVALID_REGION",
                                  "DATA_POLICY_CONFLICT",
                                  "OVER_BUDGET"
                                ]
                              },
                              "means": {
                                "type": "string"
                              },
                              "detail": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "billingOwner": {
                          "type": "object",
                          "description": "Who pays the provider for the plan this receipt describes. Released placements use SpringRoll-managed Vercel and Cloudflare accounts.",
                          "properties": {
                            "owner": {
                              "type": "string",
                              "enum": [
                                "SPRINGROLL",
                                "CUSTOMER"
                              ]
                            },
                            "means": {
                              "type": "string"
                            }
                          }
                        },
                        "recommendedInstead": {
                          "type": "object",
                          "nullable": true,
                          "description": "Historical compatibility only. New placements bind recommendation and execution to the same exact managed target.",
                          "properties": {
                            "provider": {
                              "type": "string"
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            },
                            "readiness": {
                              "type": "string",
                              "enum": [
                                "managed_ready",
                                "managed_activation_required",
                                "connection_required",
                                "connected",
                                "upgrade_required",
                                "verified",
                                "deployable",
                                "invalid_connection",
                                "unavailable"
                              ]
                            },
                            "means": {
                              "type": "string"
                            },
                            "action": {
                              "type": "string",
                              "nullable": true,
                              "description": "What makes the recommended plan deployable, when something does."
                            }
                          }
                        },
                        "executionReadiness": {
                          "type": "object",
                          "description": "Whether this organization could execute a deployment onto the described plan when the receipt was written. An action vocabulary, not a verdict: connection_required means connect an account to deploy, never rejected. On a recorded deployment this is always an executable state, because a decision only ever binds a target that could actually deploy.",
                          "properties": {
                            "state": {
                              "type": "string",
                              "enum": [
                                "managed_ready",
                                "managed_activation_required",
                                "connection_required",
                                "connected",
                                "upgrade_required",
                                "verified",
                                "deployable",
                                "invalid_connection",
                                "unavailable"
                              ]
                            },
                            "means": {
                              "type": "string"
                            },
                            "action": {
                              "type": "string",
                              "nullable": true
                            }
                          }
                        },
                        "alternatives": {
                          "type": "array",
                          "description": "Ranked also-eligible active Vercel and Cloudflare plans, best first. Managed-account readiness never removes or reorders an entry, and it cannot promote an alternative into execution.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "provider": {
                                "type": "string"
                              },
                              "providerName": {
                                "type": "string"
                              },
                              "plan": {
                                "type": "string"
                              },
                              "planName": {
                                "type": "string"
                              },
                              "free": {
                                "type": "boolean"
                              },
                              "estimatedMonthlyCost": {
                                "type": "object",
                                "nullable": true,
                                "properties": {
                                  "minUsd": {
                                    "type": "number"
                                  },
                                  "maxUsd": {
                                    "type": "number"
                                  }
                                }
                              },
                              "eligibility": {
                                "type": "string",
                                "enum": [
                                  "eligible",
                                  "ineligible",
                                  "unknown",
                                  "quote_required"
                                ]
                              },
                              "billingOwner": {
                                "type": "string",
                                "enum": [
                                  "SPRINGROLL",
                                  "CUSTOMER"
                                ]
                              },
                              "readiness": {
                                "type": "string",
                                "enum": [
                                  "managed_ready",
                                  "managed_activation_required",
                                  "connection_required",
                                  "connected",
                                  "upgrade_required",
                                  "verified",
                                  "deployable",
                                  "invalid_connection",
                                  "unavailable"
                                ]
                              },
                              "action": {
                                "type": "string",
                                "nullable": true
                              },
                              "meterBreakdown": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                }
                              },
                              "billingProjection": {
                                "type": "object",
                                "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                                "required": [
                                  "version",
                                  "basis",
                                  "components",
                                  "unmodeledCharges"
                                ],
                                "properties": {
                                  "version": {
                                    "type": "integer",
                                    "enum": [
                                      1
                                    ]
                                  },
                                  "basis": {
                                    "type": "string",
                                    "enum": [
                                      "monthly-usage-before-allowances-and-credits"
                                    ]
                                  },
                                  "builderBackend": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-sandbox",
                                      "external"
                                    ],
                                    "description": "Build service used when the cost snapshot was calculated."
                                  },
                                  "artifactStore": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-blob",
                                      "filesystem",
                                      "unknown"
                                    ],
                                    "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                                  },
                                  "components": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "key": {
                                          "type": "string"
                                        },
                                        "label": {
                                          "type": "string"
                                        },
                                        "unit": {
                                          "type": "string"
                                        },
                                        "billingScope": {
                                          "type": "string",
                                          "enum": [
                                            "vercel-infrastructure",
                                            "neon-integration",
                                            "upstash-integration",
                                            "cloudflare-account",
                                            "external-or-unverified"
                                          ],
                                          "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                                        },
                                        "expectedUsage": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "rateMinUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "rateMaxUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "grossMinUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "grossMaxUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "observedAt": {
                                          "type": [
                                            "string",
                                            "null"
                                          ],
                                          "format": "date-time"
                                        },
                                        "source": {
                                          "type": "string",
                                          "format": "uri"
                                        },
                                        "limitation": {
                                          "type": [
                                            "string",
                                            "null"
                                          ]
                                        }
                                      }
                                    }
                                  },
                                  "unmodeledCharges": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  }
                                }
                              },
                              "pricingSources": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                }
                              },
                              "limitations": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "workload": {
                      "type": "object",
                      "description": "Every field resolved, declared or inferred. Read it alongside the receipt's assumptions to see which was which."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/migration-recommendations/{recommendationId}": {
      "post": {
        "operationId": "decideMigrationRecommendation",
        "summary": "Approve or reject a provider migration",
        "description": "A production placement is sticky, and this is the only door out of it. SpringRoll re-scores placements on a schedule and raises a recommendation when a move clears both thresholds, but moving a running application between providers is not something an optimizer gets to do on a saving. Approving records consent; the move itself then goes through the ordinary deployment path, so it is policy-checked, audited, and can be rolled back. A rejection needs a note, because the next person to see the same recommendation has to know why it was turned down rather than re-deriving it.",
        "tags": [
          "Deployments"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "recommendationId",
            "in": "path",
            "required": true,
            "description": "Migration recommendation id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The decision.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "decision"
                ],
                "properties": {
                  "decision": {
                    "type": "string",
                    "enum": [
                      "APPROVE",
                      "REJECT"
                    ]
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 1000,
                    "description": "Required when rejecting."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The decision, recorded.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "recommendationId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "APPROVED",
                        "REJECTED"
                      ]
                    },
                    "nextActions": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}/deployments": {
      "get": {
        "operationId": "listDeployments",
        "summary": "List deployments",
        "description": "Deployments of this application across every environment, newest first.",
        "tags": [
          "Deployments"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "required": false,
            "description": "Restrict to one environment.",
            "schema": {
              "type": "string",
              "enum": [
                "development",
                "uat",
                "production"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum records to return.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Records to skip.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of deployments.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "total",
                    "items"
                  ],
                  "properties": {
                    "total": {
                      "type": "integer",
                      "description": "Total matching records, ignoring limit and offset."
                    },
                    "items": {
                      "type": "array",
                      "description": "The deployments.",
                      "items": {
                        "type": "object",
                        "description": "One deployment of one immutable release into one environment.",
                        "required": [
                          "id",
                          "environment",
                          "status"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Opaque server-assigned identifier. Do not construct one."
                          },
                          "applicationId": {
                            "type": "string",
                            "description": "Opaque server-assigned identifier. Do not construct one."
                          },
                          "bundleId": {
                            "type": "string",
                            "description": "The immutable release that was deployed. Promotion reuses this rather than rebuilding."
                          },
                          "environment": {
                            "type": "string",
                            "enum": [
                              "development",
                              "uat",
                              "production"
                            ],
                            "description": "Which environment this deployment serves."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "QUEUED",
                              "VALIDATING",
                              "BUILDING",
                              "DEPLOYING",
                              "READY",
                              "FAILED",
                              "CANCELLED",
                              "SUPERSEDED",
                              "ROLLED_BACK"
                            ],
                            "description": "Lifecycle of the deployment attempt itself, not of the application."
                          },
                          "url": {
                            "type": "string",
                            "format": "uri",
                            "description": "The live URL, once the deployment is serving. Absent until then."
                          },
                          "placement": {
                            "type": "object",
                            "description": "Where SpringRoll decided to run this application, and why. Null for an application on a runtime the organization configured for itself, and for every deployment that predates automatic placement.",
                            "properties": {
                              "references": {
                                "type": "object",
                                "description": "Immutable references for the decision, independent recommendation, and exact managed runtime configuration.",
                                "properties": {
                                  "decisionId": {
                                    "type": "string",
                                    "format": "uuid"
                                  },
                                  "recommendationId": {
                                    "type": "string",
                                    "format": "uuid",
                                    "nullable": true
                                  },
                                  "runtimeConfigurationId": {
                                    "type": "string",
                                    "format": "uuid",
                                    "nullable": true
                                  }
                                }
                              },
                              "recommended": {
                                "type": "object",
                                "properties": {
                                  "provider": {
                                    "type": "string",
                                    "enum": [
                                      "vercel",
                                      "cloudflare"
                                    ]
                                  },
                                  "providerName": {
                                    "type": "string"
                                  },
                                  "plan": {
                                    "type": "string"
                                  },
                                  "planName": {
                                    "type": "string"
                                  }
                                }
                              },
                              "executed": {
                                "type": "object",
                                "properties": {
                                  "provider": {
                                    "type": "string",
                                    "enum": [
                                      "vercel",
                                      "cloudflare"
                                    ]
                                  },
                                  "providerName": {
                                    "type": "string"
                                  },
                                  "plan": {
                                    "type": "string"
                                  },
                                  "planName": {
                                    "type": "string"
                                  },
                                  "runtimeConfigurationId": {
                                    "type": "string",
                                    "format": "uuid",
                                    "nullable": true
                                  }
                                }
                              },
                              "provider": {
                                "type": "string",
                                "description": "Provider identifier."
                              },
                              "providerName": {
                                "type": "string",
                                "description": "Provider name, for display."
                              },
                              "plan": {
                                "type": "string",
                                "description": "The plan on that provider."
                              },
                              "servedByInstead": {
                                "type": "object",
                                "nullable": true,
                                "description": "Historical compatibility only. New deployments never switch providers without a new approved placement decision.",
                                "properties": {
                                  "provider": {
                                    "type": "string"
                                  },
                                  "providerName": {
                                    "type": "string"
                                  }
                                }
                              },
                              "free": {
                                "type": "boolean",
                                "description": "True when adding this application to the account costs nothing more. It means the marginal cost is known to be zero, not that the plan has a zero price and not that the numbers were unreadable."
                              },
                              "estimatedMonthlyCost": {
                                "type": "object",
                                "nullable": true,
                                "description": "What adding this application costs beyond the subscription SpringRoll already pays. A range, never a single number: a metered plan's bill depends on traffic nobody has measured yet, and one figure gets quoted back as a price. Null when the cost could not be worked out at all.",
                                "properties": {
                                  "minUsd": {
                                    "type": "number"
                                  },
                                  "maxUsd": {
                                    "type": "number"
                                  },
                                  "currency": {
                                    "type": "string"
                                  },
                                  "confidence": {
                                    "type": "string",
                                    "enum": [
                                      "HIGH",
                                      "MEDIUM",
                                      "LOW",
                                      "UNKNOWN"
                                    ],
                                    "description": "How much the estimate is worth. There is no path to HIGH on a first placement."
                                  },
                                  "confidenceMeans": {
                                    "type": "string"
                                  }
                                }
                              },
                              "bestAvailable": {
                                "type": "boolean",
                                "description": "Whether SpringRoll will stand behind the claim that this is the best available placement. False when the price list was stale or the plan's price could not be read. The placement still happened; the superlative did not survive."
                              },
                              "pricing": {
                                "type": "object",
                                "description": "The price list this decision was scored against, so it can be replayed.",
                                "properties": {
                                  "version": {
                                    "type": "string"
                                  },
                                  "stale": {
                                    "type": "boolean"
                                  }
                                }
                              },
                              "meterBreakdown": {
                                "type": "array",
                                "description": "Request, bandwidth, compute, memory, storage, and build evidence behind the estimate. An incomplete required meter prevents a lowest-cost claim.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "meter": {
                                      "type": "string",
                                      "enum": [
                                        "requests",
                                        "bandwidth",
                                        "compute",
                                        "memory",
                                        "storage",
                                        "build",
                                        "database",
                                        "cache",
                                        "storage-operations"
                                      ]
                                    },
                                    "required": {
                                      "type": "boolean"
                                    },
                                    "expectedUsage": {
                                      "type": "number",
                                      "nullable": true
                                    },
                                    "unit": {
                                      "type": "string"
                                    },
                                    "includedUsage": {
                                      "nullable": true
                                    },
                                    "excessUsage": {
                                      "type": "number",
                                      "nullable": true
                                    },
                                    "rateUsd": {
                                      "type": "number",
                                      "nullable": true
                                    },
                                    "rateUnit": {
                                      "type": "string",
                                      "nullable": true
                                    },
                                    "estimatedCostUsd": {
                                      "type": "number",
                                      "nullable": true
                                    },
                                    "complete": {
                                      "type": "boolean"
                                    },
                                    "limitation": {
                                      "type": "string",
                                      "nullable": true
                                    }
                                  }
                                }
                              },
                              "pricingSources": {
                                "type": "array",
                                "description": "Public evidence frozen with the catalog version, including observation and effective dates.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "kind": {
                                      "type": "string",
                                      "enum": [
                                        "pricing",
                                        "terms"
                                      ]
                                    },
                                    "url": {
                                      "type": "string",
                                      "format": "uri"
                                    },
                                    "observedAt": {
                                      "type": "string",
                                      "format": "date-time",
                                      "nullable": true
                                    },
                                    "effectiveAt": {
                                      "type": "string",
                                      "format": "date-time",
                                      "nullable": true
                                    }
                                  }
                                }
                              },
                              "limitations": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "decidedBy": {
                                "type": "object",
                                "properties": {
                                  "source": {
                                    "type": "string",
                                    "enum": [
                                      "AUTOMATIC",
                                      "ADMIN_OVERRIDE",
                                      "LEGACY_BACKFILL",
                                      "MIGRATION"
                                    ]
                                  },
                                  "means": {
                                    "type": "string"
                                  }
                                }
                              },
                              "assumptions": {
                                "type": "array",
                                "description": "One entry per field SpringRoll had to guess, with the evidence it used. A value the caller declared never appears here, so a reader can always tell measurement from inference.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "field": {
                                      "type": "string"
                                    },
                                    "value": {
                                      "type": "string"
                                    },
                                    "because": {
                                      "type": "string"
                                    }
                                  }
                                }
                              },
                              "limits": {
                                "type": "array",
                                "description": "Every way this plan is worse than paying: sleeping when idle, stopping at a usage cap, cold starts, no backups, no availability commitment. Tell the user these before they rely on the application.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "kind": {
                                      "type": "string"
                                    },
                                    "means": {
                                      "type": "string"
                                    },
                                    "detail": {
                                      "type": "string"
                                    }
                                  }
                                }
                              },
                              "notChosen": {
                                "type": "array",
                                "description": "Every candidate that lost, with the first reason it lost. This is the half that makes the receipt an argument a reader can check rather than an assertion, so it is worth rendering rather than ignoring.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "provider": {
                                      "type": "string"
                                    },
                                    "plan": {
                                      "type": "string"
                                    },
                                    "reason": {
                                      "type": "string",
                                      "enum": [
                                        "TERMS_INELIGIBLE",
                                        "UNSUITABLE_ENVIRONMENT",
                                        "NO_MANAGED_CAPACITY",
                                        "RUNTIME_UNSUPPORTED",
                                        "UNMET_REQUIREMENT",
                                        "UNSUPPORTED_SOURCE",
                                        "INVALID_REGION",
                                        "DATA_POLICY_CONFLICT",
                                        "OVER_BUDGET"
                                      ]
                                    },
                                    "means": {
                                      "type": "string"
                                    },
                                    "detail": {
                                      "type": "string"
                                    }
                                  }
                                }
                              },
                              "billingOwner": {
                                "type": "object",
                                "description": "Who pays the provider for the plan this receipt describes. Released placements use SpringRoll-managed Vercel and Cloudflare accounts.",
                                "properties": {
                                  "owner": {
                                    "type": "string",
                                    "enum": [
                                      "SPRINGROLL",
                                      "CUSTOMER"
                                    ]
                                  },
                                  "means": {
                                    "type": "string"
                                  }
                                }
                              },
                              "recommendedInstead": {
                                "type": "object",
                                "nullable": true,
                                "description": "Historical compatibility only. New placements bind recommendation and execution to the same exact managed target.",
                                "properties": {
                                  "provider": {
                                    "type": "string"
                                  },
                                  "providerName": {
                                    "type": "string"
                                  },
                                  "plan": {
                                    "type": "string"
                                  },
                                  "planName": {
                                    "type": "string"
                                  },
                                  "readiness": {
                                    "type": "string",
                                    "enum": [
                                      "managed_ready",
                                      "managed_activation_required",
                                      "connection_required",
                                      "connected",
                                      "upgrade_required",
                                      "verified",
                                      "deployable",
                                      "invalid_connection",
                                      "unavailable"
                                    ]
                                  },
                                  "means": {
                                    "type": "string"
                                  },
                                  "action": {
                                    "type": "string",
                                    "nullable": true,
                                    "description": "What makes the recommended plan deployable, when something does."
                                  }
                                }
                              },
                              "executionReadiness": {
                                "type": "object",
                                "description": "Whether this organization could execute a deployment onto the described plan when the receipt was written. An action vocabulary, not a verdict: connection_required means connect an account to deploy, never rejected. On a recorded deployment this is always an executable state, because a decision only ever binds a target that could actually deploy.",
                                "properties": {
                                  "state": {
                                    "type": "string",
                                    "enum": [
                                      "managed_ready",
                                      "managed_activation_required",
                                      "connection_required",
                                      "connected",
                                      "upgrade_required",
                                      "verified",
                                      "deployable",
                                      "invalid_connection",
                                      "unavailable"
                                    ]
                                  },
                                  "means": {
                                    "type": "string"
                                  },
                                  "action": {
                                    "type": "string",
                                    "nullable": true
                                  }
                                }
                              },
                              "alternatives": {
                                "type": "array",
                                "description": "Ranked also-eligible active Vercel and Cloudflare plans, best first. Managed-account readiness never removes or reorders an entry, and it cannot promote an alternative into execution.",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "provider": {
                                      "type": "string"
                                    },
                                    "providerName": {
                                      "type": "string"
                                    },
                                    "plan": {
                                      "type": "string"
                                    },
                                    "planName": {
                                      "type": "string"
                                    },
                                    "free": {
                                      "type": "boolean"
                                    },
                                    "estimatedMonthlyCost": {
                                      "type": "object",
                                      "nullable": true,
                                      "properties": {
                                        "minUsd": {
                                          "type": "number"
                                        },
                                        "maxUsd": {
                                          "type": "number"
                                        }
                                      }
                                    },
                                    "eligibility": {
                                      "type": "string",
                                      "enum": [
                                        "eligible",
                                        "ineligible",
                                        "unknown",
                                        "quote_required"
                                      ]
                                    },
                                    "billingOwner": {
                                      "type": "string",
                                      "enum": [
                                        "SPRINGROLL",
                                        "CUSTOMER"
                                      ]
                                    },
                                    "readiness": {
                                      "type": "string",
                                      "enum": [
                                        "managed_ready",
                                        "managed_activation_required",
                                        "connection_required",
                                        "connected",
                                        "upgrade_required",
                                        "verified",
                                        "deployable",
                                        "invalid_connection",
                                        "unavailable"
                                      ]
                                    },
                                    "action": {
                                      "type": "string",
                                      "nullable": true
                                    },
                                    "meterBreakdown": {
                                      "type": "array",
                                      "items": {
                                        "type": "object"
                                      }
                                    },
                                    "billingProjection": {
                                      "type": "object",
                                      "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                                      "required": [
                                        "version",
                                        "basis",
                                        "components",
                                        "unmodeledCharges"
                                      ],
                                      "properties": {
                                        "version": {
                                          "type": "integer",
                                          "enum": [
                                            1
                                          ]
                                        },
                                        "basis": {
                                          "type": "string",
                                          "enum": [
                                            "monthly-usage-before-allowances-and-credits"
                                          ]
                                        },
                                        "builderBackend": {
                                          "type": "string",
                                          "enum": [
                                            "vercel-sandbox",
                                            "external"
                                          ],
                                          "description": "Build service used when the cost snapshot was calculated."
                                        },
                                        "artifactStore": {
                                          "type": "string",
                                          "enum": [
                                            "vercel-blob",
                                            "filesystem",
                                            "unknown"
                                          ],
                                          "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                                        },
                                        "components": {
                                          "type": "array",
                                          "items": {
                                            "type": "object",
                                            "properties": {
                                              "key": {
                                                "type": "string"
                                              },
                                              "label": {
                                                "type": "string"
                                              },
                                              "unit": {
                                                "type": "string"
                                              },
                                              "billingScope": {
                                                "type": "string",
                                                "enum": [
                                                  "vercel-infrastructure",
                                                  "neon-integration",
                                                  "upstash-integration",
                                                  "cloudflare-account",
                                                  "external-or-unverified"
                                                ],
                                                "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                                              },
                                              "expectedUsage": {
                                                "type": [
                                                  "number",
                                                  "null"
                                                ]
                                              },
                                              "rateMinUsd": {
                                                "type": [
                                                  "number",
                                                  "null"
                                                ]
                                              },
                                              "rateMaxUsd": {
                                                "type": [
                                                  "number",
                                                  "null"
                                                ]
                                              },
                                              "grossMinUsd": {
                                                "type": [
                                                  "number",
                                                  "null"
                                                ]
                                              },
                                              "grossMaxUsd": {
                                                "type": [
                                                  "number",
                                                  "null"
                                                ]
                                              },
                                              "observedAt": {
                                                "type": [
                                                  "string",
                                                  "null"
                                                ],
                                                "format": "date-time"
                                              },
                                              "source": {
                                                "type": "string",
                                                "format": "uri"
                                              },
                                              "limitation": {
                                                "type": [
                                                  "string",
                                                  "null"
                                                ]
                                              }
                                            }
                                          }
                                        },
                                        "unmodeledCharges": {
                                          "type": "array",
                                          "items": {
                                            "type": "string"
                                          }
                                        }
                                      }
                                    },
                                    "pricingSources": {
                                      "type": "array",
                                      "items": {
                                        "type": "object"
                                      }
                                    },
                                    "limitations": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      }
                                    }
                                  }
                                }
                              }
                            }
                          },
                          "provisionedCapabilities": {
                            "type": "object",
                            "description": "Safe runtime capability metadata. Credentials and provider account identifiers are never included.",
                            "properties": {
                              "billingProjection": {
                                "type": "object",
                                "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                                "required": [
                                  "version",
                                  "basis",
                                  "components",
                                  "unmodeledCharges"
                                ],
                                "properties": {
                                  "version": {
                                    "type": "integer",
                                    "enum": [
                                      1
                                    ]
                                  },
                                  "basis": {
                                    "type": "string",
                                    "enum": [
                                      "monthly-usage-before-allowances-and-credits"
                                    ]
                                  },
                                  "builderBackend": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-sandbox",
                                      "external"
                                    ],
                                    "description": "Build service used when the cost snapshot was calculated."
                                  },
                                  "artifactStore": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-blob",
                                      "filesystem",
                                      "unknown"
                                    ],
                                    "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                                  },
                                  "components": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "key": {
                                          "type": "string"
                                        },
                                        "label": {
                                          "type": "string"
                                        },
                                        "unit": {
                                          "type": "string"
                                        },
                                        "billingScope": {
                                          "type": "string",
                                          "enum": [
                                            "vercel-infrastructure",
                                            "neon-integration",
                                            "upstash-integration",
                                            "cloudflare-account",
                                            "external-or-unverified"
                                          ],
                                          "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                                        },
                                        "expectedUsage": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "rateMinUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "rateMaxUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "grossMinUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "grossMaxUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "observedAt": {
                                          "type": [
                                            "string",
                                            "null"
                                          ],
                                          "format": "date-time"
                                        },
                                        "source": {
                                          "type": "string",
                                          "format": "uri"
                                        },
                                        "limitation": {
                                          "type": [
                                            "string",
                                            "null"
                                          ]
                                        }
                                      }
                                    }
                                  },
                                  "unmodeledCharges": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  }
                                }
                              },
                              "billing": {
                                "type": "object",
                                "description": "Observed plans for this application's data resources, frozen at deployment. No usage totals or credentials.",
                                "additionalProperties": {
                                  "type": "object",
                                  "required": [
                                    "version",
                                    "product",
                                    "planId",
                                    "scope",
                                    "observedAt",
                                    "currency",
                                    "rates",
                                    "includedCommandsPerMonth",
                                    "source"
                                  ],
                                  "properties": {
                                    "version": {
                                      "type": "integer",
                                      "enum": [
                                        1
                                      ]
                                    },
                                    "product": {
                                      "type": "string",
                                      "enum": [
                                        "neon",
                                        "upstash-kv"
                                      ]
                                    },
                                    "planId": {
                                      "type": "string",
                                      "enum": [
                                        "launch_v3",
                                        "free",
                                        "paid"
                                      ]
                                    },
                                    "scope": {
                                      "type": "string",
                                      "enum": [
                                        "installation",
                                        "resource"
                                      ]
                                    },
                                    "observedAt": {
                                      "type": "string",
                                      "format": "date-time"
                                    },
                                    "currency": {
                                      "type": "string",
                                      "enum": [
                                        "USD"
                                      ]
                                    },
                                    "rates": {
                                      "type": "object",
                                      "properties": {
                                        "perCuHourUsd": {
                                          "type": "number",
                                          "minimum": 0
                                        },
                                        "perGbMonthUsd": {
                                          "type": "number",
                                          "minimum": 0
                                        },
                                        "per100kCommandsUsd": {
                                          "type": "number",
                                          "minimum": 0
                                        }
                                      }
                                    },
                                    "includedCommandsPerMonth": {
                                      "type": [
                                        "integer",
                                        "null"
                                      ],
                                      "minimum": 0
                                    },
                                    "source": {
                                      "type": "string",
                                      "format": "uri"
                                    }
                                  }
                                }
                              },
                              "storage": {
                                "type": "object",
                                "required": [
                                  "kind",
                                  "access",
                                  "scope",
                                  "baseUrl"
                                ],
                                "properties": {
                                  "kind": {
                                    "type": "string",
                                    "enum": [
                                      "object-storage"
                                    ]
                                  },
                                  "access": {
                                    "type": "string",
                                    "enum": [
                                      "public"
                                    ]
                                  },
                                  "scope": {
                                    "type": "string",
                                    "enum": [
                                      "application"
                                    ]
                                  },
                                  "baseUrl": {
                                    "type": "string",
                                    "format": "uri"
                                  },
                                  "binding": {
                                    "type": "string",
                                    "enum": [
                                      "STORAGE"
                                    ]
                                  },
                                  "containerEndpointVariable": {
                                    "type": "string",
                                    "enum": [
                                      "SPRINGROLL_CONTAINER_STORAGE_URL"
                                    ]
                                  }
                                }
                              },
                              "database": {
                                "type": "object",
                                "required": [
                                  "kind",
                                  "scope",
                                  "engine",
                                  "connection"
                                ],
                                "properties": {
                                  "kind": {
                                    "type": "string",
                                    "enum": [
                                      "database"
                                    ]
                                  },
                                  "scope": {
                                    "type": "string",
                                    "enum": [
                                      "application"
                                    ]
                                  },
                                  "engine": {
                                    "type": "string",
                                    "enum": [
                                      "postgres",
                                      "sqlite"
                                    ]
                                  },
                                  "connection": {
                                    "type": "string",
                                    "enum": [
                                      "environment",
                                      "binding"
                                    ]
                                  },
                                  "variable": {
                                    "type": "string",
                                    "enum": [
                                      "DATABASE_URL"
                                    ]
                                  },
                                  "binding": {
                                    "type": "string",
                                    "enum": [
                                      "DB"
                                    ]
                                  },
                                  "containerEndpointVariable": {
                                    "type": "string",
                                    "enum": [
                                      "SPRINGROLL_CONTAINER_DATABASE_URL"
                                    ]
                                  }
                                }
                              }
                            }
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "RFC 3339 timestamp, always UTC."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      },
      "post": {
        "operationId": "createDeployment",
        "summary": "Deploy a release",
        "description": "Deploys a frozen release into an environment. Direct to Production is the default posture, so this often returns a live URL without a person being involved; a staged organization answers 409 with APPROVAL_REQUIRED and an approval request id instead. Readiness, ownership, support, access, data, configuration, scan, authorization, and provider checks apply either way.",
        "tags": [
          "Deployments"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Replays safely: the same key with the same body returns the original result, and with a different body returns IDEMPOTENCY_CONFLICT. Send one on every write an agent might retry.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "What to deploy, and where. Every field is optional.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "environmentType": {
                    "type": "string",
                    "enum": [
                      "development",
                      "uat",
                      "production"
                    ],
                    "description": "Target environment. Defaults to what the application's Deployment workflow starts with: production for Direct, development for Staged."
                  },
                  "releaseId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "A frozen release to deploy. Defaults to building one from the application's current source."
                  },
                  "ref": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Git branch, tag, or commit to build, for a git-sourced application. Defaults to the application's default revision."
                  },
                  "placement": {
                    "type": "object",
                    "description": "Optional hints about what this application needs. SpringRoll chooses the provider and plan; these only inform that choice. Omitted monthly billing quantities remain unknown; ordinary workload hints are inferred from the source and named on the receipt.",
                    "properties": {
                      "monthlyUsage": {
                        "type": "object",
                        "properties": {
                          "worker": {
                            "type": "object",
                            "properties": {
                              "dispatchRequests": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Workers for Platforms billable dispatch-chain requests, not all HTTP requests or sampled Worker analytics."
                              },
                              "cpuMilliseconds": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Billable Worker CPU milliseconds, separate from container vCPU time."
                              }
                            },
                            "additionalProperties": false
                          },
                          "runtime": {
                            "type": "object",
                            "properties": {
                              "activeCpuHours": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Total active CPU-hours across runtime instances. Excludes idle and I/O wait; not allocated vCPU multiplied by elapsed time."
                              },
                              "provisionedMemoryGbHours": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Total billable provisioned memory GB-hours, including billable wait time across all runtime instances."
                              },
                              "invocations": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Billable function invocations per month; distinct from edge HTTP requests."
                              },
                              "originTransferGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Monthly GB transferred between the origin and edge; distinct from internet egress."
                              }
                            },
                            "additionalProperties": false
                          },
                          "build": {
                            "type": "object",
                            "properties": {
                              "minutes": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Build minutes for products billed per minute. Does not substitute for Sandbox CPU or memory usage."
                              },
                              "activeCpuHours": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Total active CPU-hours across all isolated builds in the month."
                              },
                              "provisionedMemoryGbHours": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Total billed build memory GB-hours, including provider minimum duration and rounding."
                              },
                              "starts": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Number of isolated build environments created during the month."
                              },
                              "dataTransferGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Monthly build data transfer in billable GB."
                              },
                              "registryStorageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Container image storage retained in the selected runtime provider's registry, averaged over the month in GB-months. Include all retained revisions, not just the newest image; exclude private build-artifact storage."
                              },
                              "artifactStorageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Private immutable build outputs retained by SpringRoll, averaged over the month in GB-months. Include all retained build revisions, including OCI layouts; exclude provider-registry images and customer object storage."
                              },
                              "artifactSimpleOperations": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed simple operations on private build artifacts, such as HEAD; do not infer this from build starts."
                              },
                              "artifactAdvancedOperations": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed advanced operations on private build artifacts, including uploads and multipart parts; do not infer this from build starts."
                              },
                              "artifactDataTransferGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed GB transferred when private build artifacts are read; separate from Sandbox build transfer and customer file delivery."
                              }
                            },
                            "additionalProperties": false
                          },
                          "container": {
                            "type": "object",
                            "properties": {
                              "billedVcpuSeconds": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare container active vCPU-seconds after the provider's 10ms billing increments, separate from provisioned memory and disk time."
                              },
                              "billedMemoryGibSeconds": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare container allocated GiB-seconds after provider billing increments."
                              },
                              "billedDiskGbSeconds": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare container allocated disk GB-seconds after provider billing increments; local disk remains ephemeral."
                              },
                              "egressNaEuGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare container egress GB delivered to North America or Europe."
                              },
                              "egressOceaniaKoreaTaiwanGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare container egress GB delivered to Oceania, Korea or Taiwan."
                              },
                              "egressOtherGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare container egress GB delivered to other destinations."
                              }
                            },
                            "additionalProperties": false
                          },
                          "database": {
                            "type": "object",
                            "properties": {
                              "computeCuHours": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Monthly database compute-unit hours, distinct from application CPU-hours."
                              },
                              "storageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Database storage averaged over the month, in GB-months."
                              },
                              "restoreHistoryGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Neon Instant Restore change history retained over the month, in GB-months; separate from database storage."
                              },
                              "extraBranchMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Neon branch-months above the plan's simultaneous included branch allowance, prorated for partial months; do not count included branches."
                              },
                              "extraBranchHours": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Neon billed branch-hours above the plan's simultaneous included branch allowance. The rate varies with the billing month's length; do not also provide extraBranchMonths."
                              },
                              "snapshotStorageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Neon manual or scheduled snapshot storage averaged over the month, in GB-months; separate from database storage and restore history."
                              },
                              "publicDataTransferGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Neon public network egress in GB for the month, including the per-project included quantity; separate from application and object delivery."
                              },
                              "rowsRead": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Database rows scanned, including provider-billed index reads; not rows returned or SQL query count."
                              },
                              "rowsWritten": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Database rows written, including provider-billed index writes; not SQL query count."
                              }
                            },
                            "additionalProperties": false
                          },
                          "cache": {
                            "type": "object",
                            "properties": {
                              "commands": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed cache commands per month, including realtime polling and internal commands."
                              },
                              "storageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cache storage averaged over the month in GB-months, including replicas and read regions; separate from database and object storage."
                              },
                              "dataTransferGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed cache bandwidth in GB per month, including replication traffic; separate from app and object delivery."
                              }
                            },
                            "additionalProperties": false
                          },
                          "durableObject": {
                            "type": "object",
                            "properties": {
                              "billableRequests": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Durable Object billable request units, including metered WebSocket messages where applicable."
                              },
                              "durationGbSeconds": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Durable Object billable GB-seconds, separate from container allocation."
                              },
                              "rowsRead": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Durable Object SQLite rows read, including billed index scans."
                              },
                              "rowsWritten": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Durable Object SQLite rows written, including billed index writes."
                              },
                              "storageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Durable Object SQLite storage GB-months."
                              }
                            },
                            "additionalProperties": false
                          },
                          "kv": {
                            "type": "object",
                            "properties": {
                              "reads": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Workers KV billable reads, including application routing reads."
                              },
                              "writes": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Workers KV billable writes, including application routing updates."
                              },
                              "deletes": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Workers KV billable deletes."
                              },
                              "lists": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Workers KV billable list operations."
                              },
                              "storageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Cloudflare Workers KV storage GB-months used by this application."
                              }
                            },
                            "additionalProperties": false
                          },
                          "objectStorage": {
                            "type": "object",
                            "properties": {
                              "storageGbMonths": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Object storage averaged over the month, in GB-months. Separate from local disk and database storage."
                              },
                              "simpleOperations": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed simple object operations per month (for example Blob reads)."
                              },
                              "advancedOperations": {
                                "type": "integer",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Provider-billed advanced object operations per month (for example Blob writes and lists)."
                              },
                              "dataTransferGb": {
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1000000000000000,
                                "description": "Billable object delivery GB per month, separate from application and build transfer."
                              }
                            },
                            "additionalProperties": false
                          }
                        },
                        "additionalProperties": false,
                        "description": "Optional expected monthly billing quantities. Missing values remain unknown; zero is explicit. On redeploy the supplied object replaces the previous forecast; omit it to retain the forecast. Resource sizes do not establish CPU time or memory duration."
                      },
                      "needs": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "enum": [
                            "static",
                            "serverless",
                            "server",
                            "container",
                            "database",
                            "postgres",
                            "auth",
                            "storage",
                            "realtime",
                            "edge-functions"
                          ]
                        },
                        "description": "Everything the application needs, in one list: at most one workload shape, plus any services it needs beside its own code. A provider that cannot supply an entry is excluded."
                      },
                      "expectedRequestsPerMonth": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "expectedBandwidthGb": {
                        "type": "number",
                        "minimum": 0
                      },
                      "computeVcpu": {
                        "type": "number",
                        "minimum": 0
                      },
                      "memoryMb": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "storageGb": {
                        "type": "number",
                        "minimum": 0
                      },
                      "region": {
                        "type": "string"
                      },
                      "coldStartTolerant": {
                        "type": "boolean"
                      },
                      "needsWebSockets": {
                        "type": "boolean"
                      },
                      "needsBackgroundWork": {
                        "type": "boolean"
                      },
                      "needsPersistentDisk": {
                        "type": "boolean"
                      },
                      "productionCritical": {
                        "type": "boolean"
                      },
                      "budgetUsdPerMonth": {
                        "type": "number",
                        "minimum": 0,
                        "description": "A real ceiling, if there is one. Omit it otherwise: a budget of zero that nobody asked for would exclude every qualified plan with a non-zero estimate."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The deployment, which may still be building.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "One deployment of one immutable release into one environment.",
                  "required": [
                    "id",
                    "environment",
                    "status"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "applicationId": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "bundleId": {
                      "type": "string",
                      "description": "The immutable release that was deployed. Promotion reuses this rather than rebuilding."
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "development",
                        "uat",
                        "production"
                      ],
                      "description": "Which environment this deployment serves."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "QUEUED",
                        "VALIDATING",
                        "BUILDING",
                        "DEPLOYING",
                        "READY",
                        "FAILED",
                        "CANCELLED",
                        "SUPERSEDED",
                        "ROLLED_BACK"
                      ],
                      "description": "Lifecycle of the deployment attempt itself, not of the application."
                    },
                    "url": {
                      "type": "string",
                      "format": "uri",
                      "description": "The live URL, once the deployment is serving. Absent until then."
                    },
                    "placement": {
                      "type": "object",
                      "description": "Where SpringRoll decided to run this application, and why. Null for an application on a runtime the organization configured for itself, and for every deployment that predates automatic placement.",
                      "properties": {
                        "references": {
                          "type": "object",
                          "description": "Immutable references for the decision, independent recommendation, and exact managed runtime configuration.",
                          "properties": {
                            "decisionId": {
                              "type": "string",
                              "format": "uuid"
                            },
                            "recommendationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            },
                            "runtimeConfigurationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            }
                          }
                        },
                        "recommended": {
                          "type": "object",
                          "properties": {
                            "provider": {
                              "type": "string",
                              "enum": [
                                "vercel",
                                "cloudflare"
                              ]
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            }
                          }
                        },
                        "executed": {
                          "type": "object",
                          "properties": {
                            "provider": {
                              "type": "string",
                              "enum": [
                                "vercel",
                                "cloudflare"
                              ]
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            },
                            "runtimeConfigurationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            }
                          }
                        },
                        "provider": {
                          "type": "string",
                          "description": "Provider identifier."
                        },
                        "providerName": {
                          "type": "string",
                          "description": "Provider name, for display."
                        },
                        "plan": {
                          "type": "string",
                          "description": "The plan on that provider."
                        },
                        "servedByInstead": {
                          "type": "object",
                          "nullable": true,
                          "description": "Historical compatibility only. New deployments never switch providers without a new approved placement decision.",
                          "properties": {
                            "provider": {
                              "type": "string"
                            },
                            "providerName": {
                              "type": "string"
                            }
                          }
                        },
                        "free": {
                          "type": "boolean",
                          "description": "True when adding this application to the account costs nothing more. It means the marginal cost is known to be zero, not that the plan has a zero price and not that the numbers were unreadable."
                        },
                        "estimatedMonthlyCost": {
                          "type": "object",
                          "nullable": true,
                          "description": "What adding this application costs beyond the subscription SpringRoll already pays. A range, never a single number: a metered plan's bill depends on traffic nobody has measured yet, and one figure gets quoted back as a price. Null when the cost could not be worked out at all.",
                          "properties": {
                            "minUsd": {
                              "type": "number"
                            },
                            "maxUsd": {
                              "type": "number"
                            },
                            "currency": {
                              "type": "string"
                            },
                            "confidence": {
                              "type": "string",
                              "enum": [
                                "HIGH",
                                "MEDIUM",
                                "LOW",
                                "UNKNOWN"
                              ],
                              "description": "How much the estimate is worth. There is no path to HIGH on a first placement."
                            },
                            "confidenceMeans": {
                              "type": "string"
                            }
                          }
                        },
                        "bestAvailable": {
                          "type": "boolean",
                          "description": "Whether SpringRoll will stand behind the claim that this is the best available placement. False when the price list was stale or the plan's price could not be read. The placement still happened; the superlative did not survive."
                        },
                        "pricing": {
                          "type": "object",
                          "description": "The price list this decision was scored against, so it can be replayed.",
                          "properties": {
                            "version": {
                              "type": "string"
                            },
                            "stale": {
                              "type": "boolean"
                            }
                          }
                        },
                        "meterBreakdown": {
                          "type": "array",
                          "description": "Request, bandwidth, compute, memory, storage, and build evidence behind the estimate. An incomplete required meter prevents a lowest-cost claim.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "meter": {
                                "type": "string",
                                "enum": [
                                  "requests",
                                  "bandwidth",
                                  "compute",
                                  "memory",
                                  "storage",
                                  "build",
                                  "database",
                                  "cache",
                                  "storage-operations"
                                ]
                              },
                              "required": {
                                "type": "boolean"
                              },
                              "expectedUsage": {
                                "type": "number",
                                "nullable": true
                              },
                              "unit": {
                                "type": "string"
                              },
                              "includedUsage": {
                                "nullable": true
                              },
                              "excessUsage": {
                                "type": "number",
                                "nullable": true
                              },
                              "rateUsd": {
                                "type": "number",
                                "nullable": true
                              },
                              "rateUnit": {
                                "type": "string",
                                "nullable": true
                              },
                              "estimatedCostUsd": {
                                "type": "number",
                                "nullable": true
                              },
                              "complete": {
                                "type": "boolean"
                              },
                              "limitation": {
                                "type": "string",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "pricingSources": {
                          "type": "array",
                          "description": "Public evidence frozen with the catalog version, including observation and effective dates.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "pricing",
                                  "terms"
                                ]
                              },
                              "url": {
                                "type": "string",
                                "format": "uri"
                              },
                              "observedAt": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                              },
                              "effectiveAt": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "limitations": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "decidedBy": {
                          "type": "object",
                          "properties": {
                            "source": {
                              "type": "string",
                              "enum": [
                                "AUTOMATIC",
                                "ADMIN_OVERRIDE",
                                "LEGACY_BACKFILL",
                                "MIGRATION"
                              ]
                            },
                            "means": {
                              "type": "string"
                            }
                          }
                        },
                        "assumptions": {
                          "type": "array",
                          "description": "One entry per field SpringRoll had to guess, with the evidence it used. A value the caller declared never appears here, so a reader can always tell measurement from inference.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string"
                              },
                              "value": {
                                "type": "string"
                              },
                              "because": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "limits": {
                          "type": "array",
                          "description": "Every way this plan is worse than paying: sleeping when idle, stopping at a usage cap, cold starts, no backups, no availability commitment. Tell the user these before they rely on the application.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string"
                              },
                              "means": {
                                "type": "string"
                              },
                              "detail": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "notChosen": {
                          "type": "array",
                          "description": "Every candidate that lost, with the first reason it lost. This is the half that makes the receipt an argument a reader can check rather than an assertion, so it is worth rendering rather than ignoring.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "provider": {
                                "type": "string"
                              },
                              "plan": {
                                "type": "string"
                              },
                              "reason": {
                                "type": "string",
                                "enum": [
                                  "TERMS_INELIGIBLE",
                                  "UNSUITABLE_ENVIRONMENT",
                                  "NO_MANAGED_CAPACITY",
                                  "RUNTIME_UNSUPPORTED",
                                  "UNMET_REQUIREMENT",
                                  "UNSUPPORTED_SOURCE",
                                  "INVALID_REGION",
                                  "DATA_POLICY_CONFLICT",
                                  "OVER_BUDGET"
                                ]
                              },
                              "means": {
                                "type": "string"
                              },
                              "detail": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "billingOwner": {
                          "type": "object",
                          "description": "Who pays the provider for the plan this receipt describes. Released placements use SpringRoll-managed Vercel and Cloudflare accounts.",
                          "properties": {
                            "owner": {
                              "type": "string",
                              "enum": [
                                "SPRINGROLL",
                                "CUSTOMER"
                              ]
                            },
                            "means": {
                              "type": "string"
                            }
                          }
                        },
                        "recommendedInstead": {
                          "type": "object",
                          "nullable": true,
                          "description": "Historical compatibility only. New placements bind recommendation and execution to the same exact managed target.",
                          "properties": {
                            "provider": {
                              "type": "string"
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            },
                            "readiness": {
                              "type": "string",
                              "enum": [
                                "managed_ready",
                                "managed_activation_required",
                                "connection_required",
                                "connected",
                                "upgrade_required",
                                "verified",
                                "deployable",
                                "invalid_connection",
                                "unavailable"
                              ]
                            },
                            "means": {
                              "type": "string"
                            },
                            "action": {
                              "type": "string",
                              "nullable": true,
                              "description": "What makes the recommended plan deployable, when something does."
                            }
                          }
                        },
                        "executionReadiness": {
                          "type": "object",
                          "description": "Whether this organization could execute a deployment onto the described plan when the receipt was written. An action vocabulary, not a verdict: connection_required means connect an account to deploy, never rejected. On a recorded deployment this is always an executable state, because a decision only ever binds a target that could actually deploy.",
                          "properties": {
                            "state": {
                              "type": "string",
                              "enum": [
                                "managed_ready",
                                "managed_activation_required",
                                "connection_required",
                                "connected",
                                "upgrade_required",
                                "verified",
                                "deployable",
                                "invalid_connection",
                                "unavailable"
                              ]
                            },
                            "means": {
                              "type": "string"
                            },
                            "action": {
                              "type": "string",
                              "nullable": true
                            }
                          }
                        },
                        "alternatives": {
                          "type": "array",
                          "description": "Ranked also-eligible active Vercel and Cloudflare plans, best first. Managed-account readiness never removes or reorders an entry, and it cannot promote an alternative into execution.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "provider": {
                                "type": "string"
                              },
                              "providerName": {
                                "type": "string"
                              },
                              "plan": {
                                "type": "string"
                              },
                              "planName": {
                                "type": "string"
                              },
                              "free": {
                                "type": "boolean"
                              },
                              "estimatedMonthlyCost": {
                                "type": "object",
                                "nullable": true,
                                "properties": {
                                  "minUsd": {
                                    "type": "number"
                                  },
                                  "maxUsd": {
                                    "type": "number"
                                  }
                                }
                              },
                              "eligibility": {
                                "type": "string",
                                "enum": [
                                  "eligible",
                                  "ineligible",
                                  "unknown",
                                  "quote_required"
                                ]
                              },
                              "billingOwner": {
                                "type": "string",
                                "enum": [
                                  "SPRINGROLL",
                                  "CUSTOMER"
                                ]
                              },
                              "readiness": {
                                "type": "string",
                                "enum": [
                                  "managed_ready",
                                  "managed_activation_required",
                                  "connection_required",
                                  "connected",
                                  "upgrade_required",
                                  "verified",
                                  "deployable",
                                  "invalid_connection",
                                  "unavailable"
                                ]
                              },
                              "action": {
                                "type": "string",
                                "nullable": true
                              },
                              "meterBreakdown": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                }
                              },
                              "billingProjection": {
                                "type": "object",
                                "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                                "required": [
                                  "version",
                                  "basis",
                                  "components",
                                  "unmodeledCharges"
                                ],
                                "properties": {
                                  "version": {
                                    "type": "integer",
                                    "enum": [
                                      1
                                    ]
                                  },
                                  "basis": {
                                    "type": "string",
                                    "enum": [
                                      "monthly-usage-before-allowances-and-credits"
                                    ]
                                  },
                                  "builderBackend": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-sandbox",
                                      "external"
                                    ],
                                    "description": "Build service used when the cost snapshot was calculated."
                                  },
                                  "artifactStore": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-blob",
                                      "filesystem",
                                      "unknown"
                                    ],
                                    "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                                  },
                                  "components": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "key": {
                                          "type": "string"
                                        },
                                        "label": {
                                          "type": "string"
                                        },
                                        "unit": {
                                          "type": "string"
                                        },
                                        "billingScope": {
                                          "type": "string",
                                          "enum": [
                                            "vercel-infrastructure",
                                            "neon-integration",
                                            "upstash-integration",
                                            "cloudflare-account",
                                            "external-or-unverified"
                                          ],
                                          "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                                        },
                                        "expectedUsage": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "rateMinUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "rateMaxUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "grossMinUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "grossMaxUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "observedAt": {
                                          "type": [
                                            "string",
                                            "null"
                                          ],
                                          "format": "date-time"
                                        },
                                        "source": {
                                          "type": "string",
                                          "format": "uri"
                                        },
                                        "limitation": {
                                          "type": [
                                            "string",
                                            "null"
                                          ]
                                        }
                                      }
                                    }
                                  },
                                  "unmodeledCharges": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  }
                                }
                              },
                              "pricingSources": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                }
                              },
                              "limitations": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "provisionedCapabilities": {
                      "type": "object",
                      "description": "Safe runtime capability metadata. Credentials and provider account identifiers are never included.",
                      "properties": {
                        "billingProjection": {
                          "type": "object",
                          "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                          "required": [
                            "version",
                            "basis",
                            "components",
                            "unmodeledCharges"
                          ],
                          "properties": {
                            "version": {
                              "type": "integer",
                              "enum": [
                                1
                              ]
                            },
                            "basis": {
                              "type": "string",
                              "enum": [
                                "monthly-usage-before-allowances-and-credits"
                              ]
                            },
                            "builderBackend": {
                              "type": "string",
                              "enum": [
                                "vercel-sandbox",
                                "external"
                              ],
                              "description": "Build service used when the cost snapshot was calculated."
                            },
                            "artifactStore": {
                              "type": "string",
                              "enum": [
                                "vercel-blob",
                                "filesystem",
                                "unknown"
                              ],
                              "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                            },
                            "components": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "key": {
                                    "type": "string"
                                  },
                                  "label": {
                                    "type": "string"
                                  },
                                  "unit": {
                                    "type": "string"
                                  },
                                  "billingScope": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-infrastructure",
                                      "neon-integration",
                                      "upstash-integration",
                                      "cloudflare-account",
                                      "external-or-unverified"
                                    ],
                                    "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                                  },
                                  "expectedUsage": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "rateMinUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "rateMaxUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "grossMinUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "grossMaxUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "observedAt": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "format": "date-time"
                                  },
                                  "source": {
                                    "type": "string",
                                    "format": "uri"
                                  },
                                  "limitation": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                }
                              }
                            },
                            "unmodeledCharges": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "billing": {
                          "type": "object",
                          "description": "Observed plans for this application's data resources, frozen at deployment. No usage totals or credentials.",
                          "additionalProperties": {
                            "type": "object",
                            "required": [
                              "version",
                              "product",
                              "planId",
                              "scope",
                              "observedAt",
                              "currency",
                              "rates",
                              "includedCommandsPerMonth",
                              "source"
                            ],
                            "properties": {
                              "version": {
                                "type": "integer",
                                "enum": [
                                  1
                                ]
                              },
                              "product": {
                                "type": "string",
                                "enum": [
                                  "neon",
                                  "upstash-kv"
                                ]
                              },
                              "planId": {
                                "type": "string",
                                "enum": [
                                  "launch_v3",
                                  "free",
                                  "paid"
                                ]
                              },
                              "scope": {
                                "type": "string",
                                "enum": [
                                  "installation",
                                  "resource"
                                ]
                              },
                              "observedAt": {
                                "type": "string",
                                "format": "date-time"
                              },
                              "currency": {
                                "type": "string",
                                "enum": [
                                  "USD"
                                ]
                              },
                              "rates": {
                                "type": "object",
                                "properties": {
                                  "perCuHourUsd": {
                                    "type": "number",
                                    "minimum": 0
                                  },
                                  "perGbMonthUsd": {
                                    "type": "number",
                                    "minimum": 0
                                  },
                                  "per100kCommandsUsd": {
                                    "type": "number",
                                    "minimum": 0
                                  }
                                }
                              },
                              "includedCommandsPerMonth": {
                                "type": [
                                  "integer",
                                  "null"
                                ],
                                "minimum": 0
                              },
                              "source": {
                                "type": "string",
                                "format": "uri"
                              }
                            }
                          }
                        },
                        "storage": {
                          "type": "object",
                          "required": [
                            "kind",
                            "access",
                            "scope",
                            "baseUrl"
                          ],
                          "properties": {
                            "kind": {
                              "type": "string",
                              "enum": [
                                "object-storage"
                              ]
                            },
                            "access": {
                              "type": "string",
                              "enum": [
                                "public"
                              ]
                            },
                            "scope": {
                              "type": "string",
                              "enum": [
                                "application"
                              ]
                            },
                            "baseUrl": {
                              "type": "string",
                              "format": "uri"
                            },
                            "binding": {
                              "type": "string",
                              "enum": [
                                "STORAGE"
                              ]
                            },
                            "containerEndpointVariable": {
                              "type": "string",
                              "enum": [
                                "SPRINGROLL_CONTAINER_STORAGE_URL"
                              ]
                            }
                          }
                        },
                        "database": {
                          "type": "object",
                          "required": [
                            "kind",
                            "scope",
                            "engine",
                            "connection"
                          ],
                          "properties": {
                            "kind": {
                              "type": "string",
                              "enum": [
                                "database"
                              ]
                            },
                            "scope": {
                              "type": "string",
                              "enum": [
                                "application"
                              ]
                            },
                            "engine": {
                              "type": "string",
                              "enum": [
                                "postgres",
                                "sqlite"
                              ]
                            },
                            "connection": {
                              "type": "string",
                              "enum": [
                                "environment",
                                "binding"
                              ]
                            },
                            "variable": {
                              "type": "string",
                              "enum": [
                                "DATABASE_URL"
                              ]
                            },
                            "binding": {
                              "type": "string",
                              "enum": [
                                "DB"
                              ]
                            },
                            "containerEndpointVariable": {
                              "type": "string",
                              "enum": [
                                "SPRINGROLL_CONTAINER_DATABASE_URL"
                              ]
                            }
                          }
                        }
                      }
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "501": {
            "$ref": "#/components/responses/Error501"
          },
          "502": {
            "$ref": "#/components/responses/Error502"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/deployments/{deploymentId}": {
      "get": {
        "operationId": "getDeployment",
        "summary": "Get a deployment",
        "description": "One deployment, including its status and its live URL once it is serving. Poll this after createDeployment rather than assuming success.",
        "tags": [
          "Deployments"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deploymentId",
            "in": "path",
            "required": true,
            "description": "Deployment id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The deployment.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "One deployment of one immutable release into one environment.",
                  "required": [
                    "id",
                    "environment",
                    "status"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "applicationId": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "bundleId": {
                      "type": "string",
                      "description": "The immutable release that was deployed. Promotion reuses this rather than rebuilding."
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "development",
                        "uat",
                        "production"
                      ],
                      "description": "Which environment this deployment serves."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "QUEUED",
                        "VALIDATING",
                        "BUILDING",
                        "DEPLOYING",
                        "READY",
                        "FAILED",
                        "CANCELLED",
                        "SUPERSEDED",
                        "ROLLED_BACK"
                      ],
                      "description": "Lifecycle of the deployment attempt itself, not of the application."
                    },
                    "url": {
                      "type": "string",
                      "format": "uri",
                      "description": "The live URL, once the deployment is serving. Absent until then."
                    },
                    "placement": {
                      "type": "object",
                      "description": "Where SpringRoll decided to run this application, and why. Null for an application on a runtime the organization configured for itself, and for every deployment that predates automatic placement.",
                      "properties": {
                        "references": {
                          "type": "object",
                          "description": "Immutable references for the decision, independent recommendation, and exact managed runtime configuration.",
                          "properties": {
                            "decisionId": {
                              "type": "string",
                              "format": "uuid"
                            },
                            "recommendationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            },
                            "runtimeConfigurationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            }
                          }
                        },
                        "recommended": {
                          "type": "object",
                          "properties": {
                            "provider": {
                              "type": "string",
                              "enum": [
                                "vercel",
                                "cloudflare"
                              ]
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            }
                          }
                        },
                        "executed": {
                          "type": "object",
                          "properties": {
                            "provider": {
                              "type": "string",
                              "enum": [
                                "vercel",
                                "cloudflare"
                              ]
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            },
                            "runtimeConfigurationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            }
                          }
                        },
                        "provider": {
                          "type": "string",
                          "description": "Provider identifier."
                        },
                        "providerName": {
                          "type": "string",
                          "description": "Provider name, for display."
                        },
                        "plan": {
                          "type": "string",
                          "description": "The plan on that provider."
                        },
                        "servedByInstead": {
                          "type": "object",
                          "nullable": true,
                          "description": "Historical compatibility only. New deployments never switch providers without a new approved placement decision.",
                          "properties": {
                            "provider": {
                              "type": "string"
                            },
                            "providerName": {
                              "type": "string"
                            }
                          }
                        },
                        "free": {
                          "type": "boolean",
                          "description": "True when adding this application to the account costs nothing more. It means the marginal cost is known to be zero, not that the plan has a zero price and not that the numbers were unreadable."
                        },
                        "estimatedMonthlyCost": {
                          "type": "object",
                          "nullable": true,
                          "description": "What adding this application costs beyond the subscription SpringRoll already pays. A range, never a single number: a metered plan's bill depends on traffic nobody has measured yet, and one figure gets quoted back as a price. Null when the cost could not be worked out at all.",
                          "properties": {
                            "minUsd": {
                              "type": "number"
                            },
                            "maxUsd": {
                              "type": "number"
                            },
                            "currency": {
                              "type": "string"
                            },
                            "confidence": {
                              "type": "string",
                              "enum": [
                                "HIGH",
                                "MEDIUM",
                                "LOW",
                                "UNKNOWN"
                              ],
                              "description": "How much the estimate is worth. There is no path to HIGH on a first placement."
                            },
                            "confidenceMeans": {
                              "type": "string"
                            }
                          }
                        },
                        "bestAvailable": {
                          "type": "boolean",
                          "description": "Whether SpringRoll will stand behind the claim that this is the best available placement. False when the price list was stale or the plan's price could not be read. The placement still happened; the superlative did not survive."
                        },
                        "pricing": {
                          "type": "object",
                          "description": "The price list this decision was scored against, so it can be replayed.",
                          "properties": {
                            "version": {
                              "type": "string"
                            },
                            "stale": {
                              "type": "boolean"
                            }
                          }
                        },
                        "meterBreakdown": {
                          "type": "array",
                          "description": "Request, bandwidth, compute, memory, storage, and build evidence behind the estimate. An incomplete required meter prevents a lowest-cost claim.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "meter": {
                                "type": "string",
                                "enum": [
                                  "requests",
                                  "bandwidth",
                                  "compute",
                                  "memory",
                                  "storage",
                                  "build",
                                  "database",
                                  "cache",
                                  "storage-operations"
                                ]
                              },
                              "required": {
                                "type": "boolean"
                              },
                              "expectedUsage": {
                                "type": "number",
                                "nullable": true
                              },
                              "unit": {
                                "type": "string"
                              },
                              "includedUsage": {
                                "nullable": true
                              },
                              "excessUsage": {
                                "type": "number",
                                "nullable": true
                              },
                              "rateUsd": {
                                "type": "number",
                                "nullable": true
                              },
                              "rateUnit": {
                                "type": "string",
                                "nullable": true
                              },
                              "estimatedCostUsd": {
                                "type": "number",
                                "nullable": true
                              },
                              "complete": {
                                "type": "boolean"
                              },
                              "limitation": {
                                "type": "string",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "pricingSources": {
                          "type": "array",
                          "description": "Public evidence frozen with the catalog version, including observation and effective dates.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "pricing",
                                  "terms"
                                ]
                              },
                              "url": {
                                "type": "string",
                                "format": "uri"
                              },
                              "observedAt": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                              },
                              "effectiveAt": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "limitations": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "decidedBy": {
                          "type": "object",
                          "properties": {
                            "source": {
                              "type": "string",
                              "enum": [
                                "AUTOMATIC",
                                "ADMIN_OVERRIDE",
                                "LEGACY_BACKFILL",
                                "MIGRATION"
                              ]
                            },
                            "means": {
                              "type": "string"
                            }
                          }
                        },
                        "assumptions": {
                          "type": "array",
                          "description": "One entry per field SpringRoll had to guess, with the evidence it used. A value the caller declared never appears here, so a reader can always tell measurement from inference.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string"
                              },
                              "value": {
                                "type": "string"
                              },
                              "because": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "limits": {
                          "type": "array",
                          "description": "Every way this plan is worse than paying: sleeping when idle, stopping at a usage cap, cold starts, no backups, no availability commitment. Tell the user these before they rely on the application.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string"
                              },
                              "means": {
                                "type": "string"
                              },
                              "detail": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "notChosen": {
                          "type": "array",
                          "description": "Every candidate that lost, with the first reason it lost. This is the half that makes the receipt an argument a reader can check rather than an assertion, so it is worth rendering rather than ignoring.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "provider": {
                                "type": "string"
                              },
                              "plan": {
                                "type": "string"
                              },
                              "reason": {
                                "type": "string",
                                "enum": [
                                  "TERMS_INELIGIBLE",
                                  "UNSUITABLE_ENVIRONMENT",
                                  "NO_MANAGED_CAPACITY",
                                  "RUNTIME_UNSUPPORTED",
                                  "UNMET_REQUIREMENT",
                                  "UNSUPPORTED_SOURCE",
                                  "INVALID_REGION",
                                  "DATA_POLICY_CONFLICT",
                                  "OVER_BUDGET"
                                ]
                              },
                              "means": {
                                "type": "string"
                              },
                              "detail": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "billingOwner": {
                          "type": "object",
                          "description": "Who pays the provider for the plan this receipt describes. Released placements use SpringRoll-managed Vercel and Cloudflare accounts.",
                          "properties": {
                            "owner": {
                              "type": "string",
                              "enum": [
                                "SPRINGROLL",
                                "CUSTOMER"
                              ]
                            },
                            "means": {
                              "type": "string"
                            }
                          }
                        },
                        "recommendedInstead": {
                          "type": "object",
                          "nullable": true,
                          "description": "Historical compatibility only. New placements bind recommendation and execution to the same exact managed target.",
                          "properties": {
                            "provider": {
                              "type": "string"
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            },
                            "readiness": {
                              "type": "string",
                              "enum": [
                                "managed_ready",
                                "managed_activation_required",
                                "connection_required",
                                "connected",
                                "upgrade_required",
                                "verified",
                                "deployable",
                                "invalid_connection",
                                "unavailable"
                              ]
                            },
                            "means": {
                              "type": "string"
                            },
                            "action": {
                              "type": "string",
                              "nullable": true,
                              "description": "What makes the recommended plan deployable, when something does."
                            }
                          }
                        },
                        "executionReadiness": {
                          "type": "object",
                          "description": "Whether this organization could execute a deployment onto the described plan when the receipt was written. An action vocabulary, not a verdict: connection_required means connect an account to deploy, never rejected. On a recorded deployment this is always an executable state, because a decision only ever binds a target that could actually deploy.",
                          "properties": {
                            "state": {
                              "type": "string",
                              "enum": [
                                "managed_ready",
                                "managed_activation_required",
                                "connection_required",
                                "connected",
                                "upgrade_required",
                                "verified",
                                "deployable",
                                "invalid_connection",
                                "unavailable"
                              ]
                            },
                            "means": {
                              "type": "string"
                            },
                            "action": {
                              "type": "string",
                              "nullable": true
                            }
                          }
                        },
                        "alternatives": {
                          "type": "array",
                          "description": "Ranked also-eligible active Vercel and Cloudflare plans, best first. Managed-account readiness never removes or reorders an entry, and it cannot promote an alternative into execution.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "provider": {
                                "type": "string"
                              },
                              "providerName": {
                                "type": "string"
                              },
                              "plan": {
                                "type": "string"
                              },
                              "planName": {
                                "type": "string"
                              },
                              "free": {
                                "type": "boolean"
                              },
                              "estimatedMonthlyCost": {
                                "type": "object",
                                "nullable": true,
                                "properties": {
                                  "minUsd": {
                                    "type": "number"
                                  },
                                  "maxUsd": {
                                    "type": "number"
                                  }
                                }
                              },
                              "eligibility": {
                                "type": "string",
                                "enum": [
                                  "eligible",
                                  "ineligible",
                                  "unknown",
                                  "quote_required"
                                ]
                              },
                              "billingOwner": {
                                "type": "string",
                                "enum": [
                                  "SPRINGROLL",
                                  "CUSTOMER"
                                ]
                              },
                              "readiness": {
                                "type": "string",
                                "enum": [
                                  "managed_ready",
                                  "managed_activation_required",
                                  "connection_required",
                                  "connected",
                                  "upgrade_required",
                                  "verified",
                                  "deployable",
                                  "invalid_connection",
                                  "unavailable"
                                ]
                              },
                              "action": {
                                "type": "string",
                                "nullable": true
                              },
                              "meterBreakdown": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                }
                              },
                              "billingProjection": {
                                "type": "object",
                                "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                                "required": [
                                  "version",
                                  "basis",
                                  "components",
                                  "unmodeledCharges"
                                ],
                                "properties": {
                                  "version": {
                                    "type": "integer",
                                    "enum": [
                                      1
                                    ]
                                  },
                                  "basis": {
                                    "type": "string",
                                    "enum": [
                                      "monthly-usage-before-allowances-and-credits"
                                    ]
                                  },
                                  "builderBackend": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-sandbox",
                                      "external"
                                    ],
                                    "description": "Build service used when the cost snapshot was calculated."
                                  },
                                  "artifactStore": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-blob",
                                      "filesystem",
                                      "unknown"
                                    ],
                                    "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                                  },
                                  "components": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "key": {
                                          "type": "string"
                                        },
                                        "label": {
                                          "type": "string"
                                        },
                                        "unit": {
                                          "type": "string"
                                        },
                                        "billingScope": {
                                          "type": "string",
                                          "enum": [
                                            "vercel-infrastructure",
                                            "neon-integration",
                                            "upstash-integration",
                                            "cloudflare-account",
                                            "external-or-unverified"
                                          ],
                                          "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                                        },
                                        "expectedUsage": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "rateMinUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "rateMaxUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "grossMinUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "grossMaxUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "observedAt": {
                                          "type": [
                                            "string",
                                            "null"
                                          ],
                                          "format": "date-time"
                                        },
                                        "source": {
                                          "type": "string",
                                          "format": "uri"
                                        },
                                        "limitation": {
                                          "type": [
                                            "string",
                                            "null"
                                          ]
                                        }
                                      }
                                    }
                                  },
                                  "unmodeledCharges": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  }
                                }
                              },
                              "pricingSources": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                }
                              },
                              "limitations": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "provisionedCapabilities": {
                      "type": "object",
                      "description": "Safe runtime capability metadata. Credentials and provider account identifiers are never included.",
                      "properties": {
                        "billingProjection": {
                          "type": "object",
                          "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                          "required": [
                            "version",
                            "basis",
                            "components",
                            "unmodeledCharges"
                          ],
                          "properties": {
                            "version": {
                              "type": "integer",
                              "enum": [
                                1
                              ]
                            },
                            "basis": {
                              "type": "string",
                              "enum": [
                                "monthly-usage-before-allowances-and-credits"
                              ]
                            },
                            "builderBackend": {
                              "type": "string",
                              "enum": [
                                "vercel-sandbox",
                                "external"
                              ],
                              "description": "Build service used when the cost snapshot was calculated."
                            },
                            "artifactStore": {
                              "type": "string",
                              "enum": [
                                "vercel-blob",
                                "filesystem",
                                "unknown"
                              ],
                              "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                            },
                            "components": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "key": {
                                    "type": "string"
                                  },
                                  "label": {
                                    "type": "string"
                                  },
                                  "unit": {
                                    "type": "string"
                                  },
                                  "billingScope": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-infrastructure",
                                      "neon-integration",
                                      "upstash-integration",
                                      "cloudflare-account",
                                      "external-or-unverified"
                                    ],
                                    "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                                  },
                                  "expectedUsage": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "rateMinUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "rateMaxUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "grossMinUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "grossMaxUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "observedAt": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "format": "date-time"
                                  },
                                  "source": {
                                    "type": "string",
                                    "format": "uri"
                                  },
                                  "limitation": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                }
                              }
                            },
                            "unmodeledCharges": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "billing": {
                          "type": "object",
                          "description": "Observed plans for this application's data resources, frozen at deployment. No usage totals or credentials.",
                          "additionalProperties": {
                            "type": "object",
                            "required": [
                              "version",
                              "product",
                              "planId",
                              "scope",
                              "observedAt",
                              "currency",
                              "rates",
                              "includedCommandsPerMonth",
                              "source"
                            ],
                            "properties": {
                              "version": {
                                "type": "integer",
                                "enum": [
                                  1
                                ]
                              },
                              "product": {
                                "type": "string",
                                "enum": [
                                  "neon",
                                  "upstash-kv"
                                ]
                              },
                              "planId": {
                                "type": "string",
                                "enum": [
                                  "launch_v3",
                                  "free",
                                  "paid"
                                ]
                              },
                              "scope": {
                                "type": "string",
                                "enum": [
                                  "installation",
                                  "resource"
                                ]
                              },
                              "observedAt": {
                                "type": "string",
                                "format": "date-time"
                              },
                              "currency": {
                                "type": "string",
                                "enum": [
                                  "USD"
                                ]
                              },
                              "rates": {
                                "type": "object",
                                "properties": {
                                  "perCuHourUsd": {
                                    "type": "number",
                                    "minimum": 0
                                  },
                                  "perGbMonthUsd": {
                                    "type": "number",
                                    "minimum": 0
                                  },
                                  "per100kCommandsUsd": {
                                    "type": "number",
                                    "minimum": 0
                                  }
                                }
                              },
                              "includedCommandsPerMonth": {
                                "type": [
                                  "integer",
                                  "null"
                                ],
                                "minimum": 0
                              },
                              "source": {
                                "type": "string",
                                "format": "uri"
                              }
                            }
                          }
                        },
                        "storage": {
                          "type": "object",
                          "required": [
                            "kind",
                            "access",
                            "scope",
                            "baseUrl"
                          ],
                          "properties": {
                            "kind": {
                              "type": "string",
                              "enum": [
                                "object-storage"
                              ]
                            },
                            "access": {
                              "type": "string",
                              "enum": [
                                "public"
                              ]
                            },
                            "scope": {
                              "type": "string",
                              "enum": [
                                "application"
                              ]
                            },
                            "baseUrl": {
                              "type": "string",
                              "format": "uri"
                            },
                            "binding": {
                              "type": "string",
                              "enum": [
                                "STORAGE"
                              ]
                            },
                            "containerEndpointVariable": {
                              "type": "string",
                              "enum": [
                                "SPRINGROLL_CONTAINER_STORAGE_URL"
                              ]
                            }
                          }
                        },
                        "database": {
                          "type": "object",
                          "required": [
                            "kind",
                            "scope",
                            "engine",
                            "connection"
                          ],
                          "properties": {
                            "kind": {
                              "type": "string",
                              "enum": [
                                "database"
                              ]
                            },
                            "scope": {
                              "type": "string",
                              "enum": [
                                "application"
                              ]
                            },
                            "engine": {
                              "type": "string",
                              "enum": [
                                "postgres",
                                "sqlite"
                              ]
                            },
                            "connection": {
                              "type": "string",
                              "enum": [
                                "environment",
                                "binding"
                              ]
                            },
                            "variable": {
                              "type": "string",
                              "enum": [
                                "DATABASE_URL"
                              ]
                            },
                            "binding": {
                              "type": "string",
                              "enum": [
                                "DB"
                              ]
                            },
                            "containerEndpointVariable": {
                              "type": "string",
                              "enum": [
                                "SPRINGROLL_CONTAINER_DATABASE_URL"
                              ]
                            }
                          }
                        }
                      }
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/deployments/{deploymentId}/promote": {
      "post": {
        "operationId": "promoteDeployment",
        "summary": "Promote to the next environment",
        "description": "Promotes the exact release this deployment carries into the next environment. There is no deploy-latest: promotion always references the immutable release, which is what makes the audit trail meaningful. Production promotion in a staged organization requires an approval.",
        "tags": [
          "Deployments"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deploymentId",
            "in": "path",
            "required": true,
            "description": "Deployment id to promote from.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Replays safely: the same key with the same body returns the original result, and with a different body returns IDEMPOTENCY_CONFLICT. Send one on every write an agent might retry.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": false,
          "description": "Optionally name the target environment; the next one in the workflow is used otherwise.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "environment": {
                    "type": "string",
                    "enum": [
                      "development",
                      "uat",
                      "production"
                    ]
                  },
                  "note": {
                    "type": "string",
                    "description": "Recorded on the audit event."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The new deployment.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "One deployment of one immutable release into one environment.",
                  "required": [
                    "id",
                    "environment",
                    "status"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "applicationId": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "bundleId": {
                      "type": "string",
                      "description": "The immutable release that was deployed. Promotion reuses this rather than rebuilding."
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "development",
                        "uat",
                        "production"
                      ],
                      "description": "Which environment this deployment serves."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "QUEUED",
                        "VALIDATING",
                        "BUILDING",
                        "DEPLOYING",
                        "READY",
                        "FAILED",
                        "CANCELLED",
                        "SUPERSEDED",
                        "ROLLED_BACK"
                      ],
                      "description": "Lifecycle of the deployment attempt itself, not of the application."
                    },
                    "url": {
                      "type": "string",
                      "format": "uri",
                      "description": "The live URL, once the deployment is serving. Absent until then."
                    },
                    "placement": {
                      "type": "object",
                      "description": "Where SpringRoll decided to run this application, and why. Null for an application on a runtime the organization configured for itself, and for every deployment that predates automatic placement.",
                      "properties": {
                        "references": {
                          "type": "object",
                          "description": "Immutable references for the decision, independent recommendation, and exact managed runtime configuration.",
                          "properties": {
                            "decisionId": {
                              "type": "string",
                              "format": "uuid"
                            },
                            "recommendationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            },
                            "runtimeConfigurationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            }
                          }
                        },
                        "recommended": {
                          "type": "object",
                          "properties": {
                            "provider": {
                              "type": "string",
                              "enum": [
                                "vercel",
                                "cloudflare"
                              ]
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            }
                          }
                        },
                        "executed": {
                          "type": "object",
                          "properties": {
                            "provider": {
                              "type": "string",
                              "enum": [
                                "vercel",
                                "cloudflare"
                              ]
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            },
                            "runtimeConfigurationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            }
                          }
                        },
                        "provider": {
                          "type": "string",
                          "description": "Provider identifier."
                        },
                        "providerName": {
                          "type": "string",
                          "description": "Provider name, for display."
                        },
                        "plan": {
                          "type": "string",
                          "description": "The plan on that provider."
                        },
                        "servedByInstead": {
                          "type": "object",
                          "nullable": true,
                          "description": "Historical compatibility only. New deployments never switch providers without a new approved placement decision.",
                          "properties": {
                            "provider": {
                              "type": "string"
                            },
                            "providerName": {
                              "type": "string"
                            }
                          }
                        },
                        "free": {
                          "type": "boolean",
                          "description": "True when adding this application to the account costs nothing more. It means the marginal cost is known to be zero, not that the plan has a zero price and not that the numbers were unreadable."
                        },
                        "estimatedMonthlyCost": {
                          "type": "object",
                          "nullable": true,
                          "description": "What adding this application costs beyond the subscription SpringRoll already pays. A range, never a single number: a metered plan's bill depends on traffic nobody has measured yet, and one figure gets quoted back as a price. Null when the cost could not be worked out at all.",
                          "properties": {
                            "minUsd": {
                              "type": "number"
                            },
                            "maxUsd": {
                              "type": "number"
                            },
                            "currency": {
                              "type": "string"
                            },
                            "confidence": {
                              "type": "string",
                              "enum": [
                                "HIGH",
                                "MEDIUM",
                                "LOW",
                                "UNKNOWN"
                              ],
                              "description": "How much the estimate is worth. There is no path to HIGH on a first placement."
                            },
                            "confidenceMeans": {
                              "type": "string"
                            }
                          }
                        },
                        "bestAvailable": {
                          "type": "boolean",
                          "description": "Whether SpringRoll will stand behind the claim that this is the best available placement. False when the price list was stale or the plan's price could not be read. The placement still happened; the superlative did not survive."
                        },
                        "pricing": {
                          "type": "object",
                          "description": "The price list this decision was scored against, so it can be replayed.",
                          "properties": {
                            "version": {
                              "type": "string"
                            },
                            "stale": {
                              "type": "boolean"
                            }
                          }
                        },
                        "meterBreakdown": {
                          "type": "array",
                          "description": "Request, bandwidth, compute, memory, storage, and build evidence behind the estimate. An incomplete required meter prevents a lowest-cost claim.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "meter": {
                                "type": "string",
                                "enum": [
                                  "requests",
                                  "bandwidth",
                                  "compute",
                                  "memory",
                                  "storage",
                                  "build",
                                  "database",
                                  "cache",
                                  "storage-operations"
                                ]
                              },
                              "required": {
                                "type": "boolean"
                              },
                              "expectedUsage": {
                                "type": "number",
                                "nullable": true
                              },
                              "unit": {
                                "type": "string"
                              },
                              "includedUsage": {
                                "nullable": true
                              },
                              "excessUsage": {
                                "type": "number",
                                "nullable": true
                              },
                              "rateUsd": {
                                "type": "number",
                                "nullable": true
                              },
                              "rateUnit": {
                                "type": "string",
                                "nullable": true
                              },
                              "estimatedCostUsd": {
                                "type": "number",
                                "nullable": true
                              },
                              "complete": {
                                "type": "boolean"
                              },
                              "limitation": {
                                "type": "string",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "pricingSources": {
                          "type": "array",
                          "description": "Public evidence frozen with the catalog version, including observation and effective dates.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "pricing",
                                  "terms"
                                ]
                              },
                              "url": {
                                "type": "string",
                                "format": "uri"
                              },
                              "observedAt": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                              },
                              "effectiveAt": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "limitations": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "decidedBy": {
                          "type": "object",
                          "properties": {
                            "source": {
                              "type": "string",
                              "enum": [
                                "AUTOMATIC",
                                "ADMIN_OVERRIDE",
                                "LEGACY_BACKFILL",
                                "MIGRATION"
                              ]
                            },
                            "means": {
                              "type": "string"
                            }
                          }
                        },
                        "assumptions": {
                          "type": "array",
                          "description": "One entry per field SpringRoll had to guess, with the evidence it used. A value the caller declared never appears here, so a reader can always tell measurement from inference.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string"
                              },
                              "value": {
                                "type": "string"
                              },
                              "because": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "limits": {
                          "type": "array",
                          "description": "Every way this plan is worse than paying: sleeping when idle, stopping at a usage cap, cold starts, no backups, no availability commitment. Tell the user these before they rely on the application.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string"
                              },
                              "means": {
                                "type": "string"
                              },
                              "detail": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "notChosen": {
                          "type": "array",
                          "description": "Every candidate that lost, with the first reason it lost. This is the half that makes the receipt an argument a reader can check rather than an assertion, so it is worth rendering rather than ignoring.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "provider": {
                                "type": "string"
                              },
                              "plan": {
                                "type": "string"
                              },
                              "reason": {
                                "type": "string",
                                "enum": [
                                  "TERMS_INELIGIBLE",
                                  "UNSUITABLE_ENVIRONMENT",
                                  "NO_MANAGED_CAPACITY",
                                  "RUNTIME_UNSUPPORTED",
                                  "UNMET_REQUIREMENT",
                                  "UNSUPPORTED_SOURCE",
                                  "INVALID_REGION",
                                  "DATA_POLICY_CONFLICT",
                                  "OVER_BUDGET"
                                ]
                              },
                              "means": {
                                "type": "string"
                              },
                              "detail": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "billingOwner": {
                          "type": "object",
                          "description": "Who pays the provider for the plan this receipt describes. Released placements use SpringRoll-managed Vercel and Cloudflare accounts.",
                          "properties": {
                            "owner": {
                              "type": "string",
                              "enum": [
                                "SPRINGROLL",
                                "CUSTOMER"
                              ]
                            },
                            "means": {
                              "type": "string"
                            }
                          }
                        },
                        "recommendedInstead": {
                          "type": "object",
                          "nullable": true,
                          "description": "Historical compatibility only. New placements bind recommendation and execution to the same exact managed target.",
                          "properties": {
                            "provider": {
                              "type": "string"
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            },
                            "readiness": {
                              "type": "string",
                              "enum": [
                                "managed_ready",
                                "managed_activation_required",
                                "connection_required",
                                "connected",
                                "upgrade_required",
                                "verified",
                                "deployable",
                                "invalid_connection",
                                "unavailable"
                              ]
                            },
                            "means": {
                              "type": "string"
                            },
                            "action": {
                              "type": "string",
                              "nullable": true,
                              "description": "What makes the recommended plan deployable, when something does."
                            }
                          }
                        },
                        "executionReadiness": {
                          "type": "object",
                          "description": "Whether this organization could execute a deployment onto the described plan when the receipt was written. An action vocabulary, not a verdict: connection_required means connect an account to deploy, never rejected. On a recorded deployment this is always an executable state, because a decision only ever binds a target that could actually deploy.",
                          "properties": {
                            "state": {
                              "type": "string",
                              "enum": [
                                "managed_ready",
                                "managed_activation_required",
                                "connection_required",
                                "connected",
                                "upgrade_required",
                                "verified",
                                "deployable",
                                "invalid_connection",
                                "unavailable"
                              ]
                            },
                            "means": {
                              "type": "string"
                            },
                            "action": {
                              "type": "string",
                              "nullable": true
                            }
                          }
                        },
                        "alternatives": {
                          "type": "array",
                          "description": "Ranked also-eligible active Vercel and Cloudflare plans, best first. Managed-account readiness never removes or reorders an entry, and it cannot promote an alternative into execution.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "provider": {
                                "type": "string"
                              },
                              "providerName": {
                                "type": "string"
                              },
                              "plan": {
                                "type": "string"
                              },
                              "planName": {
                                "type": "string"
                              },
                              "free": {
                                "type": "boolean"
                              },
                              "estimatedMonthlyCost": {
                                "type": "object",
                                "nullable": true,
                                "properties": {
                                  "minUsd": {
                                    "type": "number"
                                  },
                                  "maxUsd": {
                                    "type": "number"
                                  }
                                }
                              },
                              "eligibility": {
                                "type": "string",
                                "enum": [
                                  "eligible",
                                  "ineligible",
                                  "unknown",
                                  "quote_required"
                                ]
                              },
                              "billingOwner": {
                                "type": "string",
                                "enum": [
                                  "SPRINGROLL",
                                  "CUSTOMER"
                                ]
                              },
                              "readiness": {
                                "type": "string",
                                "enum": [
                                  "managed_ready",
                                  "managed_activation_required",
                                  "connection_required",
                                  "connected",
                                  "upgrade_required",
                                  "verified",
                                  "deployable",
                                  "invalid_connection",
                                  "unavailable"
                                ]
                              },
                              "action": {
                                "type": "string",
                                "nullable": true
                              },
                              "meterBreakdown": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                }
                              },
                              "billingProjection": {
                                "type": "object",
                                "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                                "required": [
                                  "version",
                                  "basis",
                                  "components",
                                  "unmodeledCharges"
                                ],
                                "properties": {
                                  "version": {
                                    "type": "integer",
                                    "enum": [
                                      1
                                    ]
                                  },
                                  "basis": {
                                    "type": "string",
                                    "enum": [
                                      "monthly-usage-before-allowances-and-credits"
                                    ]
                                  },
                                  "builderBackend": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-sandbox",
                                      "external"
                                    ],
                                    "description": "Build service used when the cost snapshot was calculated."
                                  },
                                  "artifactStore": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-blob",
                                      "filesystem",
                                      "unknown"
                                    ],
                                    "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                                  },
                                  "components": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "key": {
                                          "type": "string"
                                        },
                                        "label": {
                                          "type": "string"
                                        },
                                        "unit": {
                                          "type": "string"
                                        },
                                        "billingScope": {
                                          "type": "string",
                                          "enum": [
                                            "vercel-infrastructure",
                                            "neon-integration",
                                            "upstash-integration",
                                            "cloudflare-account",
                                            "external-or-unverified"
                                          ],
                                          "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                                        },
                                        "expectedUsage": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "rateMinUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "rateMaxUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "grossMinUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "grossMaxUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "observedAt": {
                                          "type": [
                                            "string",
                                            "null"
                                          ],
                                          "format": "date-time"
                                        },
                                        "source": {
                                          "type": "string",
                                          "format": "uri"
                                        },
                                        "limitation": {
                                          "type": [
                                            "string",
                                            "null"
                                          ]
                                        }
                                      }
                                    }
                                  },
                                  "unmodeledCharges": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  }
                                }
                              },
                              "pricingSources": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                }
                              },
                              "limitations": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "provisionedCapabilities": {
                      "type": "object",
                      "description": "Safe runtime capability metadata. Credentials and provider account identifiers are never included.",
                      "properties": {
                        "billingProjection": {
                          "type": "object",
                          "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                          "required": [
                            "version",
                            "basis",
                            "components",
                            "unmodeledCharges"
                          ],
                          "properties": {
                            "version": {
                              "type": "integer",
                              "enum": [
                                1
                              ]
                            },
                            "basis": {
                              "type": "string",
                              "enum": [
                                "monthly-usage-before-allowances-and-credits"
                              ]
                            },
                            "builderBackend": {
                              "type": "string",
                              "enum": [
                                "vercel-sandbox",
                                "external"
                              ],
                              "description": "Build service used when the cost snapshot was calculated."
                            },
                            "artifactStore": {
                              "type": "string",
                              "enum": [
                                "vercel-blob",
                                "filesystem",
                                "unknown"
                              ],
                              "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                            },
                            "components": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "key": {
                                    "type": "string"
                                  },
                                  "label": {
                                    "type": "string"
                                  },
                                  "unit": {
                                    "type": "string"
                                  },
                                  "billingScope": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-infrastructure",
                                      "neon-integration",
                                      "upstash-integration",
                                      "cloudflare-account",
                                      "external-or-unverified"
                                    ],
                                    "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                                  },
                                  "expectedUsage": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "rateMinUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "rateMaxUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "grossMinUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "grossMaxUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "observedAt": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "format": "date-time"
                                  },
                                  "source": {
                                    "type": "string",
                                    "format": "uri"
                                  },
                                  "limitation": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                }
                              }
                            },
                            "unmodeledCharges": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "billing": {
                          "type": "object",
                          "description": "Observed plans for this application's data resources, frozen at deployment. No usage totals or credentials.",
                          "additionalProperties": {
                            "type": "object",
                            "required": [
                              "version",
                              "product",
                              "planId",
                              "scope",
                              "observedAt",
                              "currency",
                              "rates",
                              "includedCommandsPerMonth",
                              "source"
                            ],
                            "properties": {
                              "version": {
                                "type": "integer",
                                "enum": [
                                  1
                                ]
                              },
                              "product": {
                                "type": "string",
                                "enum": [
                                  "neon",
                                  "upstash-kv"
                                ]
                              },
                              "planId": {
                                "type": "string",
                                "enum": [
                                  "launch_v3",
                                  "free",
                                  "paid"
                                ]
                              },
                              "scope": {
                                "type": "string",
                                "enum": [
                                  "installation",
                                  "resource"
                                ]
                              },
                              "observedAt": {
                                "type": "string",
                                "format": "date-time"
                              },
                              "currency": {
                                "type": "string",
                                "enum": [
                                  "USD"
                                ]
                              },
                              "rates": {
                                "type": "object",
                                "properties": {
                                  "perCuHourUsd": {
                                    "type": "number",
                                    "minimum": 0
                                  },
                                  "perGbMonthUsd": {
                                    "type": "number",
                                    "minimum": 0
                                  },
                                  "per100kCommandsUsd": {
                                    "type": "number",
                                    "minimum": 0
                                  }
                                }
                              },
                              "includedCommandsPerMonth": {
                                "type": [
                                  "integer",
                                  "null"
                                ],
                                "minimum": 0
                              },
                              "source": {
                                "type": "string",
                                "format": "uri"
                              }
                            }
                          }
                        },
                        "storage": {
                          "type": "object",
                          "required": [
                            "kind",
                            "access",
                            "scope",
                            "baseUrl"
                          ],
                          "properties": {
                            "kind": {
                              "type": "string",
                              "enum": [
                                "object-storage"
                              ]
                            },
                            "access": {
                              "type": "string",
                              "enum": [
                                "public"
                              ]
                            },
                            "scope": {
                              "type": "string",
                              "enum": [
                                "application"
                              ]
                            },
                            "baseUrl": {
                              "type": "string",
                              "format": "uri"
                            },
                            "binding": {
                              "type": "string",
                              "enum": [
                                "STORAGE"
                              ]
                            },
                            "containerEndpointVariable": {
                              "type": "string",
                              "enum": [
                                "SPRINGROLL_CONTAINER_STORAGE_URL"
                              ]
                            }
                          }
                        },
                        "database": {
                          "type": "object",
                          "required": [
                            "kind",
                            "scope",
                            "engine",
                            "connection"
                          ],
                          "properties": {
                            "kind": {
                              "type": "string",
                              "enum": [
                                "database"
                              ]
                            },
                            "scope": {
                              "type": "string",
                              "enum": [
                                "application"
                              ]
                            },
                            "engine": {
                              "type": "string",
                              "enum": [
                                "postgres",
                                "sqlite"
                              ]
                            },
                            "connection": {
                              "type": "string",
                              "enum": [
                                "environment",
                                "binding"
                              ]
                            },
                            "variable": {
                              "type": "string",
                              "enum": [
                                "DATABASE_URL"
                              ]
                            },
                            "binding": {
                              "type": "string",
                              "enum": [
                                "DB"
                              ]
                            },
                            "containerEndpointVariable": {
                              "type": "string",
                              "enum": [
                                "SPRINGROLL_CONTAINER_DATABASE_URL"
                              ]
                            }
                          }
                        }
                      }
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "502": {
            "$ref": "#/components/responses/Error502"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/deployments/{deploymentId}/rollback": {
      "post": {
        "operationId": "rollbackDeployment",
        "summary": "Roll back",
        "description": "Returns an environment to the release it was serving before this deployment. Always requires a person: rollback is a governed action even in a Direct to Production organization.",
        "tags": [
          "Deployments"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deploymentId",
            "in": "path",
            "required": true,
            "description": "Deployment id to roll back.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Replays safely: the same key with the same body returns the original result, and with a different body returns IDEMPOTENCY_CONFLICT. Send one on every write an agent might retry.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": false,
          "description": "Why.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "Recorded on the audit event."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The rollback deployment.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "One deployment of one immutable release into one environment.",
                  "required": [
                    "id",
                    "environment",
                    "status"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "applicationId": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "bundleId": {
                      "type": "string",
                      "description": "The immutable release that was deployed. Promotion reuses this rather than rebuilding."
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "development",
                        "uat",
                        "production"
                      ],
                      "description": "Which environment this deployment serves."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "QUEUED",
                        "VALIDATING",
                        "BUILDING",
                        "DEPLOYING",
                        "READY",
                        "FAILED",
                        "CANCELLED",
                        "SUPERSEDED",
                        "ROLLED_BACK"
                      ],
                      "description": "Lifecycle of the deployment attempt itself, not of the application."
                    },
                    "url": {
                      "type": "string",
                      "format": "uri",
                      "description": "The live URL, once the deployment is serving. Absent until then."
                    },
                    "placement": {
                      "type": "object",
                      "description": "Where SpringRoll decided to run this application, and why. Null for an application on a runtime the organization configured for itself, and for every deployment that predates automatic placement.",
                      "properties": {
                        "references": {
                          "type": "object",
                          "description": "Immutable references for the decision, independent recommendation, and exact managed runtime configuration.",
                          "properties": {
                            "decisionId": {
                              "type": "string",
                              "format": "uuid"
                            },
                            "recommendationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            },
                            "runtimeConfigurationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            }
                          }
                        },
                        "recommended": {
                          "type": "object",
                          "properties": {
                            "provider": {
                              "type": "string",
                              "enum": [
                                "vercel",
                                "cloudflare"
                              ]
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            }
                          }
                        },
                        "executed": {
                          "type": "object",
                          "properties": {
                            "provider": {
                              "type": "string",
                              "enum": [
                                "vercel",
                                "cloudflare"
                              ]
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            },
                            "runtimeConfigurationId": {
                              "type": "string",
                              "format": "uuid",
                              "nullable": true
                            }
                          }
                        },
                        "provider": {
                          "type": "string",
                          "description": "Provider identifier."
                        },
                        "providerName": {
                          "type": "string",
                          "description": "Provider name, for display."
                        },
                        "plan": {
                          "type": "string",
                          "description": "The plan on that provider."
                        },
                        "servedByInstead": {
                          "type": "object",
                          "nullable": true,
                          "description": "Historical compatibility only. New deployments never switch providers without a new approved placement decision.",
                          "properties": {
                            "provider": {
                              "type": "string"
                            },
                            "providerName": {
                              "type": "string"
                            }
                          }
                        },
                        "free": {
                          "type": "boolean",
                          "description": "True when adding this application to the account costs nothing more. It means the marginal cost is known to be zero, not that the plan has a zero price and not that the numbers were unreadable."
                        },
                        "estimatedMonthlyCost": {
                          "type": "object",
                          "nullable": true,
                          "description": "What adding this application costs beyond the subscription SpringRoll already pays. A range, never a single number: a metered plan's bill depends on traffic nobody has measured yet, and one figure gets quoted back as a price. Null when the cost could not be worked out at all.",
                          "properties": {
                            "minUsd": {
                              "type": "number"
                            },
                            "maxUsd": {
                              "type": "number"
                            },
                            "currency": {
                              "type": "string"
                            },
                            "confidence": {
                              "type": "string",
                              "enum": [
                                "HIGH",
                                "MEDIUM",
                                "LOW",
                                "UNKNOWN"
                              ],
                              "description": "How much the estimate is worth. There is no path to HIGH on a first placement."
                            },
                            "confidenceMeans": {
                              "type": "string"
                            }
                          }
                        },
                        "bestAvailable": {
                          "type": "boolean",
                          "description": "Whether SpringRoll will stand behind the claim that this is the best available placement. False when the price list was stale or the plan's price could not be read. The placement still happened; the superlative did not survive."
                        },
                        "pricing": {
                          "type": "object",
                          "description": "The price list this decision was scored against, so it can be replayed.",
                          "properties": {
                            "version": {
                              "type": "string"
                            },
                            "stale": {
                              "type": "boolean"
                            }
                          }
                        },
                        "meterBreakdown": {
                          "type": "array",
                          "description": "Request, bandwidth, compute, memory, storage, and build evidence behind the estimate. An incomplete required meter prevents a lowest-cost claim.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "meter": {
                                "type": "string",
                                "enum": [
                                  "requests",
                                  "bandwidth",
                                  "compute",
                                  "memory",
                                  "storage",
                                  "build",
                                  "database",
                                  "cache",
                                  "storage-operations"
                                ]
                              },
                              "required": {
                                "type": "boolean"
                              },
                              "expectedUsage": {
                                "type": "number",
                                "nullable": true
                              },
                              "unit": {
                                "type": "string"
                              },
                              "includedUsage": {
                                "nullable": true
                              },
                              "excessUsage": {
                                "type": "number",
                                "nullable": true
                              },
                              "rateUsd": {
                                "type": "number",
                                "nullable": true
                              },
                              "rateUnit": {
                                "type": "string",
                                "nullable": true
                              },
                              "estimatedCostUsd": {
                                "type": "number",
                                "nullable": true
                              },
                              "complete": {
                                "type": "boolean"
                              },
                              "limitation": {
                                "type": "string",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "pricingSources": {
                          "type": "array",
                          "description": "Public evidence frozen with the catalog version, including observation and effective dates.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "pricing",
                                  "terms"
                                ]
                              },
                              "url": {
                                "type": "string",
                                "format": "uri"
                              },
                              "observedAt": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                              },
                              "effectiveAt": {
                                "type": "string",
                                "format": "date-time",
                                "nullable": true
                              }
                            }
                          }
                        },
                        "limitations": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "decidedBy": {
                          "type": "object",
                          "properties": {
                            "source": {
                              "type": "string",
                              "enum": [
                                "AUTOMATIC",
                                "ADMIN_OVERRIDE",
                                "LEGACY_BACKFILL",
                                "MIGRATION"
                              ]
                            },
                            "means": {
                              "type": "string"
                            }
                          }
                        },
                        "assumptions": {
                          "type": "array",
                          "description": "One entry per field SpringRoll had to guess, with the evidence it used. A value the caller declared never appears here, so a reader can always tell measurement from inference.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "field": {
                                "type": "string"
                              },
                              "value": {
                                "type": "string"
                              },
                              "because": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "limits": {
                          "type": "array",
                          "description": "Every way this plan is worse than paying: sleeping when idle, stopping at a usage cap, cold starts, no backups, no availability commitment. Tell the user these before they rely on the application.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string"
                              },
                              "means": {
                                "type": "string"
                              },
                              "detail": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "notChosen": {
                          "type": "array",
                          "description": "Every candidate that lost, with the first reason it lost. This is the half that makes the receipt an argument a reader can check rather than an assertion, so it is worth rendering rather than ignoring.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "provider": {
                                "type": "string"
                              },
                              "plan": {
                                "type": "string"
                              },
                              "reason": {
                                "type": "string",
                                "enum": [
                                  "TERMS_INELIGIBLE",
                                  "UNSUITABLE_ENVIRONMENT",
                                  "NO_MANAGED_CAPACITY",
                                  "RUNTIME_UNSUPPORTED",
                                  "UNMET_REQUIREMENT",
                                  "UNSUPPORTED_SOURCE",
                                  "INVALID_REGION",
                                  "DATA_POLICY_CONFLICT",
                                  "OVER_BUDGET"
                                ]
                              },
                              "means": {
                                "type": "string"
                              },
                              "detail": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "billingOwner": {
                          "type": "object",
                          "description": "Who pays the provider for the plan this receipt describes. Released placements use SpringRoll-managed Vercel and Cloudflare accounts.",
                          "properties": {
                            "owner": {
                              "type": "string",
                              "enum": [
                                "SPRINGROLL",
                                "CUSTOMER"
                              ]
                            },
                            "means": {
                              "type": "string"
                            }
                          }
                        },
                        "recommendedInstead": {
                          "type": "object",
                          "nullable": true,
                          "description": "Historical compatibility only. New placements bind recommendation and execution to the same exact managed target.",
                          "properties": {
                            "provider": {
                              "type": "string"
                            },
                            "providerName": {
                              "type": "string"
                            },
                            "plan": {
                              "type": "string"
                            },
                            "planName": {
                              "type": "string"
                            },
                            "readiness": {
                              "type": "string",
                              "enum": [
                                "managed_ready",
                                "managed_activation_required",
                                "connection_required",
                                "connected",
                                "upgrade_required",
                                "verified",
                                "deployable",
                                "invalid_connection",
                                "unavailable"
                              ]
                            },
                            "means": {
                              "type": "string"
                            },
                            "action": {
                              "type": "string",
                              "nullable": true,
                              "description": "What makes the recommended plan deployable, when something does."
                            }
                          }
                        },
                        "executionReadiness": {
                          "type": "object",
                          "description": "Whether this organization could execute a deployment onto the described plan when the receipt was written. An action vocabulary, not a verdict: connection_required means connect an account to deploy, never rejected. On a recorded deployment this is always an executable state, because a decision only ever binds a target that could actually deploy.",
                          "properties": {
                            "state": {
                              "type": "string",
                              "enum": [
                                "managed_ready",
                                "managed_activation_required",
                                "connection_required",
                                "connected",
                                "upgrade_required",
                                "verified",
                                "deployable",
                                "invalid_connection",
                                "unavailable"
                              ]
                            },
                            "means": {
                              "type": "string"
                            },
                            "action": {
                              "type": "string",
                              "nullable": true
                            }
                          }
                        },
                        "alternatives": {
                          "type": "array",
                          "description": "Ranked also-eligible active Vercel and Cloudflare plans, best first. Managed-account readiness never removes or reorders an entry, and it cannot promote an alternative into execution.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "provider": {
                                "type": "string"
                              },
                              "providerName": {
                                "type": "string"
                              },
                              "plan": {
                                "type": "string"
                              },
                              "planName": {
                                "type": "string"
                              },
                              "free": {
                                "type": "boolean"
                              },
                              "estimatedMonthlyCost": {
                                "type": "object",
                                "nullable": true,
                                "properties": {
                                  "minUsd": {
                                    "type": "number"
                                  },
                                  "maxUsd": {
                                    "type": "number"
                                  }
                                }
                              },
                              "eligibility": {
                                "type": "string",
                                "enum": [
                                  "eligible",
                                  "ineligible",
                                  "unknown",
                                  "quote_required"
                                ]
                              },
                              "billingOwner": {
                                "type": "string",
                                "enum": [
                                  "SPRINGROLL",
                                  "CUSTOMER"
                                ]
                              },
                              "readiness": {
                                "type": "string",
                                "enum": [
                                  "managed_ready",
                                  "managed_activation_required",
                                  "connection_required",
                                  "connected",
                                  "upgrade_required",
                                  "verified",
                                  "deployable",
                                  "invalid_connection",
                                  "unavailable"
                                ]
                              },
                              "action": {
                                "type": "string",
                                "nullable": true
                              },
                              "meterBreakdown": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                }
                              },
                              "billingProjection": {
                                "type": "object",
                                "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                                "required": [
                                  "version",
                                  "basis",
                                  "components",
                                  "unmodeledCharges"
                                ],
                                "properties": {
                                  "version": {
                                    "type": "integer",
                                    "enum": [
                                      1
                                    ]
                                  },
                                  "basis": {
                                    "type": "string",
                                    "enum": [
                                      "monthly-usage-before-allowances-and-credits"
                                    ]
                                  },
                                  "builderBackend": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-sandbox",
                                      "external"
                                    ],
                                    "description": "Build service used when the cost snapshot was calculated."
                                  },
                                  "artifactStore": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-blob",
                                      "filesystem",
                                      "unknown"
                                    ],
                                    "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                                  },
                                  "components": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "key": {
                                          "type": "string"
                                        },
                                        "label": {
                                          "type": "string"
                                        },
                                        "unit": {
                                          "type": "string"
                                        },
                                        "billingScope": {
                                          "type": "string",
                                          "enum": [
                                            "vercel-infrastructure",
                                            "neon-integration",
                                            "upstash-integration",
                                            "cloudflare-account",
                                            "external-or-unverified"
                                          ],
                                          "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                                        },
                                        "expectedUsage": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "rateMinUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "rateMaxUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "grossMinUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "grossMaxUsd": {
                                          "type": [
                                            "number",
                                            "null"
                                          ]
                                        },
                                        "observedAt": {
                                          "type": [
                                            "string",
                                            "null"
                                          ],
                                          "format": "date-time"
                                        },
                                        "source": {
                                          "type": "string",
                                          "format": "uri"
                                        },
                                        "limitation": {
                                          "type": [
                                            "string",
                                            "null"
                                          ]
                                        }
                                      }
                                    }
                                  },
                                  "unmodeledCharges": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  }
                                }
                              },
                              "pricingSources": {
                                "type": "array",
                                "items": {
                                  "type": "object"
                                }
                              },
                              "limitations": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "provisionedCapabilities": {
                      "type": "object",
                      "description": "Safe runtime capability metadata. Credentials and provider account identifiers are never included.",
                      "properties": {
                        "billingProjection": {
                          "type": "object",
                          "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                          "required": [
                            "version",
                            "basis",
                            "components",
                            "unmodeledCharges"
                          ],
                          "properties": {
                            "version": {
                              "type": "integer",
                              "enum": [
                                1
                              ]
                            },
                            "basis": {
                              "type": "string",
                              "enum": [
                                "monthly-usage-before-allowances-and-credits"
                              ]
                            },
                            "builderBackend": {
                              "type": "string",
                              "enum": [
                                "vercel-sandbox",
                                "external"
                              ],
                              "description": "Build service used when the cost snapshot was calculated."
                            },
                            "artifactStore": {
                              "type": "string",
                              "enum": [
                                "vercel-blob",
                                "filesystem",
                                "unknown"
                              ],
                              "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                            },
                            "components": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "key": {
                                    "type": "string"
                                  },
                                  "label": {
                                    "type": "string"
                                  },
                                  "unit": {
                                    "type": "string"
                                  },
                                  "billingScope": {
                                    "type": "string",
                                    "enum": [
                                      "vercel-infrastructure",
                                      "neon-integration",
                                      "upstash-integration",
                                      "cloudflare-account",
                                      "external-or-unverified"
                                    ],
                                    "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                                  },
                                  "expectedUsage": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "rateMinUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "rateMaxUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "grossMinUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "grossMaxUsd": {
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "observedAt": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "format": "date-time"
                                  },
                                  "source": {
                                    "type": "string",
                                    "format": "uri"
                                  },
                                  "limitation": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                }
                              }
                            },
                            "unmodeledCharges": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "billing": {
                          "type": "object",
                          "description": "Observed plans for this application's data resources, frozen at deployment. No usage totals or credentials.",
                          "additionalProperties": {
                            "type": "object",
                            "required": [
                              "version",
                              "product",
                              "planId",
                              "scope",
                              "observedAt",
                              "currency",
                              "rates",
                              "includedCommandsPerMonth",
                              "source"
                            ],
                            "properties": {
                              "version": {
                                "type": "integer",
                                "enum": [
                                  1
                                ]
                              },
                              "product": {
                                "type": "string",
                                "enum": [
                                  "neon",
                                  "upstash-kv"
                                ]
                              },
                              "planId": {
                                "type": "string",
                                "enum": [
                                  "launch_v3",
                                  "free",
                                  "paid"
                                ]
                              },
                              "scope": {
                                "type": "string",
                                "enum": [
                                  "installation",
                                  "resource"
                                ]
                              },
                              "observedAt": {
                                "type": "string",
                                "format": "date-time"
                              },
                              "currency": {
                                "type": "string",
                                "enum": [
                                  "USD"
                                ]
                              },
                              "rates": {
                                "type": "object",
                                "properties": {
                                  "perCuHourUsd": {
                                    "type": "number",
                                    "minimum": 0
                                  },
                                  "perGbMonthUsd": {
                                    "type": "number",
                                    "minimum": 0
                                  },
                                  "per100kCommandsUsd": {
                                    "type": "number",
                                    "minimum": 0
                                  }
                                }
                              },
                              "includedCommandsPerMonth": {
                                "type": [
                                  "integer",
                                  "null"
                                ],
                                "minimum": 0
                              },
                              "source": {
                                "type": "string",
                                "format": "uri"
                              }
                            }
                          }
                        },
                        "storage": {
                          "type": "object",
                          "required": [
                            "kind",
                            "access",
                            "scope",
                            "baseUrl"
                          ],
                          "properties": {
                            "kind": {
                              "type": "string",
                              "enum": [
                                "object-storage"
                              ]
                            },
                            "access": {
                              "type": "string",
                              "enum": [
                                "public"
                              ]
                            },
                            "scope": {
                              "type": "string",
                              "enum": [
                                "application"
                              ]
                            },
                            "baseUrl": {
                              "type": "string",
                              "format": "uri"
                            },
                            "binding": {
                              "type": "string",
                              "enum": [
                                "STORAGE"
                              ]
                            },
                            "containerEndpointVariable": {
                              "type": "string",
                              "enum": [
                                "SPRINGROLL_CONTAINER_STORAGE_URL"
                              ]
                            }
                          }
                        },
                        "database": {
                          "type": "object",
                          "required": [
                            "kind",
                            "scope",
                            "engine",
                            "connection"
                          ],
                          "properties": {
                            "kind": {
                              "type": "string",
                              "enum": [
                                "database"
                              ]
                            },
                            "scope": {
                              "type": "string",
                              "enum": [
                                "application"
                              ]
                            },
                            "engine": {
                              "type": "string",
                              "enum": [
                                "postgres",
                                "sqlite"
                              ]
                            },
                            "connection": {
                              "type": "string",
                              "enum": [
                                "environment",
                                "binding"
                              ]
                            },
                            "variable": {
                              "type": "string",
                              "enum": [
                                "DATABASE_URL"
                              ]
                            },
                            "binding": {
                              "type": "string",
                              "enum": [
                                "DB"
                              ]
                            },
                            "containerEndpointVariable": {
                              "type": "string",
                              "enum": [
                                "SPRINGROLL_CONTAINER_DATABASE_URL"
                              ]
                            }
                          }
                        }
                      }
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "502": {
            "$ref": "#/components/responses/Error502"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}/approval-requests": {
      "get": {
        "operationId": "listApprovalRequests",
        "summary": "List approval requests",
        "description": "Approval requests raised for this application, newest first.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Restrict to one status.",
            "schema": {
              "type": "string",
              "enum": [
                "PENDING",
                "APPROVED",
                "REJECTED",
                "CHANGES_REQUESTED",
                "WITHDRAWN",
                "EXPIRED"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum records to return.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Records to skip.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of approval requests.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "total",
                    "items"
                  ],
                  "properties": {
                    "total": {
                      "type": "integer",
                      "description": "Total matching records, ignoring limit and offset."
                    },
                    "items": {
                      "type": "array",
                      "description": "The approval requests.",
                      "items": {
                        "type": "object",
                        "description": "A decision waiting on a person, with the evidence frozen beside it.",
                        "required": [
                          "id",
                          "status"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Opaque server-assigned identifier. Do not construct one."
                          },
                          "applicationId": {
                            "type": "string",
                            "description": "Opaque server-assigned identifier. Do not construct one."
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "UAT_PROMOTION",
                              "PRODUCTION_PROMOTION",
                              "UAT_SIGN_OFF",
                              "DATA_ACCESS_GRANT",
                              "VISIBILITY_CHANGE",
                              "OWNERSHIP_TRANSFER",
                              "ROLLBACK",
                              "RETIREMENT",
                              "DOMAIN_CHANGE",
                              "ACCESS_REQUEST"
                            ],
                            "description": "What is being asked for."
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "PENDING",
                              "APPROVED",
                              "REJECTED",
                              "CHANGES_REQUESTED",
                              "WITHDRAWN",
                              "EXPIRED"
                            ],
                            "description": "PENDING until a person decides."
                          },
                          "requestedBy": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "RFC 3339 timestamp, always UTC."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      },
      "post": {
        "operationId": "createApprovalRequest",
        "summary": "Submit an approval request",
        "description": "Asks for a decision, with the evidence frozen alongside it. An agent may submit a request; it may never decide one.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Replays safely: the same key with the same body returns the original result, and with a different body returns IDEMPOTENCY_CONFLICT. Send one on every write an agent might retry.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "What is being asked for.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "kind"
                ],
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "UAT_PROMOTION",
                      "PRODUCTION_PROMOTION",
                      "UAT_SIGN_OFF",
                      "DATA_ACCESS_GRANT",
                      "VISIBILITY_CHANGE",
                      "OWNERSHIP_TRANSFER",
                      "ROLLBACK",
                      "RETIREMENT",
                      "DOMAIN_CHANGE",
                      "ACCESS_REQUEST"
                    ],
                    "description": "The class of decision required."
                  },
                  "justification": {
                    "type": "string",
                    "description": "Why. Shown to the reviewer beside the evidence."
                  },
                  "deploymentId": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The approval request.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A decision waiting on a person, with the evidence frozen beside it.",
                  "required": [
                    "id",
                    "status"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "applicationId": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "UAT_PROMOTION",
                        "PRODUCTION_PROMOTION",
                        "UAT_SIGN_OFF",
                        "DATA_ACCESS_GRANT",
                        "VISIBILITY_CHANGE",
                        "OWNERSHIP_TRANSFER",
                        "ROLLBACK",
                        "RETIREMENT",
                        "DOMAIN_CHANGE",
                        "ACCESS_REQUEST"
                      ],
                      "description": "What is being asked for."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "PENDING",
                        "APPROVED",
                        "REJECTED",
                        "CHANGES_REQUESTED",
                        "WITHDRAWN",
                        "EXPIRED"
                      ],
                      "description": "PENDING until a person decides."
                    },
                    "requestedBy": {
                      "type": "string"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/approval-requests/{requestId}/decisions": {
      "get": {
        "operationId": "listApprovalDecisions",
        "summary": "List decisions on a request",
        "description": "Every decision recorded against this request, with the deciding person and the time. Safe for an agent to read while waiting.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "requestId",
            "in": "path",
            "required": true,
            "description": "Approval request id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The decisions.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "total",
                    "items"
                  ],
                  "properties": {
                    "total": {
                      "type": "integer",
                      "description": "Total matching records, ignoring limit and offset."
                    },
                    "items": {
                      "type": "array",
                      "description": "The recorded decisions.",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "decision",
                          "createdAt"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Opaque server-assigned identifier. Do not construct one."
                          },
                          "decision": {
                            "type": "string",
                            "enum": [
                              "APPROVE",
                              "REJECT",
                              "REQUEST_CHANGES"
                            ]
                          },
                          "decidedBy": {
                            "type": "string"
                          },
                          "note": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "RFC 3339 timestamp, always UTC."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      },
      "post": {
        "operationId": "createApprovalDecision",
        "summary": "Record a decision",
        "description": "Approves or rejects a request. Requires a human session with the approver permission. An agent token is refused with FORBIDDEN, by design, and no configuration changes that.",
        "tags": [
          "Approvals"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "requestId",
            "in": "path",
            "required": true,
            "description": "Approval request id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Replays safely: the same key with the same body returns the original result, and with a different body returns IDEMPOTENCY_CONFLICT. Send one on every write an agent might retry.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The decision.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "decision"
                ],
                "properties": {
                  "decision": {
                    "type": "string",
                    "enum": [
                      "APPROVE",
                      "REJECT",
                      "REQUEST_CHANGES"
                    ]
                  },
                  "note": {
                    "type": "string",
                    "description": "Recorded permanently with the decision."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The recorded decision.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "decision"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "decision": {
                      "type": "string",
                      "enum": [
                        "APPROVE",
                        "REJECT",
                        "REQUEST_CHANGES"
                      ]
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/apps/{appId}/data-access": {
      "get": {
        "operationId": "listDataAccessGrants",
        "summary": "List data access grants",
        "description": "What this application may read, and what it has asked for. Read this before requesting again: a duplicate request is refused.",
        "tags": [
          "Data access"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum records to return.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Records to skip.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of grants.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "total",
                    "items"
                  ],
                  "properties": {
                    "total": {
                      "type": "integer",
                      "description": "Total matching records, ignoring limit and offset."
                    },
                    "items": {
                      "type": "array",
                      "description": "The grants and requests.",
                      "items": {
                        "type": "object",
                        "description": "What a deployed application is allowed to read from one data product. The application never receives the source credential.",
                        "required": [
                          "id",
                          "status"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Opaque server-assigned identifier. Do not construct one."
                          },
                          "dataProductSlug": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "REQUESTED",
                              "APPROVED",
                              "REJECTED",
                              "REVOKED",
                              "EXPIRED"
                            ],
                            "description": "REQUESTED until a data owner decides; GRANTED once enforced at the gateway."
                          },
                          "fields": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "The approved columns. Anything else is refused at query time."
                          },
                          "queriesPerMinute": {
                            "type": "integer",
                            "description": "Approved query volume for this application against this product."
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "RFC 3339 timestamp, always UTC."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      },
      "post": {
        "operationId": "requestDataAccess",
        "summary": "Request data access",
        "description": "Asks a data owner to let this application read a data product. The application never receives the source credential: an approved grant injects a scoped identity and is enforced at the gateway, so it can be revoked without redeploying.",
        "tags": [
          "Data access"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appId",
            "in": "path",
            "required": true,
            "description": "Application id or slug.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Replays safely: the same key with the same body returns the original result, and with a different body returns IDEMPOTENCY_CONFLICT. Send one on every write an agent might retry.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "What the application needs, and why.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "dataProductSlug"
                ],
                "properties": {
                  "dataProductSlug": {
                    "type": "string",
                    "description": "The data product to read."
                  },
                  "fields": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "The columns needed. Ask for the fewest that work; a broad request is likelier to be refused."
                  },
                  "justification": {
                    "type": "string",
                    "description": "Shown to the data owner."
                  },
                  "queriesPerMinute": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Expected query volume."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The access request.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "What a deployed application is allowed to read from one data product. The application never receives the source credential.",
                  "required": [
                    "id",
                    "status"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Opaque server-assigned identifier. Do not construct one."
                    },
                    "dataProductSlug": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "REQUESTED",
                        "APPROVED",
                        "REJECTED",
                        "REVOKED",
                        "EXPIRED"
                      ],
                      "description": "REQUESTED until a data owner decides; GRANTED once enforced at the gateway."
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The approved columns. Anything else is refused at query time."
                    },
                    "queriesPerMinute": {
                      "type": "integer",
                      "description": "Approved query volume for this application against this product."
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "RFC 3339 timestamp, always UTC."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "409": {
            "$ref": "#/components/responses/Error409"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/connectors": {
      "get": {
        "operationId": "listConnectors",
        "summary": "List connectors",
        "description": "Connector definitions available in this organization, with their names, kinds, and scopes. Credentials are write-only and are never returned.",
        "tags": [
          "Data access"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum records to return.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Records to skip.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of connectors.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "total",
                    "items"
                  ],
                  "properties": {
                    "total": {
                      "type": "integer",
                      "description": "Total matching records, ignoring limit and offset."
                    },
                    "items": {
                      "type": "array",
                      "description": "The connectors.",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "slug",
                          "name"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Opaque server-assigned identifier. Do not construct one."
                          },
                          "slug": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "kind": {
                            "type": "string",
                            "description": "What kind of system it reaches."
                          },
                          "scopes": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/data/v1/schema": {
      "get": {
        "operationId": "getGovernedSchema",
        "summary": "Describe the data a grant allows",
        "description": "SpringRoll Connect. Called by a deployed application with its own identity token, not by an agent. Returns exactly the tables and columns its grants permit, and nothing about the wider source.",
        "tags": [
          "Data access"
        ],
        "security": [
          {
            "appIdentity": []
          }
        ],
        "responses": {
          "200": {
            "description": "The permitted schema.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "description": "Tables and columns this application may read."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "504": {
            "$ref": "#/components/responses/Error504"
          }
        }
      }
    },
    "/api/data/v1/ask": {
      "post": {
        "operationId": "askGovernedData",
        "summary": "Query governed data",
        "description": "SpringRoll Connect. Runs a query on behalf of a deployed application, enforced against its grants: a column outside the grant is refused rather than filtered, and query volume is capped per grant. Answers TIMEOUT when a source exceeds the allowance, which the caller can act on by asking for less.",
        "tags": [
          "Data access"
        ],
        "security": [
          {
            "appIdentity": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The question.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "query"
                ],
                "properties": {
                  "query": {
                    "type": "string",
                    "description": "The query to run, within the granted scope."
                  },
                  "parameters": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Bound parameters. Always prefer these to string interpolation."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The result set.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "rows": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    },
                    "truncated": {
                      "type": "boolean",
                      "description": "True when the grant's row limit cut the result short."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          },
          "502": {
            "$ref": "#/components/responses/Error502"
          },
          "504": {
            "$ref": "#/components/responses/Error504"
          }
        }
      }
    },
    "/api/data/v1/explain": {
      "post": {
        "operationId": "explainGovernedQuery",
        "summary": "Explain a governed query",
        "description": "Returns what a query would touch and whether the grant permits it, without running it. Cheaper than a refused query, and the right thing for an agent to call before asking a user to widen a grant.",
        "tags": [
          "Data access"
        ],
        "security": [
          {
            "appIdentity": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The query to explain.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "query"
                ],
                "properties": {
                  "query": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The explanation.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "allowed": {
                      "type": "boolean"
                    },
                    "reason": {
                      "type": "string"
                    },
                    "columns": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/v1/tenants/{tenant}/audit-events": {
      "get": {
        "operationId": "listAuditEvents",
        "summary": "List audit events",
        "description": "The append-only record of governed actions, newest first. The table refuses UPDATE and DELETE at the database level, so what is returned here is what happened.",
        "tags": [
          "Audit"
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "description": "Organization slug or id. Always verified against the caller's memberships: a tenant id in the path is not authorization.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "action",
            "in": "query",
            "required": false,
            "description": "Restrict to one action.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "description": "Only events at or after this time.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum records to return.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Records to skip.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of audit events.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "total",
                    "items"
                  ],
                  "properties": {
                    "total": {
                      "type": "integer",
                      "description": "Total matching records, ignoring limit and offset."
                    },
                    "items": {
                      "type": "array",
                      "description": "The events.",
                      "items": {
                        "type": "object",
                        "description": "One appended audit event. The table refuses UPDATE and DELETE, and each row carries a hash of the previous one.",
                        "required": [
                          "id",
                          "action",
                          "createdAt"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Opaque server-assigned identifier. Do not construct one."
                          },
                          "action": {
                            "type": "string",
                            "description": "The governed action that occurred."
                          },
                          "actor": {
                            "type": "string",
                            "description": "Who or what did it."
                          },
                          "resourceType": {
                            "type": "string"
                          },
                          "resourceId": {
                            "type": "string"
                          },
                          "correlationId": {
                            "type": "string",
                            "description": "Ties the event to the request that caused it."
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time",
                            "description": "RFC 3339 timestamp, always UTC."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "403": {
            "$ref": "#/components/responses/Error403"
          },
          "404": {
            "$ref": "#/components/responses/Error404"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/mcp": {
      "post": {
        "operationId": "callMcpEndpoint",
        "summary": "Model Context Protocol endpoint",
        "description": "The primary agent interface: JSON-RPC 2.0 over Streamable HTTP, exposing the whole control plane as tools, resources, and prompts. Prefer this over the REST endpoints above. An unauthenticated request answers 401 with a WWW-Authenticate challenge naming the authorization server, which is how a client discovers where to register. See /.well-known/mcp/server-card.json for the Server Card.",
        "tags": [
          "MCP"
        ],
        "requestBody": {
          "required": true,
          "description": "A JSON-RPC 2.0 request.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jsonrpc",
                  "method"
                ],
                "properties": {
                  "jsonrpc": {
                    "type": "string",
                    "enum": [
                      "2.0"
                    ]
                  },
                  "id": {
                    "description": "Request id. Omitted for a notification."
                  },
                  "method": {
                    "type": "string",
                    "description": "An MCP method: initialize, tools/list, tools/call, resources/list, prompts/list."
                  },
                  "params": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A JSON-RPC 2.0 response.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "jsonrpc"
                  ],
                  "properties": {
                    "jsonrpc": {
                      "type": "string",
                      "enum": [
                        "2.0"
                      ]
                    },
                    "id": {},
                    "result": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "error": {
                      "type": "object",
                      "description": "A JSON-RPC error. Distinct from the REST envelope.",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      },
      "get": {
        "operationId": "getMcpEndpoint",
        "summary": "Server-sent events (unsupported)",
        "description": "Answers 405. This deployment implements Streamable HTTP only; the deprecated HTTP+SSE transport is deliberately not offered.",
        "tags": [
          "MCP"
        ],
        "security": [],
        "responses": {
          "405": {
            "description": "Use POST with Streamable HTTP.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/mcp/server-card.json": {
      "get": {
        "operationId": "getMcpManifest",
        "summary": "MCP Server Card",
        "description": "Unauthenticated manifest describing the MCP server: its name and version, the Streamable HTTP endpoint, the OAuth 2.1 discovery documents, and every tool with its summary and read-only flag.",
        "tags": [
          "MCP",
          "Discovery"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "The manifest.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "name",
                    "version",
                    "transport",
                    "endpoint",
                    "tools"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "transport": {
                      "type": "string",
                      "enum": [
                        "streamable-http"
                      ]
                    },
                    "endpoint": {
                      "type": "string",
                      "format": "uri"
                    },
                    "authorization": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "tools": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/.well-known/oauth-authorization-server": {
      "get": {
        "operationId": "getOauthAuthorizationServerMetadata",
        "summary": "Authorization server metadata",
        "description": "RFC 8414 metadata for the authorization server backing the MCP endpoint: the authorization, token, registration, and revocation endpoints, the supported grant types, and PKCE methods. A client reads this instead of being configured.",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "RFC 8414 metadata.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/.well-known/oauth-protected-resource": {
      "get": {
        "operationId": "getOauthProtectedResourceMetadata",
        "summary": "Protected resource metadata",
        "description": "RFC 9728 metadata naming which authorization servers may issue tokens for this resource. Fetched by a client that received a 401 challenge from the MCP endpoint.",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "RFC 9728 metadata.",
            "headers": {
              "x-correlation-id": {
                "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";r=598;t=42"
              },
              "RateLimit-Policy": {
                "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
                "schema": {
                  "type": "string"
                },
                "example": "\"read\";q=600;w=60"
              },
              "RateLimit-Limit": {
                "description": "Requests allowed in the current window.",
                "schema": {
                  "type": "integer"
                },
                "example": 600
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the current window.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
                "schema": {
                  "type": "integer"
                }
              },
              "Deprecation": {
                "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
                "schema": {
                  "type": "string"
                }
              },
              "Sunset": {
                "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/oauth/register": {
      "post": {
        "operationId": "registerOauthClient",
        "summary": "Register a client",
        "description": "RFC 7591 dynamic client registration. A redirect URI must be https, loopback http, or a reverse-domain private-use scheme. A bare custom scheme is refused, because two clients could collide and receive each other's authorization codes. Tightly rate limited: this is an unauthenticated write.",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "description": "RFC 7591 client metadata.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "redirect_uris"
                ],
                "properties": {
                  "client_name": {
                    "type": "string"
                  },
                  "redirect_uris": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "grant_types": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "token_endpoint_auth_method": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The registered client.",
            "headers": {},
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "client_id"
                  ],
                  "properties": {
                    "client_id": {
                      "type": "string"
                    },
                    "client_secret": {
                      "type": "string",
                      "description": "Present only for a confidential client. Shown exactly once."
                    },
                    "redirect_uris": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/oauth/token": {
      "post": {
        "operationId": "exchangeOauthToken",
        "summary": "Token endpoint",
        "description": "RFC 6749 token endpoint with PKCE. Exchanges an authorization code, or refreshes an access token. Every issued credential resolves to exactly one membership, so an agent acts as a named person and inherits only that person's permissions.",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "description": "Form-encoded, per RFC 6749.",
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type"
                ],
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "authorization_code",
                      "refresh_token"
                    ]
                  },
                  "code": {
                    "type": "string"
                  },
                  "code_verifier": {
                    "type": "string",
                    "description": "The PKCE verifier."
                  },
                  "refresh_token": {
                    "type": "string"
                  },
                  "client_id": {
                    "type": "string"
                  },
                  "redirect_uri": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The issued tokens.",
            "headers": {},
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "access_token",
                    "token_type"
                  ],
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "token_type": {
                      "type": "string",
                      "enum": [
                        "Bearer"
                      ]
                    },
                    "expires_in": {
                      "type": "integer"
                    },
                    "refresh_token": {
                      "type": "string"
                    },
                    "scope": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Error401"
          },
          "422": {
            "$ref": "#/components/responses/Error422"
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    },
    "/api/oauth/revoke": {
      "post": {
        "operationId": "revokeOauthToken",
        "summary": "Revocation endpoint",
        "description": "RFC 7009 revocation. Answers 200 whether or not the token existed, as the specification requires, so it cannot be used to probe for valid tokens.",
        "tags": [
          "Discovery"
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "description": "Form-encoded, per RFC 7009.",
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string"
                  },
                  "token_type_hint": {
                    "type": "string"
                  },
                  "client_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Revoked, or the token did not exist."
          },
          "429": {
            "$ref": "#/components/responses/Error429"
          },
          "500": {
            "$ref": "#/components/responses/Error500"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "description": "The single error envelope every endpoint uses. `code` is stable and safe to branch on; `message` is for humans and may change wording. Never parse `message`.",
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "correlationId"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "UNAUTHENTICATED",
                  "FORBIDDEN",
                  "TENANT_NOT_RESOLVED",
                  "NOT_FOUND",
                  "CONFLICT",
                  "VALIDATION_FAILED",
                  "POLICY_BLOCKED",
                  "APPROVAL_REQUIRED",
                  "INVALID_LIFECYCLE_TRANSITION",
                  "IDEMPOTENCY_CONFLICT",
                  "RATE_LIMITED",
                  "PROVIDER_ERROR",
                  "NOT_CONFIGURED",
                  "TIMEOUT",
                  "INTERNAL"
                ],
                "description": "Stable machine-readable failure reason. Branch on this, not on the HTTP status, which several codes share."
              },
              "message": {
                "type": "string",
                "description": "Human-readable explanation. For a 5xx this is deliberately generic, so quote the correlation id instead."
              },
              "details": {
                "type": "object",
                "additionalProperties": true,
                "description": "Structured context for the failure: field-level validation issues, the retry delay for RATE_LIMITED, the blocking policy for POLICY_BLOCKED. Omitted for 5xx responses."
              },
              "nextActions": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "What the caller can do about it, in order. Present when the failure is recoverable: an agent should read this before retrying."
              },
              "correlationId": {
                "type": "string",
                "description": "Identifies this request in the audit log. Echoed in the x-correlation-id response header, and honoured on the way in if you send one."
              }
            }
          }
        }
      },
      "Application": {
        "type": "object",
        "description": "A registered application.",
        "required": [
          "id",
          "slug",
          "name",
          "lifecycleStatus"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque server-assigned identifier. Do not construct one."
          },
          "slug": {
            "type": "string",
            "description": "Stable, URL-safe name, unique inside the organization."
          },
          "name": {
            "type": "string",
            "description": "Display name."
          },
          "description": {
            "type": "string"
          },
          "lifecycleStatus": {
            "type": "string",
            "enum": [
              "DEV",
              "UAT",
              "PRODUCTION",
              "SUSPENDED",
              "DEPRECATED",
              "RETIRED"
            ],
            "description": "Where the application is in its life: only PRODUCTION and DEPRECATED appear in the App Portal."
          },
          "dataClassification": {
            "type": "string",
            "enum": [
              "public",
              "internal",
              "confidential",
              "restricted"
            ],
            "description": "The most sensitive class of data the application is cleared for."
          },
          "ownerEmail": {
            "type": "string",
            "format": "email"
          },
          "supportContact": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339 timestamp, always UTC."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339 timestamp, always UTC."
          }
        }
      },
      "Bundle": {
        "type": "object",
        "description": "An immutable release. Once created its contents and digest never change, which is what makes a promotion auditable.",
        "required": [
          "id",
          "digest"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque server-assigned identifier. Do not construct one."
          },
          "digest": {
            "type": "string",
            "description": "Content hash of the uploaded archive. Verify this rather than trusting the id."
          },
          "version": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339 timestamp, always UTC."
          }
        }
      },
      "Deployment": {
        "type": "object",
        "description": "One deployment of one immutable release into one environment.",
        "required": [
          "id",
          "environment",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque server-assigned identifier. Do not construct one."
          },
          "applicationId": {
            "type": "string",
            "description": "Opaque server-assigned identifier. Do not construct one."
          },
          "bundleId": {
            "type": "string",
            "description": "The immutable release that was deployed. Promotion reuses this rather than rebuilding."
          },
          "environment": {
            "type": "string",
            "enum": [
              "development",
              "uat",
              "production"
            ],
            "description": "Which environment this deployment serves."
          },
          "status": {
            "type": "string",
            "enum": [
              "QUEUED",
              "VALIDATING",
              "BUILDING",
              "DEPLOYING",
              "READY",
              "FAILED",
              "CANCELLED",
              "SUPERSEDED",
              "ROLLED_BACK"
            ],
            "description": "Lifecycle of the deployment attempt itself, not of the application."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The live URL, once the deployment is serving. Absent until then."
          },
          "placement": {
            "type": "object",
            "description": "Where SpringRoll decided to run this application, and why. Null for an application on a runtime the organization configured for itself, and for every deployment that predates automatic placement.",
            "properties": {
              "references": {
                "type": "object",
                "description": "Immutable references for the decision, independent recommendation, and exact managed runtime configuration.",
                "properties": {
                  "decisionId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "recommendationId": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true
                  },
                  "runtimeConfigurationId": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true
                  }
                }
              },
              "recommended": {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "vercel",
                      "cloudflare"
                    ]
                  },
                  "providerName": {
                    "type": "string"
                  },
                  "plan": {
                    "type": "string"
                  },
                  "planName": {
                    "type": "string"
                  }
                }
              },
              "executed": {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": [
                      "vercel",
                      "cloudflare"
                    ]
                  },
                  "providerName": {
                    "type": "string"
                  },
                  "plan": {
                    "type": "string"
                  },
                  "planName": {
                    "type": "string"
                  },
                  "runtimeConfigurationId": {
                    "type": "string",
                    "format": "uuid",
                    "nullable": true
                  }
                }
              },
              "provider": {
                "type": "string",
                "description": "Provider identifier."
              },
              "providerName": {
                "type": "string",
                "description": "Provider name, for display."
              },
              "plan": {
                "type": "string",
                "description": "The plan on that provider."
              },
              "servedByInstead": {
                "type": "object",
                "nullable": true,
                "description": "Historical compatibility only. New deployments never switch providers without a new approved placement decision.",
                "properties": {
                  "provider": {
                    "type": "string"
                  },
                  "providerName": {
                    "type": "string"
                  }
                }
              },
              "free": {
                "type": "boolean",
                "description": "True when adding this application to the account costs nothing more. It means the marginal cost is known to be zero, not that the plan has a zero price and not that the numbers were unreadable."
              },
              "estimatedMonthlyCost": {
                "type": "object",
                "nullable": true,
                "description": "What adding this application costs beyond the subscription SpringRoll already pays. A range, never a single number: a metered plan's bill depends on traffic nobody has measured yet, and one figure gets quoted back as a price. Null when the cost could not be worked out at all.",
                "properties": {
                  "minUsd": {
                    "type": "number"
                  },
                  "maxUsd": {
                    "type": "number"
                  },
                  "currency": {
                    "type": "string"
                  },
                  "confidence": {
                    "type": "string",
                    "enum": [
                      "HIGH",
                      "MEDIUM",
                      "LOW",
                      "UNKNOWN"
                    ],
                    "description": "How much the estimate is worth. There is no path to HIGH on a first placement."
                  },
                  "confidenceMeans": {
                    "type": "string"
                  }
                }
              },
              "bestAvailable": {
                "type": "boolean",
                "description": "Whether SpringRoll will stand behind the claim that this is the best available placement. False when the price list was stale or the plan's price could not be read. The placement still happened; the superlative did not survive."
              },
              "pricing": {
                "type": "object",
                "description": "The price list this decision was scored against, so it can be replayed.",
                "properties": {
                  "version": {
                    "type": "string"
                  },
                  "stale": {
                    "type": "boolean"
                  }
                }
              },
              "meterBreakdown": {
                "type": "array",
                "description": "Request, bandwidth, compute, memory, storage, and build evidence behind the estimate. An incomplete required meter prevents a lowest-cost claim.",
                "items": {
                  "type": "object",
                  "properties": {
                    "meter": {
                      "type": "string",
                      "enum": [
                        "requests",
                        "bandwidth",
                        "compute",
                        "memory",
                        "storage",
                        "build",
                        "database",
                        "cache",
                        "storage-operations"
                      ]
                    },
                    "required": {
                      "type": "boolean"
                    },
                    "expectedUsage": {
                      "type": "number",
                      "nullable": true
                    },
                    "unit": {
                      "type": "string"
                    },
                    "includedUsage": {
                      "nullable": true
                    },
                    "excessUsage": {
                      "type": "number",
                      "nullable": true
                    },
                    "rateUsd": {
                      "type": "number",
                      "nullable": true
                    },
                    "rateUnit": {
                      "type": "string",
                      "nullable": true
                    },
                    "estimatedCostUsd": {
                      "type": "number",
                      "nullable": true
                    },
                    "complete": {
                      "type": "boolean"
                    },
                    "limitation": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              },
              "pricingSources": {
                "type": "array",
                "description": "Public evidence frozen with the catalog version, including observation and effective dates.",
                "items": {
                  "type": "object",
                  "properties": {
                    "kind": {
                      "type": "string",
                      "enum": [
                        "pricing",
                        "terms"
                      ]
                    },
                    "url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "observedAt": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    },
                    "effectiveAt": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    }
                  }
                }
              },
              "limitations": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "decidedBy": {
                "type": "object",
                "properties": {
                  "source": {
                    "type": "string",
                    "enum": [
                      "AUTOMATIC",
                      "ADMIN_OVERRIDE",
                      "LEGACY_BACKFILL",
                      "MIGRATION"
                    ]
                  },
                  "means": {
                    "type": "string"
                  }
                }
              },
              "assumptions": {
                "type": "array",
                "description": "One entry per field SpringRoll had to guess, with the evidence it used. A value the caller declared never appears here, so a reader can always tell measurement from inference.",
                "items": {
                  "type": "object",
                  "properties": {
                    "field": {
                      "type": "string"
                    },
                    "value": {
                      "type": "string"
                    },
                    "because": {
                      "type": "string"
                    }
                  }
                }
              },
              "limits": {
                "type": "array",
                "description": "Every way this plan is worse than paying: sleeping when idle, stopping at a usage cap, cold starts, no backups, no availability commitment. Tell the user these before they rely on the application.",
                "items": {
                  "type": "object",
                  "properties": {
                    "kind": {
                      "type": "string"
                    },
                    "means": {
                      "type": "string"
                    },
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              },
              "notChosen": {
                "type": "array",
                "description": "Every candidate that lost, with the first reason it lost. This is the half that makes the receipt an argument a reader can check rather than an assertion, so it is worth rendering rather than ignoring.",
                "items": {
                  "type": "object",
                  "properties": {
                    "provider": {
                      "type": "string"
                    },
                    "plan": {
                      "type": "string"
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "TERMS_INELIGIBLE",
                        "UNSUITABLE_ENVIRONMENT",
                        "NO_MANAGED_CAPACITY",
                        "RUNTIME_UNSUPPORTED",
                        "UNMET_REQUIREMENT",
                        "UNSUPPORTED_SOURCE",
                        "INVALID_REGION",
                        "DATA_POLICY_CONFLICT",
                        "OVER_BUDGET"
                      ]
                    },
                    "means": {
                      "type": "string"
                    },
                    "detail": {
                      "type": "string"
                    }
                  }
                }
              },
              "billingOwner": {
                "type": "object",
                "description": "Who pays the provider for the plan this receipt describes. Released placements use SpringRoll-managed Vercel and Cloudflare accounts.",
                "properties": {
                  "owner": {
                    "type": "string",
                    "enum": [
                      "SPRINGROLL",
                      "CUSTOMER"
                    ]
                  },
                  "means": {
                    "type": "string"
                  }
                }
              },
              "recommendedInstead": {
                "type": "object",
                "nullable": true,
                "description": "Historical compatibility only. New placements bind recommendation and execution to the same exact managed target.",
                "properties": {
                  "provider": {
                    "type": "string"
                  },
                  "providerName": {
                    "type": "string"
                  },
                  "plan": {
                    "type": "string"
                  },
                  "planName": {
                    "type": "string"
                  },
                  "readiness": {
                    "type": "string",
                    "enum": [
                      "managed_ready",
                      "managed_activation_required",
                      "connection_required",
                      "connected",
                      "upgrade_required",
                      "verified",
                      "deployable",
                      "invalid_connection",
                      "unavailable"
                    ]
                  },
                  "means": {
                    "type": "string"
                  },
                  "action": {
                    "type": "string",
                    "nullable": true,
                    "description": "What makes the recommended plan deployable, when something does."
                  }
                }
              },
              "executionReadiness": {
                "type": "object",
                "description": "Whether this organization could execute a deployment onto the described plan when the receipt was written. An action vocabulary, not a verdict: connection_required means connect an account to deploy, never rejected. On a recorded deployment this is always an executable state, because a decision only ever binds a target that could actually deploy.",
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "managed_ready",
                      "managed_activation_required",
                      "connection_required",
                      "connected",
                      "upgrade_required",
                      "verified",
                      "deployable",
                      "invalid_connection",
                      "unavailable"
                    ]
                  },
                  "means": {
                    "type": "string"
                  },
                  "action": {
                    "type": "string",
                    "nullable": true
                  }
                }
              },
              "alternatives": {
                "type": "array",
                "description": "Ranked also-eligible active Vercel and Cloudflare plans, best first. Managed-account readiness never removes or reorders an entry, and it cannot promote an alternative into execution.",
                "items": {
                  "type": "object",
                  "properties": {
                    "provider": {
                      "type": "string"
                    },
                    "providerName": {
                      "type": "string"
                    },
                    "plan": {
                      "type": "string"
                    },
                    "planName": {
                      "type": "string"
                    },
                    "free": {
                      "type": "boolean"
                    },
                    "estimatedMonthlyCost": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "minUsd": {
                          "type": "number"
                        },
                        "maxUsd": {
                          "type": "number"
                        }
                      }
                    },
                    "eligibility": {
                      "type": "string",
                      "enum": [
                        "eligible",
                        "ineligible",
                        "unknown",
                        "quote_required"
                      ]
                    },
                    "billingOwner": {
                      "type": "string",
                      "enum": [
                        "SPRINGROLL",
                        "CUSTOMER"
                      ]
                    },
                    "readiness": {
                      "type": "string",
                      "enum": [
                        "managed_ready",
                        "managed_activation_required",
                        "connection_required",
                        "connected",
                        "upgrade_required",
                        "verified",
                        "deployable",
                        "invalid_connection",
                        "unavailable"
                      ]
                    },
                    "action": {
                      "type": "string",
                      "nullable": true
                    },
                    "meterBreakdown": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "billingProjection": {
                      "type": "object",
                      "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                      "required": [
                        "version",
                        "basis",
                        "components",
                        "unmodeledCharges"
                      ],
                      "properties": {
                        "version": {
                          "type": "integer",
                          "enum": [
                            1
                          ]
                        },
                        "basis": {
                          "type": "string",
                          "enum": [
                            "monthly-usage-before-allowances-and-credits"
                          ]
                        },
                        "builderBackend": {
                          "type": "string",
                          "enum": [
                            "vercel-sandbox",
                            "external"
                          ],
                          "description": "Build service used when the cost snapshot was calculated."
                        },
                        "artifactStore": {
                          "type": "string",
                          "enum": [
                            "vercel-blob",
                            "filesystem",
                            "unknown"
                          ],
                          "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                        },
                        "components": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              },
                              "unit": {
                                "type": "string"
                              },
                              "billingScope": {
                                "type": "string",
                                "enum": [
                                  "vercel-infrastructure",
                                  "neon-integration",
                                  "upstash-integration",
                                  "cloudflare-account",
                                  "external-or-unverified"
                                ],
                                "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                              },
                              "expectedUsage": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "rateMinUsd": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "rateMaxUsd": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "grossMinUsd": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "grossMaxUsd": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "observedAt": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time"
                              },
                              "source": {
                                "type": "string",
                                "format": "uri"
                              },
                              "limitation": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            }
                          }
                        },
                        "unmodeledCharges": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "pricingSources": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "limitations": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "provisionedCapabilities": {
            "type": "object",
            "description": "Safe runtime capability metadata. Credentials and provider account identifiers are never included.",
            "properties": {
              "billingProjection": {
                "type": "object",
                "description": "Component calculations from expected monthly usage and observed rates, before shared allowances or credits. Never a complete bill or proof of remaining headroom.",
                "required": [
                  "version",
                  "basis",
                  "components",
                  "unmodeledCharges"
                ],
                "properties": {
                  "version": {
                    "type": "integer",
                    "enum": [
                      1
                    ]
                  },
                  "basis": {
                    "type": "string",
                    "enum": [
                      "monthly-usage-before-allowances-and-credits"
                    ]
                  },
                  "builderBackend": {
                    "type": "string",
                    "enum": [
                      "vercel-sandbox",
                      "external"
                    ],
                    "description": "Build service used when the cost snapshot was calculated."
                  },
                  "artifactStore": {
                    "type": "string",
                    "enum": [
                      "vercel-blob",
                      "filesystem",
                      "unknown"
                    ],
                    "description": "Private immutable build-artifact destination used when the cost snapshot was calculated; independent of the runtime image registry."
                  },
                  "components": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "label": {
                          "type": "string"
                        },
                        "unit": {
                          "type": "string"
                        },
                        "billingScope": {
                          "type": "string",
                          "enum": [
                            "vercel-infrastructure",
                            "neon-integration",
                            "upstash-integration",
                            "cloudflare-account",
                            "external-or-unverified"
                          ],
                          "description": "The account or integration where this component is charged. Absent from older immutable receipts."
                        },
                        "expectedUsage": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "rateMinUsd": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "rateMaxUsd": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "grossMinUsd": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "grossMaxUsd": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "observedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time"
                        },
                        "source": {
                          "type": "string",
                          "format": "uri"
                        },
                        "limitation": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  },
                  "unmodeledCharges": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "billing": {
                "type": "object",
                "description": "Observed plans for this application's data resources, frozen at deployment. No usage totals or credentials.",
                "additionalProperties": {
                  "type": "object",
                  "required": [
                    "version",
                    "product",
                    "planId",
                    "scope",
                    "observedAt",
                    "currency",
                    "rates",
                    "includedCommandsPerMonth",
                    "source"
                  ],
                  "properties": {
                    "version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "product": {
                      "type": "string",
                      "enum": [
                        "neon",
                        "upstash-kv"
                      ]
                    },
                    "planId": {
                      "type": "string",
                      "enum": [
                        "launch_v3",
                        "free",
                        "paid"
                      ]
                    },
                    "scope": {
                      "type": "string",
                      "enum": [
                        "installation",
                        "resource"
                      ]
                    },
                    "observedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "USD"
                      ]
                    },
                    "rates": {
                      "type": "object",
                      "properties": {
                        "perCuHourUsd": {
                          "type": "number",
                          "minimum": 0
                        },
                        "perGbMonthUsd": {
                          "type": "number",
                          "minimum": 0
                        },
                        "per100kCommandsUsd": {
                          "type": "number",
                          "minimum": 0
                        }
                      }
                    },
                    "includedCommandsPerMonth": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "minimum": 0
                    },
                    "source": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              },
              "storage": {
                "type": "object",
                "required": [
                  "kind",
                  "access",
                  "scope",
                  "baseUrl"
                ],
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "object-storage"
                    ]
                  },
                  "access": {
                    "type": "string",
                    "enum": [
                      "public"
                    ]
                  },
                  "scope": {
                    "type": "string",
                    "enum": [
                      "application"
                    ]
                  },
                  "baseUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "binding": {
                    "type": "string",
                    "enum": [
                      "STORAGE"
                    ]
                  },
                  "containerEndpointVariable": {
                    "type": "string",
                    "enum": [
                      "SPRINGROLL_CONTAINER_STORAGE_URL"
                    ]
                  }
                }
              },
              "database": {
                "type": "object",
                "required": [
                  "kind",
                  "scope",
                  "engine",
                  "connection"
                ],
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "database"
                    ]
                  },
                  "scope": {
                    "type": "string",
                    "enum": [
                      "application"
                    ]
                  },
                  "engine": {
                    "type": "string",
                    "enum": [
                      "postgres",
                      "sqlite"
                    ]
                  },
                  "connection": {
                    "type": "string",
                    "enum": [
                      "environment",
                      "binding"
                    ]
                  },
                  "variable": {
                    "type": "string",
                    "enum": [
                      "DATABASE_URL"
                    ]
                  },
                  "binding": {
                    "type": "string",
                    "enum": [
                      "DB"
                    ]
                  },
                  "containerEndpointVariable": {
                    "type": "string",
                    "enum": [
                      "SPRINGROLL_CONTAINER_DATABASE_URL"
                    ]
                  }
                }
              }
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339 timestamp, always UTC."
          }
        }
      },
      "ApprovalRequest": {
        "type": "object",
        "description": "A decision waiting on a person, with the evidence frozen beside it.",
        "required": [
          "id",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque server-assigned identifier. Do not construct one."
          },
          "applicationId": {
            "type": "string",
            "description": "Opaque server-assigned identifier. Do not construct one."
          },
          "kind": {
            "type": "string",
            "enum": [
              "UAT_PROMOTION",
              "PRODUCTION_PROMOTION",
              "UAT_SIGN_OFF",
              "DATA_ACCESS_GRANT",
              "VISIBILITY_CHANGE",
              "OWNERSHIP_TRANSFER",
              "ROLLBACK",
              "RETIREMENT",
              "DOMAIN_CHANGE",
              "ACCESS_REQUEST"
            ],
            "description": "What is being asked for."
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "APPROVED",
              "REJECTED",
              "CHANGES_REQUESTED",
              "WITHDRAWN",
              "EXPIRED"
            ],
            "description": "PENDING until a person decides."
          },
          "requestedBy": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339 timestamp, always UTC."
          }
        }
      },
      "DataAccessGrant": {
        "type": "object",
        "description": "What a deployed application is allowed to read from one data product. The application never receives the source credential.",
        "required": [
          "id",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque server-assigned identifier. Do not construct one."
          },
          "dataProductSlug": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "REQUESTED",
              "APPROVED",
              "REJECTED",
              "REVOKED",
              "EXPIRED"
            ],
            "description": "REQUESTED until a data owner decides; GRANTED once enforced at the gateway."
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The approved columns. Anything else is refused at query time."
          },
          "queriesPerMinute": {
            "type": "integer",
            "description": "Approved query volume for this application against this product."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339 timestamp, always UTC."
          }
        }
      },
      "AuditEvent": {
        "type": "object",
        "description": "One appended audit event. The table refuses UPDATE and DELETE, and each row carries a hash of the previous one.",
        "required": [
          "id",
          "action",
          "createdAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Opaque server-assigned identifier. Do not construct one."
          },
          "action": {
            "type": "string",
            "description": "The governed action that occurred."
          },
          "actor": {
            "type": "string",
            "description": "Who or what did it."
          },
          "resourceType": {
            "type": "string"
          },
          "resourceId": {
            "type": "string"
          },
          "correlationId": {
            "type": "string",
            "description": "Ties the event to the request that caused it."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339 timestamp, always UTC."
          }
        }
      }
    },
    "responses": {
      "Error401": {
        "description": "No credential, or a credential that no longer resolves.",
        "headers": {
          "x-correlation-id": {
            "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
            "schema": {
              "type": "string"
            }
          },
          "RateLimit": {
            "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";r=598;t=42"
          },
          "RateLimit-Policy": {
            "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";q=600;w=60"
          },
          "RateLimit-Limit": {
            "description": "Requests allowed in the current window.",
            "schema": {
              "type": "integer"
            },
            "example": 600
          },
          "RateLimit-Remaining": {
            "description": "Requests left in the current window.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
            "schema": {
              "type": "integer"
            }
          },
          "Deprecation": {
            "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
            "schema": {
              "type": "string"
            }
          },
          "Sunset": {
            "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error403": {
        "description": "Authenticated, but not permitted, or the token belongs to a different organization than the path claims.",
        "headers": {
          "x-correlation-id": {
            "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
            "schema": {
              "type": "string"
            }
          },
          "RateLimit": {
            "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";r=598;t=42"
          },
          "RateLimit-Policy": {
            "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";q=600;w=60"
          },
          "RateLimit-Limit": {
            "description": "Requests allowed in the current window.",
            "schema": {
              "type": "integer"
            },
            "example": 600
          },
          "RateLimit-Remaining": {
            "description": "Requests left in the current window.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
            "schema": {
              "type": "integer"
            }
          },
          "Deprecation": {
            "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
            "schema": {
              "type": "string"
            }
          },
          "Sunset": {
            "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error404": {
        "description": "No such resource, or one belonging to an organization you are not a member of. The two are deliberately indistinguishable.",
        "headers": {
          "x-correlation-id": {
            "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
            "schema": {
              "type": "string"
            }
          },
          "RateLimit": {
            "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";r=598;t=42"
          },
          "RateLimit-Policy": {
            "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";q=600;w=60"
          },
          "RateLimit-Limit": {
            "description": "Requests allowed in the current window.",
            "schema": {
              "type": "integer"
            },
            "example": 600
          },
          "RateLimit-Remaining": {
            "description": "Requests left in the current window.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
            "schema": {
              "type": "integer"
            }
          },
          "Deprecation": {
            "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
            "schema": {
              "type": "string"
            }
          },
          "Sunset": {
            "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error409": {
        "description": "State conflict: an approval is required, the lifecycle transition is illegal, or an idempotency key was reused with a different body.",
        "headers": {
          "x-correlation-id": {
            "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
            "schema": {
              "type": "string"
            }
          },
          "RateLimit": {
            "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";r=598;t=42"
          },
          "RateLimit-Policy": {
            "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";q=600;w=60"
          },
          "RateLimit-Limit": {
            "description": "Requests allowed in the current window.",
            "schema": {
              "type": "integer"
            },
            "example": 600
          },
          "RateLimit-Remaining": {
            "description": "Requests left in the current window.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
            "schema": {
              "type": "integer"
            }
          },
          "Deprecation": {
            "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
            "schema": {
              "type": "string"
            }
          },
          "Sunset": {
            "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error422": {
        "description": "The request was understood but rejected: it failed validation, or was blocked by policy.",
        "headers": {
          "x-correlation-id": {
            "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
            "schema": {
              "type": "string"
            }
          },
          "RateLimit": {
            "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";r=598;t=42"
          },
          "RateLimit-Policy": {
            "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";q=600;w=60"
          },
          "RateLimit-Limit": {
            "description": "Requests allowed in the current window.",
            "schema": {
              "type": "integer"
            },
            "example": 600
          },
          "RateLimit-Remaining": {
            "description": "Requests left in the current window.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
            "schema": {
              "type": "integer"
            }
          },
          "Deprecation": {
            "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
            "schema": {
              "type": "string"
            }
          },
          "Sunset": {
            "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error429": {
        "description": "Rate limited. Honour the Retry-After header.",
        "headers": {
          "x-correlation-id": {
            "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
            "schema": {
              "type": "string"
            }
          },
          "RateLimit": {
            "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";r=598;t=42"
          },
          "RateLimit-Policy": {
            "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";q=600;w=60"
          },
          "RateLimit-Limit": {
            "description": "Requests allowed in the current window.",
            "schema": {
              "type": "integer"
            },
            "example": 600
          },
          "RateLimit-Remaining": {
            "description": "Requests left in the current window.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
            "schema": {
              "type": "integer"
            }
          },
          "Deprecation": {
            "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
            "schema": {
              "type": "string"
            }
          },
          "Sunset": {
            "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
            "schema": {
              "type": "string"
            }
          },
          "Retry-After": {
            "description": "Seconds to wait before retrying. Honour this rather than backing off by guess.",
            "schema": {
              "type": "integer"
            },
            "required": true
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error500": {
        "description": "Unexpected failure. Quote the correlation id.",
        "headers": {
          "x-correlation-id": {
            "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
            "schema": {
              "type": "string"
            }
          },
          "RateLimit": {
            "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";r=598;t=42"
          },
          "RateLimit-Policy": {
            "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";q=600;w=60"
          },
          "RateLimit-Limit": {
            "description": "Requests allowed in the current window.",
            "schema": {
              "type": "integer"
            },
            "example": 600
          },
          "RateLimit-Remaining": {
            "description": "Requests left in the current window.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
            "schema": {
              "type": "integer"
            }
          },
          "Deprecation": {
            "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
            "schema": {
              "type": "string"
            }
          },
          "Sunset": {
            "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error501": {
        "description": "The feature is not configured on this deployment.",
        "headers": {
          "x-correlation-id": {
            "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
            "schema": {
              "type": "string"
            }
          },
          "RateLimit": {
            "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";r=598;t=42"
          },
          "RateLimit-Policy": {
            "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";q=600;w=60"
          },
          "RateLimit-Limit": {
            "description": "Requests allowed in the current window.",
            "schema": {
              "type": "integer"
            },
            "example": 600
          },
          "RateLimit-Remaining": {
            "description": "Requests left in the current window.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
            "schema": {
              "type": "integer"
            }
          },
          "Deprecation": {
            "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
            "schema": {
              "type": "string"
            }
          },
          "Sunset": {
            "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error502": {
        "description": "An upstream provider failed.",
        "headers": {
          "x-correlation-id": {
            "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
            "schema": {
              "type": "string"
            }
          },
          "RateLimit": {
            "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";r=598;t=42"
          },
          "RateLimit-Policy": {
            "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";q=600;w=60"
          },
          "RateLimit-Limit": {
            "description": "Requests allowed in the current window.",
            "schema": {
              "type": "integer"
            },
            "example": 600
          },
          "RateLimit-Remaining": {
            "description": "Requests left in the current window.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
            "schema": {
              "type": "integer"
            }
          },
          "Deprecation": {
            "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
            "schema": {
              "type": "string"
            }
          },
          "Sunset": {
            "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Error504": {
        "description": "A data source exceeded the time the grant allows.",
        "headers": {
          "x-correlation-id": {
            "description": "Identifies this request in the audit log. Echoed from the request when you send one.",
            "schema": {
              "type": "string"
            }
          },
          "RateLimit": {
            "description": "Current quota state as a structured field: `\"policy\";r=<remaining>;t=<seconds until reset>`. Self-throttle from this rather than retrying blind.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";r=598;t=42"
          },
          "RateLimit-Policy": {
            "description": "The quota this response was charged against: `\"policy\";q=<limit>;w=<window in seconds>`. The unauthenticated discovery endpoints send every policy, so a budget can be read before the first call.",
            "schema": {
              "type": "string"
            },
            "example": "\"read\";q=600;w=60"
          },
          "RateLimit-Limit": {
            "description": "Requests allowed in the current window.",
            "schema": {
              "type": "integer"
            },
            "example": 600
          },
          "RateLimit-Remaining": {
            "description": "Requests left in the current window.",
            "schema": {
              "type": "integer"
            }
          },
          "RateLimit-Reset": {
            "description": "Seconds until the window resets. A delta, not a timestamp. X-RateLimit-Reset is the timestamp form.",
            "schema": {
              "type": "integer"
            }
          },
          "Deprecation": {
            "description": "IMF-fixdate naming when this API version was deprecated. Absent while the version is current. Once present, the version keeps answering for at least 365 days.",
            "schema": {
              "type": "string"
            }
          },
          "Sunset": {
            "description": "IMF-fixdate naming when this API version stops answering (RFC 8594). Absent while the version is current. After it passes, the version answers 410 Gone.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "agentToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "A SpringRoll agent token, prefixed `sbp_`, in the Authorization header. Issued to a named membership: it carries exactly that person's permissions and can never record an approval decision.\n\nA bearer token takes precedence over a session cookie, so a script running inside a logged-in browser cannot accidentally act as the user.\n\nAn MCP client should not use this at all: it should run the OAuth 2.1 flow and receive its own credential instead of being handed one."
      },
      "oauth2": {
        "type": "oauth2",
        "description": "OAuth 2.1 with PKCE and RFC 7591 dynamic client registration. Discover the endpoints from /.well-known/oauth-authorization-server rather than hard-coding them.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://springroll.dev/oauth/authorize",
            "tokenUrl": "https://springroll.dev/api/oauth/token",
            "refreshUrl": "https://springroll.dev/api/oauth/token",
            "scopes": {}
          }
        }
      },
      "appIdentity": {
        "type": "http",
        "scheme": "bearer",
        "description": "The identity token SpringRoll injects into a deployed application. Used only by the SpringRoll Connect endpoints under /api/data/v1, and scoped to that application's approved grants. Never the source system's credential."
      }
    }
  }
}