openapi: 3.0.3
info:
  title: Studio Platform API
  version: 1.0.0
  description: |
    # Introduction

    The Studio Platform API lets you manage your workspace account programmatically. You can use it to automate common tasks that would otherwise be performed from the dashboard, such as creating, updating, listing, and deleting projects.

    The API is RESTful: it uses predictable resource URLs, standard HTTP response codes, and JSON request and response bodies. It is useful for automations, internal tools, and integrations that need to create or manage Studio resources from your own backend or workflows.

    # Authentication

    All Platform API endpoints are private and require bearer authentication.

    Most endpoints authenticate with a bearer API key. Some trusted client-side flows can instead use a short-lived access token created from an API key.

    You can create and manage API keys from the [Platform API dashboard](https://app.grapesjs.com/dashboard/platform-api).

    Your API key acts like a password, so keep it guarded and secure. Do not expose it in client-side code, public repositories, or places where end users can access it.

    Send your API key in the `Authorization` header on every request:

    `Authorization: Bearer YOUR_API_KEY`
servers:
  - url: https://api.grapesjs.com/v1
security:
  - BearerAuth: []
tags:
  - name: Projects
    description: Create, list, update, fetch, and delete projects.
  - name: Deploys
    description: Configure deployment targets and publish project files.
  - name: Internal
    x-scalar-ignore: true
  - name: Templates
    description: List and fetch public and workspace templates.
  - name: AI
    description: Stream AI-assisted responses for Studio integrations such as the AI chat plugin.
  - name: Access Tokens
    description: Generate short-lived access tokens for trusted client-side flows.
paths:
  /access-tokens:
    post:
      operationId: createAccessToken
      tags:
        - Access Tokens
      summary: Create access token
      description: |
        Creates a short-lived access token for trusted client-side flows.

        To use when your backend needs to hand temporary credentials to trusted client-side code.

        This is currently intended for the `/ai/chat` endpoint used by the [AI chat plugin](https://app.grapesjs.com/docs-sdk/plugins/ai/overview).

      responses:
        '200':
          description: Access token created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AccessToken'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /ai/chat:
    post:
      operationId: createAiChatStream
      tags:
        - AI
      summary: Start an AI chat stream
      description: |
        Starts a streaming AI chat session, used by [AI chat plugin](https://app.grapesjs.com/docs-sdk/plugins/ai/overview).

        This endpoint is intended to be used with a short-lived access token created with `/access-tokens` for trusted client-side requests.

        The response is a SSE stream in the AI SDK UI message format, consumed directly by the chat transport.

        For more information about the AI chat plugin setup refer to this [guide](https://app.grapesjs.com/docs-sdk/plugins/ai/ai-chat#chat-platform-api).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AiChatRequest'
      responses:
        '200':
          description: Streaming response started successfully
          content:
            text/event-stream:
              schema:
                type: string
                format: binary
              examples:
                stream:
                  summary: SSE stream
                  value: |
                    data: {"type":"start"}

        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ErrorResponse403'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /projects:
    get:
      operationId: listProjects
      tags:
        - Projects
      summary: List projects
      description: Returns projects with page-based pagination.
      parameters:
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/ProjectType'
        - $ref: '#/components/parameters/IsTemplate'
      responses:
        '200':
          description: Projects listed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListProjectsResult'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
    post:
      operationId: createProject
      tags:
        - Projects
      summary: Create a project
      description: |
        Creates a new project.

        If `projectData` is not provided, an empty project is created based on the provided `type`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateProjectRequest'
      responses:
        '201':
          description: Project created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /projects/{projectId}:
    parameters:
      - $ref: '#/components/parameters/ProjectId'
    get:
      operationId: getProject
      tags:
        - Projects
      summary: Get a project
      description: Returns a single project and optionally includes project data.
      parameters:
        - $ref: '#/components/parameters/WithProjectData'
      responses:
        '200':
          description: Project fetched successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
    put:
      operationId: updateProject
      tags:
        - Projects
      summary: Update a project
      description: |
        Updates project metadata.

        If `projectData` is provided, it overwrites the existing stored project data.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateProjectRequest'
      responses:
        '200':
          description: Project updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
    delete:
      operationId: deleteProject
      tags:
        - Projects
      summary: Delete a project
      description: Deletes the project and all related data.
      responses:
        '200':
          description: Project deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteProjectResult'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /projects/{projectId}/files:
    parameters:
      - $ref: '#/components/parameters/ProjectId'
    get:
      operationId: getProjectFiles
      tags:
        - Projects
      summary: Get project files
      description: Returns the stored text-based files generated by the editor for a project.
      responses:
        '200':
          description: Project files fetched successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectFilesResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /projects/{projectId}/deploy-targets:
    parameters:
      - $ref: '#/components/parameters/ProjectId'
    get:
      operationId: listDeployTargets
      tags:
        - Deploys
      summary: List deploy targets
      description: Lists the project's reusable deployment destinations. Each deploy target has an immutable subdomain and an optional primary custom domain.
      parameters:
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
      responses:
        '200':
          description: Deploy targets fetched successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListDeployTargetsResult'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
    post:
      operationId: createDeployTarget
      tags:
        - Deploys
      summary: Create a deploy target
      description: Creates a reusable deployment destination for this project. Targets let a project use separate environments such as production and staging.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateDeployTargetRequest'
      responses:
        '201':
          description: Deploy target created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeployTargetResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /projects/{projectId}/deploy-targets/{targetId}:
    parameters:
      - $ref: '#/components/parameters/ProjectId'
      - $ref: '#/components/parameters/DeployTargetId'
    get:
      operationId: getDeployTarget
      tags:
        - Deploys
      summary: Get a deploy target
      description: Returns one deployment destination, including its configured domains, preferred URL, and latest deployment state.
      responses:
        '200':
          description: Deploy target fetched successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeployTargetDetailsResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
    patch:
      operationId: updateDeployTarget
      tags:
        - Deploys
      summary: Update a deploy target
      description: Updates the mutable configuration of a deployment destination. The display name and primary custom domain can change; the target subdomain and provider cannot.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateDeployTargetRequest'
      responses:
        '200':
          description: Deploy target updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeployTargetResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
    delete:
      operationId: deleteDeployTarget
      tags:
        - Deploys
      summary: Delete a deploy target
      description: Permanently removes a deployment destination, including its external project, primary custom-domain association, and deployment history. This action cannot be undone.
      responses:
        '200':
          description: Deploy target deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteDeployTargetResult'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /projects/{projectId}/deploy-targets/{targetId}/deploy:
    parameters:
      - $ref: '#/components/parameters/ProjectId'
      - $ref: '#/components/parameters/DeployTargetId'
    post:
      operationId: deployDeployTarget
      tags:
        - Deploys
      summary: Deploy a target
      description: Publishes the project's saved editor files to this deploy target. Fetch the target afterward to check the latest deployment status.
      responses:
        '200':
          description: Deploy target published successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeployTargetDetailsResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /projects/{projectId}/deploys:
    parameters:
      - $ref: '#/components/parameters/ProjectId'
    get:
      operationId: listDeployments
      tags:
        - Internal
      summary: List deployments
      description: Lists the project's deployment history across every deploy target. Each deployment is a publish attempt of the project's saved editor files to one target.
      parameters:
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
      responses:
        '200':
          description: Deployments fetched successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListDeploymentsResult'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
    post:
      operationId: createDeployment
      tags:
        - Internal
      summary: Create a deployment
      description: Publishes the project's saved editor files to the specified deploy target and creates a deployment record. A deploy target must be created before a deployment can be requested.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateDeploymentRequest'
      responses:
        '201':
          description: Deployment created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeploymentResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /projects/{projectId}/deploys/{deploymentId}:
    parameters:
      - $ref: '#/components/parameters/ProjectId'
      - $ref: '#/components/parameters/DeploymentId'
    get:
      operationId: getDeployment
      tags:
        - Internal
      summary: Get a deployment
      description: Returns one deployment record and refreshes its current status. Use this endpoint to follow an individual publish attempt until it reaches a terminal state.
      responses:
        '200':
          description: Deployment fetched successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeploymentResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /exports:
    get:
      operationId: listExports
      tags:
        - Exports
      summary: List exports
      description: Returns export history for the authenticated workspace with page-based pagination.
      parameters:
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
      responses:
        '200':
          description: Exports listed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListExportsResult'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /exports/pdf:
    post:
      operationId: createPdfExport
      tags:
        - Exports
      summary: Export a PDF
      description: Renders a saved project page, HTML, or URL as a PDF. The response contains the export immediately when ready, or a processing export that can be fetched later.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePdfExportRequest'
      responses:
        '201':
          description: Export completed during the request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExportResponse'
        '202':
          description: Export is still processing
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExportResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ErrorResponse403'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /exports/image:
    post:
      operationId: createImageExport
      tags:
        - Exports
      summary: Export an image
      description: Renders a saved project page, HTML, or URL as an image. The response contains the export immediately when ready, or a processing export that can be fetched later.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateImageExportRequest'
      responses:
        '201':
          description: Export completed during the request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExportResponse'
        '202':
          description: Export is still processing
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExportResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/ErrorResponse403'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /exports/{exportId}:
    parameters:
      - $ref: '#/components/parameters/ExportId'
    get:
      operationId: getExport
      tags:
        - Exports
      summary: Get an export
      description: Returns an export and, when it is ready, a fresh private download URL.
      responses:
        '200':
          description: Export fetched successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExportResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /templates:
    get:
      operationId: listTemplates
      tags:
        - Templates
      summary: List templates
      description: Returns public and/or workspace templates with page-based pagination.
      parameters:
        - $ref: '#/components/parameters/Page'
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/TemplateSourceFilter'
        - $ref: '#/components/parameters/ProjectType'
        - $ref: '#/components/parameters/TemplateQuery'
      responses:
        '200':
          description: Templates listed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListTemplatesResult'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
  /templates/{templateId}:
    parameters:
      - $ref: '#/components/parameters/TemplateId'
    get:
      operationId: getTemplate
      tags:
        - Templates
      summary: Get a template
      description: Returns a single template and optionally includes project data.
      parameters:
        - $ref: '#/components/parameters/WithProjectData'
      responses:
        '200':
          description: Template fetched successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TemplateResponse'
        '400':
          $ref: '#/components/responses/ErrorResponse400'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '404':
          $ref: '#/components/responses/ErrorResponse404'
        '500':
          $ref: '#/components/responses/ErrorResponse500'
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key
      description: |
        Use bearer authentication for requests. Most endpoints use an API key, while some trusted client-side flows can use a short-lived access token created from an API key.

        Create and manage your API keys from the [Platform API dashboard](https://app.grapesjs.com/dashboard/platform-api).

        API keys act like passwords. Keep them guarded and secure, and never expose them in client-side code or public repositories.

        Include the key in the `Authorization` header:

        `Authorization: Bearer YOUR_API_KEY`
  parameters:
    Page:
      name: page
      in: query
      schema:
        type: integer
        minimum: 0
        default: 0
      description: Zero-based page index.
    PageSize:
      name: pageSize
      in: query
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 20
      description: Number of items to return per page.
    ProjectType:
      name: type
      in: query
      schema:
        $ref: '#/components/schemas/ProjectType'
      description: Optional project type filter.
    TemplateSourceFilter:
      name: source
      in: query
      schema:
        $ref: '#/components/schemas/TemplateSourceFilter'
        default: public
      description: Template source filter. Defaults to `public`.
    TemplateQuery:
      name: q
      in: query
      schema:
        type: string
      description: Optional case-insensitive text search over template name and description.
    IsTemplate:
      name: isTemplate
      in: query
      schema:
        type: boolean
      description: Optional template filter.
    TemplateId:
      name: templateId
      in: path
      required: true
      schema:
        type: string
        minLength: 24
        maxLength: 24
        pattern: '^[a-z][a-z0-9]{23}$'
      description: Template identifier.
    ProjectId:
      name: projectId
      in: path
      required: true
      schema:
        type: string
        minLength: 24
        maxLength: 24
        pattern: '^[a-z][a-z0-9]{23}$'
      description: Project identifier.
    DeployTargetId:
      name: targetId
      in: path
      required: true
      schema:
        type: string
        minLength: 24
        maxLength: 25
        pattern: '^[a-z][a-z0-9]{23,24}$'
      description: Deploy target identifier.
    DeploymentId:
      name: deploymentId
      in: path
      required: true
      schema:
        type: string
        minLength: 24
        maxLength: 25
        pattern: '^[a-z][a-z0-9]{23,24}$'
      description: Deployment identifier.
    ExportId:
      name: exportId
      in: path
      required: true
      schema:
        type: string
        minLength: 24
        maxLength: 25
        pattern: '^[a-z][a-z0-9]{23,24}$'
      description: Export identifier.
    WithProjectData:
      name: withProjectData
      in: query
      schema:
        type: boolean
      description: When true, include the stored project JSON in the response.
  responses:
    UnauthorizedResponse:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ErrorResponse400:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ErrorResponse403:
      description: Forbidden
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ErrorResponse404:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ErrorResponse500:
      description: Server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  schemas:
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
      required:
        - error
    AccessToken:
      type: object
      properties:
        accessToken:
          type: string
          example: at_ABCdef12_34567890ABCdef12345678901234567890
          description: Short-lived bearer token starting with `at_`, intended for trusted client-side access to allowed endpoints such as `/ai/chat`.
        expiresAt:
          type: string
          format: date-time
      required:
        - accessToken
        - expiresAt
    AiChatRequest:
      type: object
      additionalProperties: true
      properties:
        id:
          type: string
          description: Chat session identifier.
        messages:
          type: array
          description: Recent chat messages sent to the AI model.
          items:
            $ref: '#/components/schemas/AiChatMessage'
        projectContext:
          $ref: '#/components/schemas/AiChatProjectContext'
        settings:
          $ref: '#/components/schemas/AiChatSettings'
      required:
        - id
        - messages
        - projectContext
    AiChatSettings:
      type: object
      additionalProperties: false
      description: Optional settings for this chat request.
      properties:
        agentChat:
          type: object
          additionalProperties: false
          description: Main chat agent settings. Model selection and prompt customization are independent.
          properties:
            modelId:
              type: string
              minLength: 1
              description: ID of an active workspace text model. When omitted, the Studio chat model is used.
            prompt:
              $ref: '#/components/schemas/AiChatPromptInstructions'
        agentDev:
          type: object
          additionalProperties: false
          description: Code agent settings. Supplied system-prompt sections replace the corresponding defaults; omitted sections remain unchanged.
          properties:
            modelId:
              type: string
              minLength: 1
              description: ID of an active workspace text model. When omitted, the Studio code model is used.
            prompt:
              $ref: '#/components/schemas/AiDevPromptInstructions'
        agentImage:
          type: object
          additionalProperties: false
          description: Image generation settings. Prompt instructions surround the image prompt without changing reference images.
          properties:
            modelId:
              type: string
              minLength: 1
              description: ID of an active workspace image model. When omitted, the Studio image model is used.
            prompt:
              $ref: '#/components/schemas/AiChatPromptInstructions'
    AiChatPromptInstructions:
      type: object
      additionalProperties: false
      description: Prompt instructions before and after the built-in prompt. For chat, a supplied preamble replaces the default introductory preamble; the core system prompt remains unchanged.
      properties:
        preamble:
          type: string
          description: Instructions placed before the prompt. An empty string removes the default introductory preamble for chat.
        postamble:
          type: string
          description: Additional instructions placed after the prompt.
    AiDevPromptInstructions:
      type: object
      additionalProperties: false
      description: Optional code-agent system-prompt sections. Supplied strings replace individual sections, including Studio-specific defaults. An empty string removes a section. Only sections used by the current operation and project type apply.
      properties:
        preamble:
          type: string
          description: Initial task instructions.
        postamble:
          type: string
          description: Additional instructions appended to the system prompt.
        currentCode:
          type: string
          description: Current code context.
        mainPage:
          type: string
          description: Main page context.
        design:
          type: string
          description: Design instructions.
        imageRefs:
          type: string
          description: Image reference instructions.
        media:
          type: string
          description: Media usage instructions.
        icons:
          type: string
          description: Icon usage instructions.
        pageLinking:
          type: string
          description: Page linking instructions.
        css:
          type: string
          description: CSS instructions.
        responsiveStyles:
          type: string
          description: Responsive styling instructions.
        globalStyles:
          type: string
          description: Global styling instructions.
        plugins:
          type: string
          description: Installed plugin instructions.
        scripts:
          type: string
          description: Script instructions.
        output:
          type: string
          description: Generated code output instructions.
    AiChatMessage:
      type: object
      additionalProperties: true
      description: AI chat message object forwarded by the client.
    AiChatProjectContext:
      type: object
      additionalProperties: true
      description: AI chat project context object forwarded by the client.
    ProjectType:
      type: string
      enum:
        - web
        - email
    TemplateSource:
      type: string
      enum:
        - public
        - workspace
    TemplateSourceFilter:
      type: string
      enum:
        - public
        - workspace
        - all
      default: public
    ProjectData:
      type: object
      additionalProperties: true
      description: JSON payload produced by the editor that contains the full project structure and content.
    StoredProjectFile:
      type: object
      properties:
        path:
          type: string
          description: Optional directory path containing the file.
        pathname:
          type: string
          description: Canonical file path, including the file name.
        filename:
          type: string
          description: File name.
        mimeType:
          type: string
          description: MIME type of the file contents.
        content:
          type: string
          description: Text contents of the file.
      required:
        - pathname
        - filename
        - mimeType
        - content
    DeployProviderId:
      type: string
      enum:
        - default
      description: Deploy provider identifier. Omit this field to use the default provider.
    DeployTarget:
      type: object
      properties:
        id:
          type: string
          description: Deploy target ID.
        providerId:
          $ref: '#/components/schemas/DeployProviderId'
        subdomain:
          type: string
          description: Immutable subdomain for the deploy target.
        displayName:
          type: string
          nullable: true
          description: Optional human-readable target label.
        customDomain:
          type: string
          nullable: true
          description: Optional primary custom domain attached to the target.
        deployedUrl:
          type: string
          nullable: true
          description: Preferred deployed URL, using the custom domain when present.
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - providerId
        - subdomain
        - displayName
        - customDomain
        - deployedUrl
        - createdAt
        - updatedAt
    CreateDeployTargetRequest:
      type: object
      additionalProperties: false
      properties:
        providerId:
          $ref: '#/components/schemas/DeployProviderId'
        subdomain:
          type: string
          minLength: 1
          maxLength: 63
          pattern: '^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$'
          description: Optional subdomain for this target. When omitted, one is generated from the project name and ID.
        displayName:
          type: string
          minLength: 1
        customDomain:
          type: string
          minLength: 3
      required:
        - displayName
    UpdateDeployTargetRequest:
      type: object
      additionalProperties: false
      properties:
        displayName:
          type: string
          minLength: 1
        customDomain:
          type: string
          nullable: true
          minLength: 3
    DeployTargetResponse:
      type: object
      properties:
        target:
          $ref: '#/components/schemas/DeployTarget'
      required:
        - target
    DeployTargetDetails:
      allOf:
        - $ref: '#/components/schemas/DeployTarget'
        - type: object
          properties:
            status:
              allOf:
                - $ref: '#/components/schemas/DeploymentStatus'
              nullable: true
              description: Status of the latest deployment attempt.
            isDeployed:
              type: boolean
              description: Whether the latest deployment attempt is ready.
            lastDeployedAt:
              type: string
              format: date-time
              nullable: true
              description: Creation time of the latest ready deployment.
          required:
            - status
            - isDeployed
            - lastDeployedAt
    DeployTargetDetailsResponse:
      type: object
      properties:
        target:
          $ref: '#/components/schemas/DeployTargetDetails'
      required:
        - target
    ListDeployTargetsResult:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/DeployTarget'
        total:
          type: integer
        page:
          type: integer
        pageSize:
          type: integer
      required:
        - items
        - total
        - page
        - pageSize
    DeploymentStatus:
      type: string
      enum:
        - queued
        - building
        - ready
        - error
        - canceled
        - unknown
    DeleteDeployTargetResult:
      type: object
      properties:
        success:
          type: boolean
      required:
        - success
    Deployment:
      type: object
      properties:
        id:
          type: string
          description: Deployment record ID.
        deployTargetId:
          type: string
        providerId:
          $ref: '#/components/schemas/DeployProviderId'
        status:
          $ref: '#/components/schemas/DeploymentStatus'
        url:
          type: string
          nullable: true
        inspectorUrl:
          type: string
          nullable: true
        error:
          type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
      required:
        - id
        - deployTargetId
        - providerId
        - status
        - url
        - inspectorUrl
        - error
        - createdAt
    CreateDeploymentRequest:
      type: object
      additionalProperties: false
      properties:
        deployTargetId:
          type: string
          minLength: 24
          maxLength: 25
          pattern: '^[a-z][a-z0-9]{23,24}$'
      required:
        - deployTargetId
    DeploymentResponse:
      type: object
      properties:
        deployment:
          $ref: '#/components/schemas/Deployment'
      required:
        - deployment
    ListDeploymentsResult:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/Deployment'
        total:
          type: integer
        page:
          type: integer
        pageSize:
          type: integer
      required:
        - items
        - total
        - page
        - pageSize
    ExportStatus:
      type: string
      enum:
        - processing
        - ready
        - failed
    ExportSource:
      oneOf:
        - $ref: '#/components/schemas/ProjectExportSource'
        - $ref: '#/components/schemas/HtmlExportSource'
        - $ref: '#/components/schemas/UrlExportSource'
    ProjectExportSource:
      type: object
      additionalProperties: false
      properties:
        projectId:
          type: string
          minLength: 24
          maxLength: 24
          pattern: '^[a-z][a-z0-9]{23}$'
        filePath:
          type: string
          minLength: 1
      required:
        - projectId
    HtmlExportSource:
      type: object
      additionalProperties: false
      properties:
        html:
          type: string
          minLength: 1
      required:
        - html
    UrlExportSource:
      type: object
      additionalProperties: false
      properties:
        url:
          type: string
          format: uri
      required:
        - url
    PdfExportOutput:
      type: object
      additionalProperties: false
      properties:
        pageFormat:
          type: string
          enum:
            - A3
            - A4
            - A5
            - Letter
            - Legal
          default: A4
        landscape:
          type: boolean
          default: false
        printBackground:
          type: boolean
          default: true
    ImageExportOutput:
      type: object
      additionalProperties: false
      properties:
        type:
          type: string
          enum:
            - png
            - jpeg
            - webp
        width:
          type: integer
          minimum: 1
          maximum: 4096
          default: 1440
          description: Width of the browser viewport in CSS pixels. This controls responsive layout, not the exported image width. Use imageWidth to set the output image width.
        height:
          type: integer
          minimum: 1
          maximum: 4096
          description: Height of the browser viewport in CSS pixels. If omitted while width is provided, it is calculated using a 16:9 aspect ratio.
        fullPage:
          type: boolean
          default: false
          description: When true, capture the full scrollable page instead of only the viewport.
        imageWidth:
          type: integer
          minimum: 1
          maximum: 8192
          description: Target output image width in pixels. When deviceScaleFactor is omitted, the image is scaled to this width without changing the viewport.
        quality:
          type: integer
          minimum: 0
          maximum: 100
          description: Image compression quality. This has no effect on PNG output.
        omitBackground:
          type: boolean
          description: When true, capture a transparent background where the selected image format supports it.
        deviceScaleFactor:
          type: number
          minimum: 0
          exclusiveMinimum: true
          description: Device pixel ratio used to render the image. Overrides imageWidth when both are supplied.
        scrollPage:
          type: boolean
          description: When true, scroll through the page before capture to trigger lazy-loaded content.
        selector:
          type: string
          minLength: 1
          description: CSS selector for the specific element to capture.
      required:
        - type
    CreatePdfExportRequest:
      type: object
      additionalProperties: false
      properties:
        source:
          $ref: '#/components/schemas/ExportSource'
        output:
          $ref: '#/components/schemas/PdfExportOutput'
        isPrivate:
          type: boolean
          default: false
          description: When true, store the output privately and return a short-lived URL. Public output URLs do not expire.
      required:
        - source
        - output
    CreateImageExportRequest:
      type: object
      additionalProperties: false
      properties:
        source:
          $ref: '#/components/schemas/ExportSource'
        output:
          $ref: '#/components/schemas/ImageExportOutput'
        isPrivate:
          type: boolean
          default: false
          description: When true, store the output privately and return a short-lived URL. Public output URLs do not expire.
      required:
        - source
        - output
    ExportOutputFile:
      type: object
      properties:
        url:
          type: string
          nullable: true
        expiresAt:
          type: string
          format: date-time
          nullable: true
          description: Expiration time for a private output URL. Null for public outputs and outputs that are not ready.
        mimeType:
          type: string
          nullable: true
        size:
          type: integer
          nullable: true
          format: int64
      required:
        - url
        - expiresAt
        - mimeType
        - size
    Export:
      type: object
      properties:
        id:
          type: string
        format:
          type: string
          enum:
            - pdf
            - image
        status:
          $ref: '#/components/schemas/ExportStatus'
        isPrivate:
          type: boolean
          description: Whether the output is stored privately.
        source:
          $ref: '#/components/schemas/ExportSource'
        output:
          oneOf:
            - $ref: '#/components/schemas/PdfExportOutput'
            - $ref: '#/components/schemas/ImageExportOutput'
        outputFile:
          $ref: '#/components/schemas/ExportOutputFile'
        error:
          type: string
          nullable: true
        completedAt:
          type: string
          format: date-time
          nullable: true
        createdAt:
          type: string
          format: date-time
      required:
        - id
        - format
        - status
        - isPrivate
        - source
        - output
        - outputFile
        - error
        - completedAt
        - createdAt
    ExportResponse:
      type: object
      properties:
        export:
          $ref: '#/components/schemas/Export'
      required:
        - export
    ListExportsResult:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/Export'
        total:
          type: integer
        page:
          type: integer
        pageSize:
          type: integer
      required:
        - items
        - total
        - page
        - pageSize
    CreateProjectRequest:
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          minLength: 1
          description: Project name.
        description:
          type: string
          nullable: true
          description: Short project description.
        type:
          $ref: '#/components/schemas/ProjectType'
          description: Project type.
        isTemplate:
          type: boolean
          description: Whether the project should be treated as a template.
        projectData:
          $ref: '#/components/schemas/ProjectData'
          description: Editor project JSON to store with the project.
      required:
        - type
    UpdateProjectRequest:
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          minLength: 1
          description: Project name.
        description:
          type: string
          nullable: true
          description: Short project description.
        isTemplate:
          type: boolean
          description: Whether the project should be treated as a template.
        projectData:
          $ref: '#/components/schemas/ProjectData'
          description: Editor project JSON that replaces the currently stored project data.
    ProjectSummary:
      type: object
      properties:
        id:
          type: string
          description: Project ID.
        name:
          type: string
          description: Project name.
        description:
          type: string
          nullable: true
          description: Short project description.
        type:
          allOf:
            - $ref: '#/components/schemas/ProjectType'
          nullable: true
          description: Project type.
        isTemplate:
          type: boolean
          description: Whether the project is marked as a template.
        createdAt:
          type: string
          format: date-time
          description: Project creation date and time.
        updatedAt:
          type: string
          format: date-time
          description: Last project update date and time.
        previewUrl:
          type: string
          nullable: true
          description: URL of the project preview image.
        publishedUrl:
          type: string
          nullable: true
          description: Published project URL. `null` means the project is not published.
        lastPublishedAt:
          type: string
          format: date-time
          nullable: true
          description: Last publish date and time.
      required:
        - id
        - name
        - description
        - type
        - isTemplate
        - createdAt
        - updatedAt
        - lastPublishedAt
    ListProjectsResult:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/ProjectSummary'
          description: Projects in the current page.
        total:
          type: integer
          description: Total number of matching projects.
        page:
          type: integer
          description: Current page index.
        pageSize:
          type: integer
          description: Number of items per page.
      required:
        - items
        - total
        - page
        - pageSize
    TemplateSummary:
      type: object
      properties:
        id:
          type: string
          description: Template ID.
        source:
          $ref: '#/components/schemas/TemplateSource'
          description: Template source.
        name:
          type: string
          description: Template name.
        description:
          type: string
          nullable: true
          description: Short template description.
        type:
          allOf:
            - $ref: '#/components/schemas/ProjectType'
          nullable: true
          description: Template type.
        createdAt:
          type: string
          format: date-time
          description: Template creation date and time.
        updatedAt:
          type: string
          format: date-time
          description: Last template update date and time.
        previewUrl:
          type: string
          nullable: true
          description: URL of the template preview image.
        publishedUrl:
          type: string
          nullable: true
          description: Published template URL. `null` means the template is not published.
        lastPublishedAt:
          type: string
          format: date-time
          nullable: true
          description: Last publish date and time.
      required:
        - id
        - source
        - name
        - description
        - type
        - createdAt
        - updatedAt
        - lastPublishedAt
    ListTemplatesResult:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/TemplateSummary'
          description: Templates in the current page.
        total:
          type: integer
          description: Total number of matching templates.
        page:
          type: integer
          description: Current page index.
        pageSize:
          type: integer
          description: Number of items per page.
      required:
        - items
        - total
        - page
        - pageSize
    ProjectResponse:
      type: object
      properties:
        project:
          $ref: '#/components/schemas/ProjectSummary'
          description: Project metadata.
        projectData:
          $ref: '#/components/schemas/ProjectData'
          description: Editor project JSON, included when requested.
      required:
        - project
    ProjectFilesResponse:
      type: object
      properties:
        files:
          type: array
          items:
            $ref: '#/components/schemas/StoredProjectFile'
          description: Stored text-based files generated by the editor.
      required:
        - files
    TemplateResponse:
      type: object
      properties:
        template:
          $ref: '#/components/schemas/TemplateSummary'
          description: Template metadata.
        projectData:
          $ref: '#/components/schemas/ProjectData'
          description: Editor project JSON, included when requested.
      required:
        - template
    DeleteProjectResult:
      type: object
      properties:
        success:
          type: boolean
      required:
        - success
