{
  "openapi": "3.1.0",
  "x-visibility": {
    "extent": "public"
  },
  "x-lifecycle": "Beta",
  "info": {
    "title": "Hosting API",
    "version": "1.0.0",
    "license": {
      "name": "Proprietary",
      "url": "https://www.godaddy.com/legal/agreements/software-license-agreement"
    },
    "contact": {
      "name": "GoDaddy Hosting",
      "x-slack-channel": "#agi-hosting-nodejs",
      "x-visibility": {
        "extent": "private"
      }
    },
    "description": "Manage hosted applications across GoDaddy hosting products.\n\n## Async operations\n\nAny operation that takes time returns `202 Accepted` with a resource body and a `links[rel=self]` URL. The same URL is also returned in the `Location` response header. Poll that URL until the status field reaches a terminal state.\n\n## Correlation\n\nEvery response carries an `X-Request-Id` header. Include this value when reporting issues so the request can be traced end to end. Clients should send a W3C `traceparent` header on every request so the trace can be correlated across services.\n\n## Rate limiting\n\nA `429 Too Many Requests` response may come in one of two shapes: an empty body with `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset` headers; or a JSON `Error` body with `Retry-After` and `RateLimit-*` headers. Clients should honour whichever headers are present and should not assume a JSON body is available.\n\n## Forward compatibility\n\nSeveral of the enumerations in this specification are expected to gain members as new products, environments and states come online. Where an enumeration's description says so, clients must not fail on a member they do not recognise — treat it as an unhandled value and continue.\n"
  },
  "servers": [
    {
      "url": "https://api.godaddy.com/v1/hosting",
      "description": "Production"
    },
    {
      "url": "https://api.ote-godaddy.com/v1/hosting",
      "description": "OTE / sandbox"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Personal Access Token (PAT). Generate one from the developer dashboard. Pass as: `Authorization: Bearer <token>`."
      }
    },
    "parameters": {
      "appId": {
        "name": "appId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^[A-Z][A-Z0-9_]*-[A-Za-z0-9_-]+$"
        },
        "description": "Application identifier in `{PRODUCT}-{id}` form. The prefix is the application type in upper case — an upper-case letter followed by any number of upper-case letters, digits, or underscores — then a hyphen, then the identifier. For `NODEJS`, the suffix is a 10-character nanoid. Example: `NODEJS-aBcDeFgHiJ`.\n"
      },
      "appType": {
        "name": "appType",
        "in": "query",
        "required": true,
        "schema": {
          "$ref": "#/x-ext/55e83fe"
        },
        "description": "Product type to scope the operation to."
      },
      "hostingProduct": {
        "name": "hostingProduct",
        "in": "query",
        "required": true,
        "schema": {
          "$ref": "#/x-ext/fa98d95"
        },
        "description": "Hosting product to scope the operation to. This filter is required rather than optional: an optional filter introduced after general availability would have to default to `WEB_HOSTING` for ever, or the set of subscriptions returned would silently change for clients that omit it. It is made required now, while this spec is still Beta.\n"
      },
      "pageToken": {
        "name": "pageToken",
        "in": "query",
        "required": false,
        "schema": {
          "$ref": "#/x-ext/e7c120b/properties/pageToken"
        },
        "description": "Opaque pagination cursor. Clients should navigate by following `links[rel=next].href` from the previous response rather than constructing URLs manually; this parameter is documented so that the endpoint's contract is discoverable.\n"
      },
      "pageSize": {
        "name": "pageSize",
        "in": "query",
        "required": false,
        "schema": {
          "$ref": "#/x-ext/e7c120b/properties/pageSize"
        },
        "description": "Maximum number of items to return."
      },
      "totalRequired": {
        "name": "totalRequired",
        "in": "query",
        "required": false,
        "schema": {
          "$ref": "#/x-ext/e7c120b/properties/totalRequired"
        },
        "description": "When `true`, populate `totalItems` in the response. This may impact response time on large collections.\n"
      },
      "traceparent": {
        "name": "traceparent",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "pattern": "^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$"
        },
        "description": "W3C Trace Context identifier for this request. Clients should send a `traceparent` on every request so the trace can be correlated across services. See https://www.w3.org/TR/trace-context/ for the format.\n"
      },
      "idempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        },
        "description": "Client-generated UUID that makes a request safe to retry. Supplying the same key on a retry with an identical request body returns the original response without triggering a second operation. Retrying with the same key while the first request is still in flight returns `409 Conflict`. Reusing a key with a different request body returns `422 Unprocessable Entity` with `details[].issue` `IDEMPOTENCY_KEY_MISMATCH`. Keys are retained for 24 hours after the operation completes, after which the key may be reused.\n"
      }
    },
    "schemas": {
      "Error": {
        "$ref": "#/x-ext/21ae8c5"
      },
      "PagedApplications": {
        "allOf": [
          {
            "$ref": "#/x-ext/70f5935"
          },
          {
            "type": "object",
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/x-ext/a87153c"
                }
              }
            }
          }
        ]
      },
      "PagedDeployments": {
        "allOf": [
          {
            "$ref": "#/x-ext/70f5935"
          },
          {
            "type": "object",
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/x-ext/edb0cb2"
                }
              }
            }
          }
        ]
      },
      "SecretList": {
        "$ref": "#/x-ext/34c8cb4"
      },
      "CreateAppRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Human-readable display name for the application."
          }
        }
      },
      "RestartRequest": {
        "type": "object",
        "required": [
          "variant"
        ],
        "properties": {
          "variant": {
            "$ref": "#/x-ext/a699683",
            "description": "Which environment to restart."
          }
        }
      },
      "ImportGitHubSourceRequest": {
        "type": "object",
        "required": [
          "repositoryFullName",
          "branch"
        ],
        "properties": {
          "repositoryFullName": {
            "type": "string",
            "description": "Repository in `owner/repo` format.",
            "examples": [
              "acme-corp/my-node-app"
            ]
          },
          "branch": {
            "type": "string",
            "description": "Branch to import from.",
            "examples": [
              "main"
            ]
          }
        }
      },
      "AttachDomainRequest": {
        "type": "object",
        "required": [
          "hostname"
        ],
        "properties": {
          "hostname": {
            "type": "string",
            "description": "The fully-qualified domain name to attach.",
            "examples": [
              "www.example.com"
            ]
          }
        }
      },
      "AttachSubscriptionRequest": {
        "type": "object",
        "required": [
          "subscriptionId"
        ],
        "properties": {
          "subscriptionId": {
            "type": "string",
            "description": "The id of the subscription to attach."
          }
        }
      },
      "PagedDomains": {
        "description": "Domain attachments for an application. Returned as a single page in current implementations; navigate future pages via `links[rel=next]` if it is present in the response.\n",
        "allOf": [
          {
            "$ref": "#/x-ext/70f5935"
          },
          {
            "type": "object",
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/x-ext/7244d8c"
                }
              }
            }
          }
        ]
      },
      "PagedSubscriptions": {
        "description": "Hosting subscriptions belonging to the authenticated user. Returned as a single page in current implementations; navigate future pages via `links[rel=next]` if it is present in the response.\n",
        "allOf": [
          {
            "$ref": "#/x-ext/70f5935"
          },
          {
            "type": "object",
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/x-ext/d018c9e"
                }
              }
            }
          }
        ]
      },
      "PagedLogEntries": {
        "allOf": [
          {
            "$ref": "#/x-ext/70f5935"
          },
          {
            "type": "object",
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/x-ext/9fa0221"
                }
              }
            }
          }
        ]
      }
    },
    "headers": {
      "XRequestId": {
        "description": "Server-generated correlation identifier for this response. Include this value when reporting issues so the request can be traced end to end.\n",
        "schema": {
          "type": "string"
        }
      },
      "Location": {
        "description": "URL of the resource created or accepted by this request. On a `202 Accepted` response this matches the `links[rel=self]` entry in the response body and is the URL clients should poll.\n",
        "schema": {
          "type": "string",
          "format": "uri"
        }
      },
      "RateLimitLimit": {
        "description": "Total number of requests allowed in the current window for this route.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitRemaining": {
        "description": "Number of requests remaining in the current window.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitReset": {
        "description": "Seconds until the rate-limit window resets.",
        "schema": {
          "type": "integer"
        }
      },
      "RetryAfter": {
        "description": "Seconds the client should wait before retrying. On `429` responses, present when the rate-limiter uses this header instead of `RateLimit-Reset`. On `202 Accepted` responses, an optional hint suggesting how long to wait before polling again.\n",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Authentication credentials are missing or invalid.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The caller is authenticated, but the request is not permitted: either the access token does not carry the scope this operation requires, or the operation is disabled for this account.\n",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limit exceeded. A `429` response may come in one of two shapes: an empty body with `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset` headers; or a JSON `Error` body with `Retry-After` and `RateLimit-*` headers. Clients should honour whichever headers are present and should not assume a JSON body is available on every `429`.\n",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "The requested resource does not exist.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "BadRequest": {
        "description": "The request body or parameters did not pass schema validation.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "UnprocessableEntity": {
        "description": "The request was well-formed but could not be processed due to a business rule violation.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Conflict": {
        "description": "The request conflicts with the current state of the resource.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotImplemented": {
        "description": "The request is contract-valid, but the operation, or a value the request names, is not applicable to this deployment. `details[].issue` is always `NOT_APPLICABLE`. For example, deployments and restarts are offered for `NODEJS` applications only, and a hosting product this deployment does not serve is answered here rather than with a `400`.\n",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "The service is temporarily unable to handle the request. Retry after a short delay. May include a `Retry-After` header hinting at when to retry.\n",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          },
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/apps": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        }
      ],
      "get": {
        "operationId": "listApps",
        "summary": "List applications",
        "description": "Returns a paginated list of applications for the authenticated user. `appType` is required. Cross-product listing will be supported in a future version.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/appType"
          },
          {
            "$ref": "#/components/parameters/pageToken"
          },
          {
            "$ref": "#/components/parameters/pageSize"
          },
          {
            "$ref": "#/components/parameters/totalRequired"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of applications.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PagedApplications"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createApp",
        "summary": "Create an application",
        "description": "Creates a new hosted application. Because no `appId` exists until provisioning has assigned one, this endpoint returns `202 Accepted` with an `AppOperation` resource carrying an `operationId`. Poll `GET /app-operations/{operationId}` until `status` is `COMPLETED` or `FAILED`. On `COMPLETED` the operation result includes the created `Application` with `status: ACTIVE`; use its `id` for any further calls.\n\nCurrently only `NODEJS` applications can be created through this endpoint. The request body is product-specific; the fields below apply to Node.js. Support for additional product types will be documented when those paths are available.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/appType"
          },
          {
            "$ref": "#/components/parameters/idempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAppRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Application creation accepted. Poll `links[rel=self]` until `status` is `COMPLETED` or `FAILED`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/0bebd09"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/app-operations/{operationId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "name": "operationId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          },
          "description": "The operation identifier returned by `POST /apps`."
        }
      ],
      "get": {
        "operationId": "getAppOperation",
        "summary": "Get an application-creation operation",
        "description": "Returns the current state of an application-creation operation. Use this as the poll target after `POST /apps` until `status` reaches `COMPLETED` or `FAILED`. On `COMPLETED`, the response includes the created `Application` with `status: ACTIVE`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Operation details.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/0bebd09"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/apps/{appId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "$ref": "#/components/parameters/appId"
        }
      ],
      "get": {
        "operationId": "getApp",
        "summary": "Get an application",
        "description": "Returns the current state of an application.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Application details.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/a87153c"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateApp",
        "summary": "Update an application",
        "description": "Partial update via [JSON Patch (RFC 6902)](https://datatracker.ietf.org/doc/html/rfc6902). The request body is an array of operations applied in order and atomically. At least one operation must be present.\n\nOnly the `replace` operation is supported, and only against the `/name` and `/rootPath` paths. Any other op or path returns `400 Bad Request`.\n\n- `/name` — human-readable display name. String, 1–200 characters. - `/rootPath` — subdirectory within the repository to treat as\n  the application root. Write-only; not returned on the\n  `Application` resource.\n\n\nCurrently only supported for `NODEJS` applications. Additional product-specific paths will be documented when those paths are available.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json-patch+json": {
              "schema": {
                "$ref": "#/x-ext/785f9fe"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated application.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/a87153c"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteApp",
        "summary": "Delete an application",
        "description": "Permanently deletes the application, its deployments, imported source, secrets, and attached domains. This action cannot be undone. Returns `204 No Content` on success.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Application deleted.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/apps/{appId}/status": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "$ref": "#/components/parameters/appId"
        }
      ],
      "get": {
        "operationId": "getAppStatus",
        "summary": "Get application runtime status",
        "description": "Returns per-environment lifecycle detail. Use as the poll target after `POST /apps/{appId}/restarts`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Application status.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/509c3ac"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/apps/{appId}/deployments": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "$ref": "#/components/parameters/appId"
        }
      ],
      "get": {
        "operationId": "listDeployments",
        "summary": "List deployments",
        "description": "Returns deployments for the application, newest first. Use this to inspect deployment history or find the most recent successful build.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/pageToken"
          },
          {
            "$ref": "#/components/parameters/pageSize"
          },
          {
            "$ref": "#/components/parameters/totalRequired"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of deployments, newest first.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PagedDeployments"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createDeployment",
        "summary": "Trigger a deployment",
        "description": "Builds the latest imported source and deploys it to the publish environment. Returns `202 Accepted`. Poll `GET /apps/{appId}/deployments/{deploymentId}` until `status` is `COMPLETED` or `FAILED`.\n\nThis endpoint is only applicable to Node.js applications (`appType: NODEJS`): a deployment builds the imported source and publishes it through the Node.js application agent, which other hosting products do not have. Other product types return `501`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/idempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Deployment accepted. Poll `links[rel=self]` until status is terminal.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/edb0cb2"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/apps/{appId}/deployments/{deploymentId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "$ref": "#/components/parameters/appId"
        },
        {
          "name": "deploymentId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          },
          "description": "Deployment identifier returned in the `deploymentId` field of `POST /apps/{appId}/deployments`."
        }
      ],
      "get": {
        "operationId": "getDeployment",
        "summary": "Get a deployment",
        "description": "Returns the current state of a deployment. Use as the poll target after `POST /apps/{appId}/deployments` until `status` reaches `COMPLETED` or `FAILED`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Deployment details.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/edb0cb2"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/apps/{appId}/restarts": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "$ref": "#/components/parameters/appId"
        }
      ],
      "post": {
        "operationId": "createAppRestart",
        "summary": "Restart an application environment",
        "description": "Triggers a restart of the specified environment (`PREVIEW` or `PUBLISH`). Returns `202 Accepted`. Poll `GET /apps/{appId}/status` until the targeted variant reaches a stable state.\n\nThis endpoint is only applicable to Node.js applications (`appType: NODEJS`): restarts act on the `PREVIEW` and `PUBLISH` environment variants, which are specific to the Node.js runtime model. Other product types return `501`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/idempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestartRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Restart accepted. Poll `links[rel=self]` until the targeted variant reaches a stable state.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/509c3ac"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/apps/{appId}/imports": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "$ref": "#/components/parameters/appId"
        }
      ],
      "post": {
        "operationId": "createSourceImport",
        "summary": "Import source code",
        "description": "Imports source code for an application. The `Content-Type` header determines the import type:\n- `multipart/form-data`: upload a ZIP archive directly. - `application/json`: upload from a connected GitHub repository.\nReturns `202 Accepted` with a `SourceImport` resource. The `importType` field identifies what was submitted. Poll `GET /apps/{appId}/imports/{importId}` until `status` is `COMPLETED` or `FAILED`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/idempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "ZIP archive of the application source code."
                  }
                }
              }
            },
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportGitHubSourceRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Import accepted. Poll `links[rel=self]` until status is terminal.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/23e638a"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/apps/{appId}/imports/{importId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "$ref": "#/components/parameters/appId"
        },
        {
          "name": "importId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          },
          "description": "Import identifier returned in the `importId` field of `POST /apps/{appId}/imports`."
        }
      ],
      "get": {
        "operationId": "getSourceImport",
        "summary": "Get a source import",
        "description": "Returns the current state of a source import. Use as the poll target after `POST /apps/{appId}/imports` until `status` reaches `COMPLETED` or `FAILED`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Source import details.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/23e638a"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/apps/{appId}/secrets": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "$ref": "#/components/parameters/appId"
        }
      ],
      "get": {
        "operationId": "listSecrets",
        "summary": "List secrets",
        "description": "Returns secret metadata. Values are never included in responses.\n",
        "parameters": [
          {
            "name": "variant",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/x-ext/a699683"
            },
            "description": "The environment variant to target. Defaults to `PREVIEW`.\n"
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Secret metadata list.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateSecrets",
        "summary": "Update secrets",
        "description": "Partial update via [JSON Patch (RFC 6902)](https://datatracker.ietf.org/doc/html/rfc6902). The request body is an array of operations applied in order and atomically. At least one operation must be present. The combined total number of operations must not exceed 50. Existing secrets not referenced in the request are left unchanged.\n\nThe `variant` query parameter selects the environment (`PREVIEW` or `PUBLISH`). Defaults to `PREVIEW`.\n\nSupported operations are `add`, `replace`, and `remove`. Any other op returns `400 Bad Request`. Each path is `/{name}` — a JSON Pointer to the secret name, not an index into the `ScopedSecretSet` response.\nEncode `/` in a secret name as `~1` per RFC 6901. Secret names must start with a letter and contain only letters, digits, `/`, `_`, `+`, `=`, `.`, `@`, or `-`. Reserved environment variable names are rejected. System-managed and reserved secrets cannot be updated or deleted.\n\nFor `add` and `replace`, `value` is the secret string (max 8 KB). `remove` does not take a value. A request that would leave the application with more than 50 secrets returns `400 Bad Request`.\n\nThe response is secret metadata after the update. Values are never included.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/idempotencyKey"
          },
          {
            "name": "variant",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/x-ext/a699683"
            },
            "description": "The environment variant to target. Defaults to `PREVIEW`.\n"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json-patch+json": {
              "schema": {
                "$ref": "#/x-ext/785f9fe"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Secret metadata after the update. Values are never included.\n",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/3c029b5"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/apps/{appId}/logs": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "$ref": "#/components/parameters/appId"
        }
      ],
      "get": {
        "operationId": "getLogs",
        "summary": "Get application logs",
        "description": "Returns log entries for the application, newest first. The v2 endpoint always returns entries in the normalized shape defined by `LogEntry`: `timestamp`, `level` (`INFO`/`WARN`/`ERROR`), `source` (`STDOUT`/`STDERR`), and `message`. Entries whose raw level or source cannot be mapped to one of the values defined today are dropped, so no entry is returned carrying a value outside `LogLevel` or `LogSource`. Both enumerations may gain members in a future version of this specification, so clients must not fail on a value they do not recognise.\n\n`variant` selects the environment (`PREVIEW` or `PUBLISH`), matching the `variant` field used by the restart request body. The service still honours two earlier spellings, `target` and `environment`, both deprecated; the precedence is `variant` > `target` > `environment`, and the first one supplied wins while the others are ignored. When none is supplied the environment defaults to `PREVIEW`. New clients should send `variant` only. `since` limits results to entries at or after the given timestamp; defaults to 24 hours ago and cannot exceed 7 days. `level` filters entries by severity after retrieval.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "variant",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/x-ext/a699683"
            },
            "description": "Environment to retrieve logs from. The canonical parameter; it takes precedence over the deprecated `target` and `environment`. Defaults to `PREVIEW` when none of the three is supplied.\n"
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/x-ext/37bf2ab"
            },
            "description": "Return only entries at or after this ISO 8601 timestamp (must include timezone offset). Defaults to 24 hours ago. Cannot exceed 7 days in the past.\n"
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/x-ext/33c2cb4"
            },
            "description": "Filter logs by source stream. Defaults to all streams."
          },
          {
            "name": "level",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/x-ext/d7d4644"
            },
            "description": "Filter logs by severity level."
          },
          {
            "$ref": "#/components/parameters/pageToken"
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "description": "Maximum number of log entries to return."
          }
        ],
        "responses": {
          "200": {
            "description": "Log entries, newest first.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PagedLogEntries"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/apps/{appId}/runtime": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "$ref": "#/components/parameters/appId"
        }
      ],
      "get": {
        "operationId": "getRuntime",
        "summary": "Get runtime configuration",
        "description": "Returns the runtime version configuration for the application. Each entry identifies a runtime component (e.g. `NODE`, `PHP`, `WORDPRESS`) and its current version.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Runtime version configuration for the application.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/x-ext/92a6c61"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/apps/{appId}/domains": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "$ref": "#/components/parameters/appId"
        }
      ],
      "get": {
        "operationId": "listDomains",
        "summary": "List attached domains",
        "description": "Returns the domains currently attached to this application, including their DNS verification state.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Domains attached to this application.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PagedDomains"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "attachDomain",
        "summary": "Attach a domain",
        "description": "Attaches a custom domain to the application and initiates DNS verification. Returns `202 Accepted`. Poll `GET /apps/{appId}/domains/{domainId}` until `verificationStatus` is `ACTIVE` or `FAILED`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/idempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AttachDomainRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Domain attachment accepted. Poll `links[rel=self]` until `verificationStatus` is `ACTIVE` or `FAILED`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/7244d8c"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/apps/{appId}/domains/{domainId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "$ref": "#/components/parameters/appId"
        },
        {
          "name": "domainId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          },
          "description": "Domain attachment identifier returned in the `domainId` field of `POST /apps/{appId}/domains`."
        }
      ],
      "get": {
        "operationId": "getDomain",
        "summary": "Get a domain attachment",
        "description": "Returns the current state of a domain attachment, including `verificationStatus`. Use as the poll target after `POST /apps/{appId}/domains`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Domain attachment details.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/7244d8c"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "detachDomain",
        "summary": "Remove a domain attachment",
        "description": "Detaches a custom domain from the application. DNS records at the registrar are not modified. Returns `204 No Content` on success.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Domain detached.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/subscriptions": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        }
      ],
      "get": {
        "operationId": "listSubscriptions",
        "summary": "List hosting subscriptions",
        "description": "Returns hosting subscriptions for the authenticated user, including slot usage. Use this to find a `subscriptionId` when attaching a subscription to an application. `hostingProduct` is required. Cross-product listing will be supported in a future version.\n\nThe parameter has three outcomes. Omitting it, or sending a value outside `HostingProduct`, returns `400` with `details[].issue` `VALIDATION_FAILED`. Sending a product the enum admits but this deployment does not serve returns `501` with `details[].issue` `NOT_APPLICABLE` — never `400`. Sending a product this deployment serves returns `200`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/hostingProduct"
          }
        ],
        "responses": {
          "200": {
            "description": "Hosting subscriptions.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PagedSubscriptions"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/apps/{appId}/subscription": {
      "parameters": [
        {
          "$ref": "#/components/parameters/traceparent"
        },
        {
          "$ref": "#/components/parameters/appId"
        }
      ],
      "get": {
        "operationId": "getSubscriptionAttachment",
        "summary": "Get the subscription attached to an application",
        "description": "Returns the subscription currently attached to this application. Returns `404` if no subscription has ever been attached.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Current subscription attachment.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/896165a"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "put": {
        "operationId": "attachSubscription",
        "summary": "Attach a subscription to an application",
        "description": "Attaches a hosting subscription to the application. The subscription must have at least one free slot. If not, a `409` is returned with `details[].issue` `NO_CAPACITY`.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AttachSubscriptionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Subscription attached.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/x-ext/896165a"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "501": {
            "$ref": "#/components/responses/NotImplemented"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    }
  },
  "x-ext-urls": {
    "55e83fe": "enums/AppType.yaml",
    "fa98d95": "enums/HostingProduct.yaml",
    "e7c120b": "types/Pagination.yaml",
    "21ae8c5": "common-types/v1/schemas/yaml/error.yaml",
    "40b48f1": "common-types/v1/schemas/yaml/error-details.yaml",
    "590647a": "common-types/v1/schemas/yaml/link-description.yaml",
    "70f5935": "types/PagedList.yaml",
    "a87153c": "models/Application.yaml",
    "175517a": "enums/AppStatus.yaml",
    "cbb4385": "enums/AppSource.yaml",
    "c884c57": "models/GitHubSource.yaml",
    "37bf2ab": "common-types/v1/schemas/yaml/date-time.yaml",
    "edb0cb2": "models/Deployment.yaml",
    "34345ed": "enums/OperationStatus.yaml",
    "34c8cb4": "models/SecretList.yaml",
    "e8b6820": "models/Secret.yaml",
    "a699683": "enums/Environment.yaml",
    "7244d8c": "models/Domain.yaml",
    "d6b04e3": "enums/DomainRole.yaml",
    "41b11db": "enums/DomainVerificationStatus.yaml",
    "8a11b44": "enums/CdnStatus.yaml",
    "e037d3b": "enums/DomainType.yaml",
    "d018c9e": "models/HostingSubscription.yaml",
    "9fa0221": "models/LogEntry.yaml",
    "d7d4644": "enums/LogLevel.yaml",
    "33c2cb4": "enums/LogSource.yaml",
    "0bebd09": "models/AppOperation.yaml",
    "2e3b863": "models/AppOperationApplication.yaml",
    "785f9fe": "common-types/v1/schemas/yaml/patch-request.yaml",
    "22b55f1": "common-types/v1/schemas/yaml/patch.yaml",
    "509c3ac": "models/ApplicationStatus.yaml",
    "401b226": "models/EnvironmentVariant.yaml",
    "23e638a": "models/SourceImport.yaml",
    "c3448d8": "enums/ImportType.yaml",
    "3c029b5": "models/ScopedSecretSet.yaml",
    "92a6c61": "models/RuntimeVersion.yaml",
    "896165a": "models/SubscriptionAttachment.yaml",
    "4b51c7c": "enums/AttachState.yaml",
    "a215287": "enums/AppState.yaml"
  },
  "x-ext": {
    "55e83fe": {
      "title": "AppType",
      "type": "string",
      "description": "The product type for a hosted application. Required on list and create operations. Each application id is prefixed with its application type in upper case — an upper-case letter followed by any number of upper-case letters, digits, or underscores — then a hyphen, then the identifier (e.g. `NODEJS-v1StcMHAbqMs`), so item-scoped requests do not require this parameter. Additional product types will be added to this enum as they come online. Clients must tolerate values not listed here.\n",
      "examples": [
        "NODEJS"
      ]
    },
    "fa98d95": {
      "title": "HostingProduct",
      "type": "string",
      "description": "The hosting product a subscription applies to. Clients must tolerate values not listed here.\n",
      "examples": [
        "WEB_HOSTING",
        "MANAGED_WORDPRESS"
      ]
    },
    "e7c120b": {
      "properties": {
        "pageToken": {
          "type": "string"
        },
        "pageSize": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 25
        },
        "totalRequired": {
          "type": "boolean",
          "default": false
        }
      },
      "type": "object"
    },
    "40b48f1": {
      "title": "Error Details",
      "type": "object",
      "description": "The error details. Required for client-side `4XX` errors.",
      "properties": {
        "field": {
          "type": "string",
          "description": "The field that caused the error. If the field is in the body, set this value to the JSON pointer to that field. Required for client-side errors."
        },
        "value": {
          "type": "string",
          "description": "The value of the field that caused the error."
        },
        "location": {
          "type": "string",
          "description": "The location of the field that caused the error. Value is `body`, `path`, or `query`.",
          "default": "body"
        },
        "issue": {
          "type": "string",
          "description": "The unique fine-grained application-level error code."
        },
        "description": {
          "type": "string",
          "description": "The human-readable description for an issue. The description MAY change over the lifetime of an API, so clients MUST NOT depend on this value."
        }
      },
      "required": [
        "issue"
      ]
    },
    "590647a": {
      "title": "Link Description",
      "type": "object",
      "description": "A request-related [HATEOAS link](https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-hyperschema-02).",
      "properties": {
        "href": {
          "description": "The complete target URL, or link, to use in combination with the method to make the related call, as defined by [RFC 6570 - URI Template](https://tools.ietf.org/html/rfc6570), with the addition of the `$`, `(`, and `)` characters for pre-processing. The `href` is the key HATEOAS component that links a completed call with a subsequent call.",
          "type": "string",
          "format": "uri"
        },
        "rel": {
          "description": "The [link relation type](https://tools.ietf.org/html/rfc5988#section-4), which is an identifier for a link that unambiguously describes the semantics of the link. For values, see [Link Relationship Types](https://www.iana.org/assignments/link-relations/link-relations.xhtml).",
          "type": "string"
        },
        "title": {
          "description": "The link title.",
          "type": "string"
        },
        "targetMediaType": {
          "description": "The [RFC 2046-defined media type](https://www.ietf.org/rfc/rfc2046.txt) that describes the link target.",
          "type": "string"
        },
        "targetSchema": {
          "description": "The schema that describes the link target."
        },
        "method": {
          "description": "The method to use to request the link target. For example, for HTTP, this might be `GET` or `DELETE`.",
          "type": "string"
        },
        "submissionMediaType": {
          "description": "The media type with which to submit data with the request.",
          "type": "string",
          "default": "application/json"
        },
        "submissionSchema": {
          "description": "The schema that describes the request data."
        }
      },
      "required": [
        "rel",
        "href"
      ]
    },
    "21ae8c5": {
      "type": "object",
      "title": "Error",
      "description": "The error information.",
      "definitions": {
        "error-details": {
          "$ref": "#/x-ext/40b48f1"
        },
        "link-description": {
          "$ref": "#/x-ext/590647a"
        }
      },
      "properties": {
        "name": {
          "type": "string",
          "description": "The human-readable, unique name of the error."
        },
        "correlationId": {
          "type": "string",
          "description": "Internal identifier used for correlation purposes."
        },
        "message": {
          "type": "string",
          "description": "The message that describes the error."
        },
        "informationLink": {
          "type": "string",
          "description": "The URI for detailed information related to this error for the developer."
        },
        "details": {
          "type": "array",
          "description": "An array of additional details about the error. Required for client-side `4XX` errors.",
          "additionalItems": false,
          "items": {
            "$ref": "#/x-ext/21ae8c5/definitions/error-details"
          }
        },
        "links": {
          "type": "array",
          "description": "An array of error-related HATEOAS links.",
          "readOnly": true,
          "items": {
            "$ref": "#/x-ext/21ae8c5/definitions/link-description",
            "readOnly": true
          }
        }
      },
      "required": [
        "name",
        "correlationId",
        "message"
      ]
    },
    "70f5935": {
      "type": "object",
      "required": [
        "items"
      ],
      "properties": {
        "items": {
          "type": "array"
        },
        "totalItems": {
          "type": "integer",
          "minimum": 0,
          "description": "Total number of items across all pages. Only populated when `totalRequired=true`.\n"
        },
        "totalPages": {
          "type": "integer",
          "minimum": 0,
          "description": "Total number of pages. Only populated when `totalRequired=true`.\n"
        },
        "links": {
          "type": "array",
          "description": "HATEOAS navigation links. May include `rel=self`, `rel=next`, `rel=prev`, `rel=first`, and `rel=last` depending on the current page position. Clients should navigate by following `links[rel=next].href` rather than constructing URLs manually.\n",
          "items": {
            "$ref": "#/x-ext/590647a"
          }
        }
      }
    },
    "175517a": {
      "title": "AppStatus",
      "type": "string",
      "description": "Lifecycle state of a hosted application. When `POST /apps` is used, the application is `ACTIVE` by the time the `AppOperation` reaches `COMPLETED` — no secondary poll of `GET /apps/{appId}` is required. `FAILED` is a terminal state indicating that provisioning did not complete successfully. `DELETING` is a transient state while the application is being removed. `SUSPENDED` indicates the application has been suspended. `UNKNOWN` is emitted by the service when the underlying hosting platform reports a status this API does not model; treat it as \"state not determinable\" rather than as a healthy application. Clients must tolerate values not listed here.\n",
      "examples": [
        "CREATING",
        "ACTIVE",
        "FAILED",
        "DELETING",
        "SUSPENDED",
        "UNKNOWN"
      ]
    },
    "cbb4385": {
      "title": "AppSource",
      "type": "string",
      "description": "Indicates how the source code for an application was supplied.",
      "examples": [
        "ZIP",
        "GITHUB"
      ]
    },
    "c884c57": {
      "title": "GitHubSource",
      "type": "object",
      "required": [
        "repositoryFullName",
        "branch"
      ],
      "properties": {
        "repositoryFullName": {
          "type": "string",
          "description": "Repository in owner/repo format."
        },
        "branch": {
          "type": "string",
          "description": "Branch to import from."
        }
      }
    },
    "37bf2ab": {
      "description": "A date and time, in [Internet date and time format](https://tools.ietf.org/html/rfc3339#section-5.6). Note: The regular expression provides static schematic guidance but does not reject all invalid dates.",
      "type": "string",
      "minLength": 20,
      "maxLength": 64,
      "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])[T,t]([0-1][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)([.][0-9]+)?([Zz]|[+-][0-9]{2}:[0-9]{2})$"
    },
    "a87153c": {
      "title": "Application",
      "type": "object",
      "description": "A hosted application. After creation, `status` will be `CREATING`. Poll `GET /apps/{appId}` until it reaches `ACTIVE` or `FAILED`.\n",
      "required": [
        "id",
        "name",
        "appType",
        "status",
        "urls",
        "createdAt",
        "updatedAt",
        "links"
      ],
      "properties": {
        "id": {
          "type": "string",
          "readOnly": true,
          "pattern": "^[A-Z][A-Z0-9_]*-[A-Za-z0-9_-]+$",
          "description": "Server-assigned identifier. The prefix is the application type in upper case — an upper-case letter followed by any number of upper-case letters, digits, or underscores — then a hyphen, then a product-specific suffix. For `NODEJS`, the suffix is a 10-character nanoid (e.g. `NODEJS-aBcDeFgHiJ`).\nThe prefix lets you identify the product type from the id without an extra lookup. Immutable.\n",
          "examples": [
            "NODEJS-aBcDeFgHiJ"
          ]
        },
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200,
          "description": "Human-readable display name for the application."
        },
        "appType": {
          "readOnly": true,
          "$ref": "#/x-ext/55e83fe"
        },
        "status": {
          "readOnly": true,
          "$ref": "#/x-ext/175517a"
        },
        "source": {
          "readOnly": true,
          "$ref": "#/x-ext/cbb4385"
        },
        "sourceDetails": {
          "readOnly": true,
          "description": "Present when source is GITHUB. Null when ZIP or no import has been performed.",
          "oneOf": [
            {
              "$ref": "#/x-ext/c884c57"
            },
            {
              "type": "null"
            }
          ]
        },
        "urls": {
          "type": "object",
          "readOnly": true,
          "description": "Environment URLs assigned to this application.",
          "properties": {
            "preview": {
              "type": [
                "string",
                "null"
              ],
              "format": "uri",
              "description": "Preview environment URL."
            },
            "publish": {
              "type": [
                "string",
                "null"
              ],
              "format": "uri",
              "description": "Publish environment URL."
            }
          }
        },
        "region": {
          "type": "string",
          "readOnly": true,
          "description": "Datacenter region the application is provisioned into, in the same form as `AppOperationApplication.region`. Emitted today only on the items of `GET /apps`; omitted on `GET /apps/{appId}` and whenever the platform does not report one. Today `na` and `eu` are emitted; this is not a closed set, so treat an unlisted value as valid.\n",
          "examples": [
            "na",
            "eu"
          ]
        },
        "createdAt": {
          "readOnly": true,
          "$ref": "#/x-ext/37bf2ab"
        },
        "updatedAt": {
          "readOnly": true,
          "$ref": "#/x-ext/37bf2ab"
        },
        "links": {
          "type": "array",
          "readOnly": true,
          "description": "HATEOAS navigation links for this resource. When present, `rel=self` is the canonical URL of the application (`GET /apps/{appId}`).\n",
          "items": {
            "$ref": "#/x-ext/590647a"
          }
        }
      }
    },
    "34345ed": {
      "title": "OperationStatus",
      "type": "string",
      "description": "Progress state of an asynchronous operation. Poll the URL returned in `links[rel=self]` until the status reaches `COMPLETED` or `FAILED`. Clients must tolerate values not listed here.\n",
      "examples": [
        "PENDING",
        "IN_PROGRESS",
        "COMPLETED",
        "FAILED"
      ]
    },
    "edb0cb2": {
      "title": "Deployment",
      "type": "object",
      "description": "An asynchronous deployment operation. Poll `GET /apps/{appId}/deployments/{deploymentId}` until `status` reaches `COMPLETED` or `FAILED`.\n",
      "required": [
        "deploymentId",
        "status",
        "createdAt",
        "updatedAt",
        "links"
      ],
      "properties": {
        "deploymentId": {
          "type": "string",
          "readOnly": true,
          "description": "Server-assigned deployment identifier."
        },
        "status": {
          "readOnly": true,
          "$ref": "#/x-ext/34345ed"
        },
        "gitHash": {
          "type": [
            "string",
            "null"
          ],
          "readOnly": true,
          "description": "The Git commit hash deployed. Null when no source has been imported yet.\n"
        },
        "createdAt": {
          "readOnly": true,
          "$ref": "#/x-ext/37bf2ab"
        },
        "updatedAt": {
          "readOnly": true,
          "$ref": "#/x-ext/37bf2ab"
        },
        "error": {
          "readOnly": true,
          "description": "Populated when `status` is `FAILED`. Describes why the deployment did not complete.\n",
          "oneOf": [
            {
              "$ref": "#/x-ext/21ae8c5"
            },
            {
              "type": "null"
            }
          ]
        },
        "logs": {
          "type": "array",
          "readOnly": true,
          "description": "Build and publish log lines captured for this deployment, oldest first. Omitted when no lines have been captured yet. This is a convenience excerpt; read the full stream with `GET /apps/{appId}/deployments/{deploymentId}/logs`.\n",
          "items": {
            "type": "string"
          }
        },
        "links": {
          "type": "array",
          "readOnly": true,
          "description": "HATEOAS navigation links for this resource. When present, `rel=self` is the canonical URL of the deployment (`GET /apps/{appId}/deployments/{deploymentId}`), suitable as a poll target.\n",
          "items": {
            "$ref": "#/x-ext/590647a"
          }
        }
      }
    },
    "e8b6820": {
      "title": "Secret",
      "type": "object",
      "description": "Metadata for an environment secret. Secret values are write-only and are never returned in any response. To write a secret, send `PATCH /apps/{appId}/secrets?variant=PREVIEW` or `?variant=PUBLISH` with a JSON Patch path of `/{name}`.\n",
      "required": [
        "name",
        "systemManaged"
      ],
      "properties": {
        "name": {
          "type": "string",
          "description": "The secret key name as it appears in the application environment."
        },
        "systemManaged": {
          "type": "boolean",
          "readOnly": true,
          "description": "`true` for secrets injected by the platform. System-managed secrets cannot be updated or deleted.\n"
        },
        "createdAt": {
          "readOnly": true,
          "description": "The time the secret was created. Null when the backend does not record a creation timestamp.\n",
          "oneOf": [
            {
              "$ref": "#/x-ext/37bf2ab"
            },
            {
              "type": "null"
            }
          ]
        },
        "updatedAt": {
          "readOnly": true,
          "description": "The time the secret value was last updated. Null if never updated since creation.",
          "oneOf": [
            {
              "$ref": "#/x-ext/37bf2ab"
            },
            {
              "type": "null"
            }
          ]
        }
      }
    },
    "34c8cb4": {
      "title": "SecretList",
      "type": "object",
      "description": "The full set of secrets for an application, returned as a single page. Each application is capped at 50 secrets, so no `links[rel=next]` is emitted and no cursor is required.\n",
      "required": [
        "items"
      ],
      "properties": {
        "items": {
          "type": "array",
          "items": {
            "$ref": "#/x-ext/e8b6820"
          }
        }
      }
    },
    "a699683": {
      "title": "Environment",
      "type": "string",
      "description": "A hosted application's runtime environment. `PREVIEW` is the staging variant used to validate a deployment before it is promoted; `PUBLISH` is the live variant that serves production traffic. In responses, clients must tolerate values not listed here — this enumeration may gain members as new variants come online. In requests it is closed: a value outside this list is rejected with `400`.\n",
      "examples": [
        "PREVIEW",
        "PUBLISH"
      ]
    },
    "d6b04e3": {
      "title": "DomainRole",
      "type": "string",
      "description": "Whether a domain is the primary domain for the application or an additional alias.\n",
      "enum": [
        "PRIMARY",
        "ADDITIONAL"
      ]
    },
    "41b11db": {
      "title": "DomainVerificationStatus",
      "type": "string",
      "description": "Current DNS verification state of a domain attachment. `PENDING` means the domain has not yet been confirmed as pointing to the application. `ACTIVE` means DNS is verified and the domain is live. `DELETING` means removal is in progress. `FAILED` means verification did not complete. Clients must tolerate values not listed here.\n",
      "examples": [
        "PENDING",
        "ACTIVE",
        "DELETING",
        "FAILED"
      ]
    },
    "8a11b44": {
      "title": "CdnStatus",
      "type": "string",
      "description": "CDN provisioning state for a domain attachment. `INIT` means CDN setup has not started. `PENDING` means provisioning is in progress. `ACTIVE` means the CDN is serving the domain. `ERROR` means provisioning failed. `DELETED` means the CDN configuration has been removed. Clients must tolerate values not listed here.\n",
      "examples": [
        "INIT",
        "PENDING",
        "ACTIVE",
        "ERROR",
        "DELETED"
      ]
    },
    "e037d3b": {
      "title": "DomainType",
      "type": "string",
      "description": "How the domain was attached. `CUSTOM` is a customer-owned hostname. `PREFIX` is a platform-managed subdomain.\n",
      "enum": [
        "PREFIX",
        "CUSTOM"
      ]
    },
    "7244d8c": {
      "title": "Domain",
      "type": "object",
      "description": "A custom domain attached to an application. After calling `POST /apps/{appId}/domains`, poll `GET /apps/{appId}/domains/{domainId}` until `verificationStatus` reaches `ACTIVE` or `FAILED`.\n",
      "required": [
        "domainId",
        "hostname",
        "role",
        "verificationStatus",
        "certificateValidationCname",
        "anycastIp",
        "cdnStatus",
        "domainType",
        "links"
      ],
      "properties": {
        "domainId": {
          "type": "string",
          "readOnly": true,
          "description": "Server-assigned domain attachment identifier."
        },
        "hostname": {
          "type": "string",
          "readOnly": true,
          "description": "The fully-qualified domain name.",
          "examples": [
            "www.example.com"
          ]
        },
        "role": {
          "$ref": "#/x-ext/d6b04e3",
          "readOnly": true,
          "description": "Whether this domain is the primary domain for the application or an additional alias.\n"
        },
        "verificationStatus": {
          "$ref": "#/x-ext/41b11db",
          "readOnly": true,
          "description": "Current DNS verification state. `PENDING` means the domain has not yet been confirmed as pointing to this application. `ACTIVE` means DNS is verified and the domain is live. `DELETING` means removal is in progress. `FAILED` means verification did not complete. Check that the domain's A record points to `anycastIp` and that certificate validation (when required) uses `certificateValidationCname`, then try again.\n"
        },
        "certificateValidationCname": {
          "type": [
            "string",
            "null"
          ],
          "readOnly": true,
          "description": "Target hostname for the `_acme-challenge` CNAME used to prove domain ownership for certificate issuance. Null until issuance starts.\n",
          "examples": [
            "_acme-challenge.example.com.validation.example.net"
          ]
        },
        "anycastIp": {
          "type": [
            "string",
            "null"
          ],
          "readOnly": true,
          "description": "IPv4 address to use as the domain's A record once ownership is verified and routing is ready. Null until that address is available.\n",
          "examples": [
            "192.0.2.10"
          ]
        },
        "cdnStatus": {
          "readOnly": true,
          "description": "CDN provisioning state for this domain. Null when CDN state has not been reported yet.\n",
          "oneOf": [
            {
              "$ref": "#/x-ext/8a11b44"
            },
            {
              "type": "null"
            }
          ]
        },
        "domainType": {
          "$ref": "#/x-ext/e037d3b",
          "readOnly": true,
          "description": "How the domain was attached: `CUSTOM` for a customer-owned hostname, or `PREFIX` for a platform-managed subdomain.\n"
        },
        "links": {
          "type": "array",
          "readOnly": true,
          "description": "HATEOAS navigation links for this resource. When present, `rel=self` is the canonical URL of the domain attachment (`GET /apps/{appId}/domains/{domainId}`), suitable as a poll target.\n",
          "items": {
            "$ref": "#/x-ext/590647a"
          }
        }
      }
    },
    "d018c9e": {
      "title": "HostingSubscription",
      "type": "object",
      "description": "A hosting subscription belonging to the authenticated user, including how many application slots have been used and the total available.\n",
      "required": [
        "subscriptionId",
        "hostingProduct",
        "tier",
        "label",
        "status",
        "attachedCount",
        "slotLimit",
        "availableSlots",
        "links"
      ],
      "properties": {
        "subscriptionId": {
          "type": "string",
          "readOnly": true,
          "description": "Opaque subscription identifier."
        },
        "hostingProduct": {
          "$ref": "#/x-ext/fa98d95",
          "description": "The hosting product associated with this subscription."
        },
        "tier": {
          "type": "string",
          "examples": [
            "ECONOMY",
            "DELUXE",
            "ULTIMATE"
          ],
          "readOnly": true,
          "description": "Plan tier of this subscription. Product-specific; other values may appear.\n"
        },
        "label": {
          "type": "string",
          "readOnly": true,
          "description": "Human-readable label for this subscription, suitable for display in a subscription picker.\n"
        },
        "status": {
          "type": "string",
          "examples": [
            "ACTIVE",
            "SUSPENDED"
          ],
          "readOnly": true,
          "description": "Billing status of this subscription. `ACTIVE` means the plan is in good standing; `SUSPENDED` means it has lapsed. Product-specific; other values may appear.\n"
        },
        "attachedCount": {
          "type": "integer",
          "minimum": 0,
          "readOnly": true,
          "description": "Number of application slots currently in use."
        },
        "slotLimit": {
          "type": "integer",
          "minimum": 0,
          "readOnly": true,
          "description": "Total number of application slots available on this subscription."
        },
        "availableSlots": {
          "type": "integer",
          "minimum": 0,
          "readOnly": true,
          "description": "Number of application slots still free on this subscription (`slotLimit` minus `attachedCount`).\n"
        },
        "paidThroughDate": {
          "$ref": "#/x-ext/37bf2ab",
          "readOnly": true,
          "examples": [
            "2027-08-06T00:00:00Z"
          ],
          "description": "The date and time through which this subscription is paid, as an RFC 3339 date-time. Omitted when the billing system does not report one.\n"
        },
        "links": {
          "type": "array",
          "readOnly": true,
          "description": "Reserved for future per-subscription HATEOAS links; currently always an empty array. The collection's `rel=self` (`GET /subscriptions`) lives on the `PagedSubscriptions` envelope, not here.\n",
          "items": {
            "$ref": "#/x-ext/590647a"
          }
        }
      }
    },
    "d7d4644": {
      "title": "LogLevel",
      "type": "string",
      "description": "Normalized severity level of a log entry. Entries whose raw level cannot be mapped to one of the values defined today are dropped, so no entry is returned carrying a level outside this list. This enumeration may still gain members in a future version of this specification; clients must tolerate values not listed here.\n",
      "examples": [
        "INFO",
        "WARN",
        "ERROR"
      ]
    },
    "33c2cb4": {
      "title": "LogSource",
      "type": "string",
      "description": "Origin stream of a log entry. Entries whose raw source cannot be mapped to one of the values defined today are dropped, so no entry is returned carrying a source outside this list. This enumeration may still gain members in a future version of this specification; clients must tolerate values not listed here.\n",
      "examples": [
        "STDOUT",
        "STDERR"
      ]
    },
    "9fa0221": {
      "title": "LogEntry",
      "type": "object",
      "description": "A single normalized log line from an application. The v2 endpoint always returns entries in this shape; entries that cannot be mapped to the normalized level or source values are silently dropped.\n",
      "required": [
        "timestamp",
        "level",
        "source",
        "message"
      ],
      "properties": {
        "timestamp": {
          "$ref": "#/x-ext/37bf2ab"
        },
        "level": {
          "$ref": "#/x-ext/d7d4644",
          "description": "Severity level of this log line."
        },
        "source": {
          "$ref": "#/x-ext/33c2cb4",
          "description": "Origin stream of this log line."
        },
        "message": {
          "type": "string",
          "description": "The raw log content."
        }
      }
    },
    "2e3b863": {
      "title": "AppOperationApplication",
      "type": "object",
      "description": "The creation-time view of an application, embedded in `AppOperation.app` when the operation reaches `COMPLETED`. It is a deliberate subset of `Application`: only the fields settled at creation are present. Read the full resource with `GET /apps/{appId}` — or follow `links[rel=self]` — once you need `name`, `appType`, `urls` or `updatedAt`.\n",
      "required": [
        "id",
        "status",
        "createdAt",
        "links"
      ],
      "properties": {
        "id": {
          "type": "string",
          "readOnly": true,
          "pattern": "^[A-Z][A-Z0-9_]*-[A-Za-z0-9_-]+$",
          "description": "Server-assigned identifier of the created application, in the same form as `Application.id`. Use it for all subsequent calls.\n",
          "examples": [
            "NODEJS-aBcDeFgHiJ"
          ]
        },
        "status": {
          "readOnly": true,
          "$ref": "#/x-ext/175517a"
        },
        "region": {
          "type": "string",
          "readOnly": true,
          "description": "Datacenter region the application was provisioned into. Omitted when the platform does not report one. Today `na` and `eu` are emitted; this is not a closed set, so treat an unlisted value as valid.\n",
          "examples": [
            "na",
            "eu"
          ]
        },
        "createdAt": {
          "readOnly": true,
          "$ref": "#/x-ext/37bf2ab"
        },
        "links": {
          "type": "array",
          "readOnly": true,
          "description": "HATEOAS navigation links for the created application. `rel=self` is the canonical URL of the application (`GET /apps/{appId}`).\n",
          "items": {
            "$ref": "#/x-ext/590647a"
          }
        }
      }
    },
    "0bebd09": {
      "title": "AppOperation",
      "type": "object",
      "description": "An asynchronous application-creation operation. `POST /apps` returns this resource before an `appId` has been assigned. Poll `GET /app-operations/{operationId}` until `status` reaches `COMPLETED` or `FAILED`. On `COMPLETED`, `app` contains an `AppOperationApplication` — the creation-time subset of the created application — with `status` guaranteed to be `ACTIVE`, so the application is ready to use. Use its `id` for all subsequent calls.\n",
      "required": [
        "operationId",
        "status",
        "links"
      ],
      "properties": {
        "operationId": {
          "type": "string",
          "readOnly": true,
          "description": "Server-assigned operation identifier."
        },
        "status": {
          "readOnly": true,
          "$ref": "#/x-ext/34345ed"
        },
        "app": {
          "readOnly": true,
          "description": "The created application, in its creation-time subset shape. Present when `status` is `COMPLETED`. Null otherwise. Follow `links[rel=self]` on it, or call `GET /apps/{appId}`, for the full `Application`.\n",
          "oneOf": [
            {
              "$ref": "#/x-ext/2e3b863"
            },
            {
              "type": "null"
            }
          ]
        },
        "error": {
          "readOnly": true,
          "description": "Populated when `status` is `FAILED`. Describes why the application could not be created.\n",
          "oneOf": [
            {
              "$ref": "#/x-ext/21ae8c5"
            },
            {
              "type": "null"
            }
          ]
        },
        "createdAt": {
          "readOnly": true,
          "description": "When the operation was accepted. Optional: the service does not supply it on every operation response, so clients must handle its absence.\n",
          "$ref": "#/x-ext/37bf2ab"
        },
        "links": {
          "type": "array",
          "readOnly": true,
          "description": "HATEOAS navigation links for this resource. When present, `rel=self` is the canonical URL of the operation (`GET /app-operations/{operationId}`), suitable as a poll target.\n",
          "items": {
            "$ref": "#/x-ext/590647a"
          }
        }
      }
    },
    "22b55f1": {
      "type": "object",
      "title": "Patch",
      "description": "The JSON patch object to apply partial updates to resources.",
      "properties": {
        "op": {
          "type": "string",
          "description": "The operation to complete.",
          "enum": [
            "add",
            "remove",
            "replace",
            "move",
            "copy",
            "test"
          ]
        },
        "path": {
          "type": "string",
          "description": "The JSON pointer to the target document location at which to complete the operation."
        },
        "value": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "integer"
            },
            {
              "type": "string"
            },
            {
              "type": "boolean"
            },
            {
              "type": "array",
              "items": {}
            },
            {
              "type": "object"
            }
          ],
          "nullable": true,
          "description": "The value to apply. The `remove` operation does not require a value."
        },
        "from": {
          "type": "string",
          "description": "The JSON pointer to the target document location from which to move the value. Required for the `move` operation."
        }
      },
      "required": [
        "op"
      ]
    },
    "785f9fe": {
      "type": "array",
      "title": "Patch Request",
      "description": "An array of JSON patch objects to apply partial updates to resources.",
      "items": {
        "$ref": "#/x-ext/22b55f1"
      }
    },
    "401b226": {
      "title": "EnvironmentVariant",
      "type": "object",
      "description": "Runtime state of a single environment (`PREVIEW` or `PUBLISH`) within an application.\n",
      "required": [
        "variant",
        "status"
      ],
      "properties": {
        "variant": {
          "$ref": "#/x-ext/a699683",
          "description": "The environment this variant represents."
        },
        "status": {
          "type": "string",
          "examples": [
            "RUNNING",
            "RESTARTING",
            "STOPPED"
          ],
          "description": "Runtime status of this environment. Product-specific; other values may appear.\n"
        },
        "lifecycleState": {
          "type": "string",
          "examples": [
            "PROVISIONED",
            "PROVISIONING",
            "SUSPENDED"
          ],
          "description": "Lifecycle state of this environment. Product-specific; other values may appear.\n"
        }
      }
    },
    "509c3ac": {
      "title": "ApplicationStatus",
      "type": "object",
      "description": "Detailed runtime status of an application, including per-environment state. Use as the poll target after `POST /apps/{appId}/restarts`.\n",
      "required": [
        "status",
        "variants",
        "links"
      ],
      "properties": {
        "status": {
          "$ref": "#/x-ext/175517a"
        },
        "variants": {
          "type": "array",
          "description": "Per-environment lifecycle detail.",
          "items": {
            "$ref": "#/x-ext/401b226"
          }
        },
        "links": {
          "type": "array",
          "readOnly": true,
          "description": "HATEOAS navigation links for this resource. When present, `rel=self` is the canonical URL of the application status (`GET /apps/{appId}/status`), suitable as a poll target after a restart.\n",
          "items": {
            "$ref": "#/x-ext/590647a"
          }
        }
      }
    },
    "c3448d8": {
      "title": "ImportType",
      "type": "string",
      "description": "Indicates how the source code for an import was supplied. `ZIP` means the source was uploaded as a zip archive. `GITHUB` means the source was pulled from a GitHub repository.\n",
      "enum": [
        "ZIP",
        "GITHUB"
      ]
    },
    "23e638a": {
      "title": "SourceImport",
      "type": "object",
      "description": "An asynchronous source-code import operation. Use `POST /apps/{appId}/imports` to start an import. Send a ZIP archive as `multipart/form-data`, or send a GitHub repository reference as `application/json`. The `importType` field in the response tells you which kind this is. Poll `GET /apps/{appId}/imports/{importId}` until `status` reaches `COMPLETED` or `FAILED`.\n",
      "required": [
        "importId",
        "importType",
        "status",
        "createdAt",
        "links"
      ],
      "properties": {
        "importId": {
          "type": "string",
          "readOnly": true,
          "description": "Server-assigned import identifier."
        },
        "importType": {
          "readOnly": true,
          "$ref": "#/x-ext/c3448d8"
        },
        "status": {
          "readOnly": true,
          "$ref": "#/x-ext/34345ed"
        },
        "gitHash": {
          "type": [
            "string",
            "null"
          ],
          "readOnly": true,
          "description": "The Git commit hash produced by this import. Populated on `COMPLETED` for `GITHUB` imports. Null otherwise.\n"
        },
        "createdAt": {
          "readOnly": true,
          "$ref": "#/x-ext/37bf2ab"
        },
        "error": {
          "readOnly": true,
          "description": "Populated when `status` is `FAILED`. Describes why the import did not complete.\n",
          "oneOf": [
            {
              "$ref": "#/x-ext/21ae8c5"
            },
            {
              "type": "null"
            }
          ]
        },
        "links": {
          "type": "array",
          "readOnly": true,
          "description": "HATEOAS navigation links for this resource. When present, `rel=self` is the canonical URL of the source import (`GET /apps/{appId}/imports/{importId}`), suitable as a poll target.\n",
          "items": {
            "$ref": "#/x-ext/590647a"
          }
        }
      }
    },
    "3c029b5": {
      "title": "ScopedSecretSet",
      "type": "object",
      "description": "Secret metadata after a patch. Values are never returned.\n",
      "required": [
        "shared",
        "variants"
      ],
      "properties": {
        "shared": {
          "type": "object",
          "readOnly": true,
          "description": "Secrets visible to both the `PREVIEW` and `PUBLISH` variants.\n",
          "required": [
            "secrets"
          ],
          "properties": {
            "secrets": {
              "type": "array",
              "description": "Shared-scope secret metadata. Empty when none are set.",
              "items": {
                "$ref": "#/x-ext/e8b6820"
              }
            }
          }
        },
        "variants": {
          "type": "object",
          "readOnly": true,
          "description": "Secrets scoped to a single environment variant, keyed by variant. A key is omitted when that variant has no variant-scoped secrets.\n",
          "properties": {
            "preview": {
              "type": "object",
              "description": "Secrets scoped to the `PREVIEW` variant.",
              "required": [
                "secrets"
              ],
              "properties": {
                "secrets": {
                  "type": "array",
                  "items": {
                    "$ref": "#/x-ext/e8b6820"
                  }
                }
              }
            },
            "publish": {
              "type": "object",
              "description": "Secrets scoped to the `PUBLISH` variant.",
              "required": [
                "secrets"
              ],
              "properties": {
                "secrets": {
                  "type": "array",
                  "items": {
                    "$ref": "#/x-ext/e8b6820"
                  }
                }
              }
            }
          }
        }
      }
    },
    "92a6c61": {
      "title": "RuntimeVersion",
      "type": "object",
      "description": "The version of a single runtime component for an application.",
      "required": [
        "runtime",
        "version"
      ],
      "properties": {
        "runtime": {
          "type": "string",
          "description": "Identifies which runtime this entry describes.",
          "examples": [
            "NODE",
            "PHP",
            "WORDPRESS"
          ]
        },
        "version": {
          "type": "string",
          "description": "Version of the runtime in use.",
          "examples": [
            "20",
            "22",
            "8.3",
            "6.5"
          ]
        }
      }
    },
    "4b51c7c": {
      "title": "AttachState",
      "type": "string",
      "description": "Current state of a subscription attachment on an application. `ACTIVE` means the subscription is attached and the plan is in good standing. `SUSPENDED` means the plan has lapsed but the attachment record still exists.\n\n`CANCELLED` is reserved and is not emitted today: it is intended for a cancelled subscription whose attachment record is still returned, so clients could distinguish that state from no attachment ever having existed. The service currently returns `ACTIVE` or `SUSPENDED` only. The member is declared so that clients written against this specification already tolerate it when it does begin to appear.\n",
      "enum": [
        "ACTIVE",
        "SUSPENDED",
        "CANCELLED"
      ]
    },
    "a215287": {
      "title": "AppState",
      "type": "string",
      "description": "Which environment of the application the attached subscription is currently backing. `PUBLISHED` means the application has been published and the subscription covers the live environment; `PREVIEW` means only the preview environment is in use. This tracks the same environment axis as `Environment`, which grows as new variants come online. Clients must tolerate values not listed here.\n",
      "examples": [
        "PUBLISHED",
        "PREVIEW"
      ]
    },
    "896165a": {
      "title": "SubscriptionAttachment",
      "type": "object",
      "description": "The subscription currently attached to an application. Returned by `GET /apps/{appId}/subscription` and `PUT /apps/{appId}/subscription`.\n",
      "required": [
        "subscriptionId",
        "hostingProduct",
        "attachState",
        "appState",
        "links"
      ],
      "properties": {
        "subscriptionId": {
          "type": [
            "string",
            "null"
          ],
          "description": "The identifier of the attached subscription. Null when an attachment record exists without an associated subscription (a legacy shape the platform still permits); always non-null in the response to `PUT /apps/{appId}/subscription`.\n"
        },
        "hostingProduct": {
          "$ref": "#/x-ext/fa98d95",
          "description": "The hosting product associated with the attached subscription."
        },
        "attachState": {
          "$ref": "#/x-ext/4b51c7c",
          "description": "Current attachment state. The endpoint returns `404` only when no attachment has ever been created for this application; a lapsed attachment is still returned so clients can distinguish that state from a fresh application. `ACTIVE` and `SUSPENDED` are the only values emitted today — `CANCELLED` is reserved, see `AttachState`.\n"
        },
        "appState": {
          "$ref": "#/x-ext/a215287",
          "description": "Which environment of the application the subscription currently backs. `PUBLISHED` once the application has been published; `PREVIEW` while only the preview environment is in use.\n"
        },
        "links": {
          "type": "array",
          "readOnly": true,
          "description": "HATEOAS navigation links for this resource. When present, `rel=self` is the canonical URL of the attachment (`GET /apps/{appId}/subscription`).\n",
          "items": {
            "$ref": "#/x-ext/590647a"
          }
        }
      }
    }
  }
}
