{
  "openapi": "3.0.3",
  "info": {
    "title": "ZennoLab PublicApi",
    "version": "1.2.0",
    "description": "Versioned, transport-neutral control plane for ProjectMaker and ZennoPoster."
  },
  "servers": [
    {
      "url": "http://localhost:{port}",
      "variables": {
        "port": {
          "default": "5299",
          "description": "5299 = ProjectMaker, 5300 = ZennoPoster Core"
        }
      }
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "paths": {
    "/api/v1/ping": {
      "get": {
        "operationId": "ping",
        "summary": "Liveness check of the integration",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "security": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/product/version": {
      "get": {
        "operationId": "product_version",
        "summary": "Product name and version",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "productVariant": {
                      "type": "string",
                      "description": "Product edition name, e.g. \u0022ZennoPoster Pro\u0022 or \u0022ZennoDroid Enterprise\u0022 \u2014 lets the client adapt to browser vs Android capabilities."
                    },
                    "productVersion": {
                      "type": "string",
                      "description": "Full product version string (e.g. \u00227.7.7.0\u0022)."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current": {
      "get": {
        "operationId": "project_get_current",
        "summary": "Info about the open project",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "zennoPosterVersion": {
                      "type": "string",
                      "description": "Version of the ZennoPoster/ProjectMaker product currently running."
                    },
                    "projectName": {
                      "type": "string",
                      "description": "Name of the currently open project (active tab)."
                    },
                    "projectPath": {
                      "type": "string",
                      "description": "Full path of the project\u0027s .zp file on disk; null when the project has not been saved yet."
                    },
                    "projectId": {
                      "type": "string",
                      "description": "Stable unique id stored inside the project."
                    },
                    "projectMinVersion": {
                      "type": "string",
                      "description": "The project\u0027s UpdateVersion \u2014 the product version that last wrote the .zp; treat it as the minimum product version expected to open the project."
                    },
                    "lastModified": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Last modification time (UTC) of the project; default (zero) when unknown."
                    },
                    "isZDroid": {
                      "type": "boolean",
                      "description": "True when the host product is ZennoDroid (Android automation) rather than ZennoPoster."
                    },
                    "isRealPhone": {
                      "type": "boolean",
                      "description": "True on ZennoDroid Enterprise, which drives real phones instead of emulators. Always false outside ZennoDroid."
                    },
                    "hasUnsavedChanges": {
                      "type": "boolean",
                      "description": "True when the in-memory project has edits that have NOT yet been written to its .zp file \u2014 i.e. the file on disk is stale relative to what is open in ProjectMaker. Call SaveProject before running the project in ZennoPoster. For a brand-new project with no file yet, this is false only if there is also no edit history (nothing to save)."
                    },
                    "fileHash": {
                      "type": "string",
                      "description": "Freshness token: lowercase hex SHA-256 of the .zp file bytes currently on disk. This describes the SAVED file, not the in-memory edits \u2014 when HasUnsavedChanges is true this hash still reflects the previous save. Matches the FileHash returned by SaveProject/OpenProject for the same unchanged file. Null if the project has no file yet or the file could not be read."
                    },
                    "fileSizeBytes": {
                      "type": "integer",
                      "description": "Size in bytes of the .zp file on disk. Null if no file / unreadable."
                    },
                    "lastWriteTimeUtc": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Last write time (UTC) of the .zp file on disk. Null if no file / unreadable."
                    }
                  },
                  "required": [
                    "lastModified",
                    "isZDroid",
                    "isRealPhone",
                    "hasUnsavedChanges"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects": {
      "post": {
        "operationId": "project_create",
        "summary": "Create a new project",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projectName": {
                      "type": "string",
                      "description": "Name of the newly created project."
                    },
                    "projectPath": {
                      "type": "string",
                      "description": "Full path on disk, or null for a freshly created project that has not been saved yet (use SaveProject with a path to persist it)."
                    },
                    "projectId": {
                      "type": "string",
                      "description": "Unique id assigned to the project."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/open": {
      "post": {
        "operationId": "project_open",
        "summary": "Open a project by path",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "path": {
                    "type": "string",
                    "description": "Full path to the project file to open (e.g. *.zp / *.xmlz)."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projectName": {
                      "type": "string",
                      "description": "Name of the opened project."
                    },
                    "projectPath": {
                      "type": "string",
                      "description": "Full path of the opened .zp file."
                    },
                    "projectId": {
                      "type": "string",
                      "description": "Stable unique id stored inside the project."
                    },
                    "fileHash": {
                      "type": "string",
                      "description": "Freshness token: lowercase hex SHA-256 of the opened .zp file bytes on disk. Matches the FileHash returned by SaveProject for the same unchanged file. Null if the file could not be read back after opening."
                    },
                    "fileSizeBytes": {
                      "type": "integer",
                      "description": "Size in bytes of the opened .zp file. Null if the file could not be read back."
                    },
                    "lastWriteTimeUtc": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Last write time (UTC) of the opened .zp file. Null if the file could not be read back."
                    },
                    "projectVersion": {
                      "type": "string",
                      "description": "Version stamped into the opened .zp (the project\u0027s UpdateVersion). Part of the freshness token alongside the hash; matches the value SaveProject returned for the same file."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/save": {
      "post": {
        "operationId": "project_save",
        "summary": "Save the open project",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "path": {
                    "type": "string",
                    "description": "Optional target file path (\u0022save as\u0022). When null/empty the project is saved in place to its existing file. A path is REQUIRED the first time a freshly created project is saved (it has no file yet)."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projectName": {
                      "type": "string",
                      "description": "Name of the saved project."
                    },
                    "projectPath": {
                      "type": "string",
                      "description": "Full path the project was saved to."
                    },
                    "fileHash": {
                      "type": "string",
                      "description": "Freshness token: lowercase hex SHA-256 of the saved .zp file bytes on disk, computed by reading the file back AFTER the save completed. Null if the file could not be read back (the save itself still succeeded). OpenProject returns the identical hash for the same unchanged file."
                    },
                    "fileSizeBytes": {
                      "type": "integer",
                      "description": "Size in bytes of the saved .zp file. Null if the file could not be read back."
                    },
                    "lastWriteTimeUtc": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Last write time (UTC) of the saved .zp file. Null if the file could not be read back."
                    },
                    "projectVersion": {
                      "type": "string",
                      "description": "Version stamped into the saved .zp (the project\u0027s UpdateVersion \u2014 the product version that wrote the file). Part of the freshness token alongside the hash; stored inside the file, so OpenProject on the same file returns the same value."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "failed_precondition: The project is not in a state that allows this operation (RESULT_FAILED_PRECONDITION)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/close": {
      "post": {
        "operationId": "project_close",
        "summary": "Close the open project",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "discardUnsavedChanges": {
                    "type": "boolean",
                    "description": "Close the project even when it has unsaved changes, discarding them. When false (the default) a changed project is not closed: the call fails with 409 failed_precondition so no work is lost silently \u2014 save first (project_save) or opt into discarding explicitly."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                },
                "required": [
                  "discardUnsavedChanges"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projectName": {
                      "type": "string",
                      "description": "Name of the project that was closed."
                    },
                    "projectPath": {
                      "type": "string",
                      "description": "Path of the closed project\u0027s file; null for a never-saved project."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "failed_precondition: The project is not in a state that allows this operation (RESULT_FAILED_PRECONDITION)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/start": {
      "post": {
        "operationId": "project_start",
        "summary": "Run the open project \u2014 executes project code incl. OwnCode (RCE class)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 3,
        "x-implemented": true,
        "x-required-scope": "project:run",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "started": {
                      "type": "boolean",
                      "description": "True when the project run was triggered. Execution happens asynchronously \u2014 poll GetExecutionLogs / GetLastError / GetProjectStructure (action ExecutionState) to observe progress and completion."
                    }
                  },
                  "required": [
                    "started"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/stop": {
      "post": {
        "operationId": "project_stop",
        "summary": "Stop the running project",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 2,
        "x-implemented": true,
        "x-required-scope": "project:run",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/actions/catalog": {
      "get": {
        "operationId": "actions_catalog_list",
        "summary": "Catalog of action types",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "categories": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "tag": {
                            "type": "string",
                            "description": "Category tag (e.g. \u0022WebBrowser\u0022) \u2014 the action type half of the (type, action) address; also the FindActions type filter."
                          },
                          "title": {
                            "type": "string",
                            "description": "Human-readable category title."
                          },
                          "summary": {
                            "type": "string",
                            "description": "Optional short description of what the category covers; null when none is defined."
                          },
                          "actions": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "description": {
                                  "type": "string",
                                  "description": "Human-readable description of the action type, shared by all its variants."
                                },
                                "variants": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "action": {
                                        "type": "string",
                                        "description": "Action tag \u2014 pass as action to AddAction/UpdateAction/GetActionSchema together with the owning category\u0027s tag as type (e.g. CMD_OPENTAB, ToUpper)."
                                      },
                                      "description": {
                                        "type": "string",
                                        "description": "Human-readable description of the variant."
                                      },
                                      "parameters": {
                                        "type": "array",
                                        "items": {
                                          "type": "object",
                                          "properties": {
                                            "name": {
                                              "type": "string",
                                              "description": "Parameter name \u2014 the key to use in the parameters map of AddAction/UpdateAction."
                                            },
                                            "kind": {
                                              "type": "string",
                                              "description": "Value kind (ParameterKind name): String | Int | Bool | Double | Url | FilePath | Xpath | CssSelector | Regex | Enum | VariableName | ListName | TableName | GoogleSpreadsheetName | Json | OpenSchema."
                                            },
                                            "description": {
                                              "type": "string",
                                              "description": "Human-readable description of the parameter; null when none is defined."
                                            },
                                            "required": {
                                              "type": "boolean",
                                              "description": "True when the parameter must always be supplied."
                                            },
                                            "requiredWhen": {
                                              "type": "object",
                                              "properties": {
                                                "parameterName": {
                                                  "type": "string",
                                                  "description": "Name of the controlling parameter the condition inspects."
                                                },
                                                "valuesThatRequire": {
                                                  "type": "array",
                                                  "items": {
                                                    "type": "string"
                                                  },
                                                  "description": "Values of the controlling parameter that make the dependent parameter required."
                                                }
                                              },
                                              "description": "Conditional requirement: the parameter becomes required when another parameter takes one of the listed values; null when the requirement is unconditional (see Required)."
                                            },
                                            "possibleValues": {
                                              "type": "array",
                                              "items": {
                                                "type": "string"
                                              },
                                              "description": "Closed list of allowed values for enum-like parameters; null when the value is free-form."
                                            },
                                            "example": {
                                              "type": "string",
                                              "description": "Sample value illustrating the expected format; null when none is defined."
                                            },
                                            "format": {
                                              "type": "string",
                                              "description": "Free-form format hint (e.g. an expected pattern) when the kind alone is not specific enough; null otherwise."
                                            },
                                            "defaultValue": {
                                              "type": "string",
                                              "description": "Value the engine uses when the parameter is omitted; null when there is no default."
                                            },
                                            "minValue": {
                                              "type": "number",
                                              "description": "Lower bound for numeric kinds; null when unbounded."
                                            },
                                            "maxValue": {
                                              "type": "number",
                                              "description": "Upper bound for numeric kinds; null when unbounded."
                                            }
                                          },
                                          "required": [
                                            "required"
                                          ]
                                        },
                                        "description": "Parameter definitions of the variant: kind, required-ness, allowed values, defaults."
                                      },
                                      "results": {
                                        "type": "array",
                                        "items": {
                                          "type": "object",
                                          "properties": {
                                            "name": {
                                              "type": "string",
                                              "description": "Result name \u2014 the key to use in the results map when binding it to a project variable."
                                            },
                                            "description": {
                                              "type": "string",
                                              "description": "Human-readable description of the result; null when none is defined."
                                            }
                                          }
                                        },
                                        "description": "Result variables the variant can emit (e.g. OutputVariable)."
                                      },
                                      "schemaVersion": {
                                        "type": "integer",
                                        "description": "Version of the variant\u0027s schema definition; bumps when the parameter surface changes."
                                      },
                                      "acceptedBindings": {
                                        "type": "array",
                                        "items": {
                                          "type": "string"
                                        },
                                        "description": "Names of the binding kinds this variant accepts (match by Name against the category\u0027s Bindings); null when the variant takes no element finder."
                                      }
                                    },
                                    "required": [
                                      "schemaVersion"
                                    ]
                                  },
                                  "description": "Variants of the action type. Each is addressed by the owning category\u0027s tag (type) plus its own action tag; flat types have exactly one."
                                }
                              }
                            },
                            "description": "Visible action types of the category."
                          },
                          "bindings": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "name": {
                                  "type": "string",
                                  "description": "Binding name \u2014 the label referenced by a variant\u0027s AcceptedBindings."
                                },
                                "discriminatorValue": {
                                  "type": "string",
                                  "description": "Value to pass in the category\u0027s binding-discriminator parameter (and as the bindings.discriminator of AddAction/UpdateAction) to select this binding, e.g. \u0022XPathFinder\u0022."
                                },
                                "description": {
                                  "type": "string",
                                  "description": "Human-readable description of the binding; null when none is defined."
                                },
                                "fields": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "name": {
                                        "type": "string",
                                        "description": "Field name \u2014 the key to use in the bindings.scalars map (or in an array element row)."
                                      },
                                      "kind": {
                                        "type": "string",
                                        "description": "Value kind (ParameterKind name): String | Int | Bool | Double | Url | FilePath | Xpath | CssSelector | Regex | Enum | VariableName | ListName | TableName | GoogleSpreadsheetName | Json | OpenSchema."
                                      },
                                      "description": {
                                        "type": "string",
                                        "description": "Human-readable description of the field; null when none is defined."
                                      },
                                      "required": {
                                        "type": "boolean",
                                        "description": "True when the field must be supplied."
                                      },
                                      "possibleValues": {
                                        "type": "array",
                                        "items": {
                                          "type": "string"
                                        },
                                        "description": "Closed list of allowed values for enum-like fields; null when the value is free-form."
                                      },
                                      "example": {
                                        "type": "string",
                                        "description": "Sample value illustrating the expected format; null when none is defined."
                                      }
                                    },
                                    "required": [
                                      "required"
                                    ]
                                  },
                                  "description": "Scalar fields of the binding (keys for the bindings.scalars map)."
                                },
                                "nestedArrays": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "name": {
                                        "type": "string",
                                        "description": "Array name \u2014 the key to use in the bindings.nestedArrays map (e.g. \u0022SearchCondition\u0022)."
                                      },
                                      "description": {
                                        "type": "string",
                                        "description": "Human-readable description of the array; null when none is defined."
                                      },
                                      "minOneRequired": {
                                        "type": "boolean",
                                        "description": "True when at least one element row must be supplied."
                                      },
                                      "elementFields": {
                                        "type": "array",
                                        "items": {
                                          "type": "object",
                                          "properties": {
                                            "name": {
                                              "type": "string",
                                              "description": "Field name \u2014 the key to use in the bindings.scalars map (or in an array element row)."
                                            },
                                            "kind": {
                                              "type": "string",
                                              "description": "Value kind (ParameterKind name): String | Int | Bool | Double | Url | FilePath | Xpath | CssSelector | Regex | Enum | VariableName | ListName | TableName | GoogleSpreadsheetName | Json | OpenSchema."
                                            },
                                            "description": {
                                              "type": "string",
                                              "description": "Human-readable description of the field; null when none is defined."
                                            },
                                            "required": {
                                              "type": "boolean",
                                              "description": "True when the field must be supplied."
                                            },
                                            "possibleValues": {
                                              "type": "array",
                                              "items": {
                                                "type": "string"
                                              },
                                              "description": "Closed list of allowed values for enum-like fields; null when the value is free-form."
                                            },
                                            "example": {
                                              "type": "string",
                                              "description": "Sample value illustrating the expected format; null when none is defined."
                                            }
                                          },
                                          "required": [
                                            "required"
                                          ]
                                        },
                                        "description": "Field definitions of each array element row."
                                      }
                                    },
                                    "required": [
                                      "minOneRequired"
                                    ]
                                  },
                                  "description": "Repeated sub-groups of the binding (e.g. DomFinder\u0027s SearchCondition rows)."
                                }
                              }
                            },
                            "description": "Element-finder binding definitions available to actions of this category; null when it has none."
                          },
                          "bindingDiscriminator": {
                            "type": "string",
                            "description": "Name of the parameter that selects the active binding (typically \u0022FinderType\u0022); null when the category has no bindings."
                          }
                        }
                      },
                      "description": "All visible catalog categories with their action types and variants; hidden actions are excluded."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/actions/catalog/search": {
      "get": {
        "operationId": "actions_catalog_search",
        "summary": "Search actions (query/category/maxResults)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": false,
            "description": "Free-text search over action names, descriptions and tags.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Restrict the search to one action type (catalog category tag, e.g. WebBrowser).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "maxResults",
            "in": "query",
            "required": false,
            "description": "Maximum number of hits. Default 10.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "totalMatches": {
                      "type": "integer",
                      "description": "Total variants that matched, before the maxResults cut."
                    },
                    "truncated": {
                      "type": "boolean",
                      "description": "True when more variants matched than were returned \u2014 narrow the query/category."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "description": "Action type of the matched variant (category tag, e.g. \u0022WebBrowser\u0022) \u2014 pass to AddAction / GetActionSchema."
                          },
                          "action": {
                            "type": "string",
                            "description": "Action tag of the matched variant \u2014 pass as action alongside the type."
                          },
                          "description": {
                            "type": "string",
                            "description": "Human-readable description of the matched variant."
                          },
                          "actionTypeDescription": {
                            "type": "string",
                            "description": "Description of the owning action type. Emitted only on the first hit of each action type \u2014 variants of the same action type share it, repeating it would bloat the payload."
                          },
                          "parameters": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Up to 5 parameter names, present only when the search had a free-text query (enough to confirm the right variant matched on a parameter-name term). Fetch the full parameter list via actions_catalog_schema."
                          },
                          "parameterCount": {
                            "type": "integer",
                            "description": "Total number of parameters the variant declares (the Parameters preview may show fewer)."
                          }
                        },
                        "required": [
                          "parameterCount"
                        ]
                      },
                      "description": "Matched action variants, best matches first, capped by maxResults."
                    }
                  },
                  "required": [
                    "totalMatches",
                    "truncated"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/actions/catalog/{type}/{action}/schema": {
      "get": {
        "operationId": "actions_catalog_schema",
        "summary": "Parameter/result schema of a variant",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "action",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "description": "Echo of the requested action type (catalog category tag, e.g. \u0022WebBrowser\u0022, \u0022Logic\u0022)."
                    },
                    "action": {
                      "type": "string",
                      "description": "Echo of the requested action tag."
                    },
                    "description": {
                      "type": "string",
                      "description": "Human-readable description of this variant."
                    },
                    "actionTypeDescription": {
                      "type": "string",
                      "description": "Description of the owning action type (shared by all its variants)."
                    },
                    "schemaVersion": {
                      "type": "integer",
                      "description": "Version of the variant\u0027s schema definition; bumps when the parameter surface changes."
                    },
                    "parameters": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Parameter name \u2014 the key to use in the parameters map of AddAction/UpdateAction."
                          },
                          "kind": {
                            "type": "string",
                            "description": "Value kind (ParameterKind name): String | Int | Bool | Double | Url | FilePath | Xpath | CssSelector | Regex | Enum | VariableName | ListName | TableName | GoogleSpreadsheetName | Json | OpenSchema."
                          },
                          "description": {
                            "type": "string",
                            "description": "Human-readable description of the parameter; null when none is defined."
                          },
                          "required": {
                            "type": "boolean",
                            "description": "True when the parameter must always be supplied."
                          },
                          "requiredWhen": {
                            "type": "object",
                            "properties": {
                              "parameterName": {
                                "type": "string",
                                "description": "Name of the controlling parameter the condition inspects."
                              },
                              "valuesThatRequire": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "Values of the controlling parameter that make the dependent parameter required."
                              }
                            },
                            "description": "Conditional requirement: the parameter becomes required when another parameter takes one of the listed values; null when the requirement is unconditional (see Required)."
                          },
                          "possibleValues": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Closed list of allowed values for enum-like parameters; null when the value is free-form."
                          },
                          "example": {
                            "type": "string",
                            "description": "Sample value illustrating the expected format; null when none is defined."
                          },
                          "format": {
                            "type": "string",
                            "description": "Free-form format hint (e.g. an expected pattern) when the kind alone is not specific enough; null otherwise."
                          },
                          "defaultValue": {
                            "type": "string",
                            "description": "Value the engine uses when the parameter is omitted; null when there is no default."
                          },
                          "minValue": {
                            "type": "number",
                            "description": "Lower bound for numeric kinds; null when unbounded."
                          },
                          "maxValue": {
                            "type": "number",
                            "description": "Upper bound for numeric kinds; null when unbounded."
                          }
                        },
                        "required": [
                          "required"
                        ]
                      },
                      "description": "Parameter definitions of the variant: kind, required-ness (including conditional RequiredWhen rules), allowed values, defaults."
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Result name \u2014 the key to use in the results map when binding it to a project variable."
                          },
                          "description": {
                            "type": "string",
                            "description": "Human-readable description of the result; null when none is defined."
                          }
                        }
                      },
                      "description": "Result variables the variant can emit (e.g. OutputVariable)."
                    },
                    "bindingDiscriminator": {
                      "type": "string",
                      "description": "Name of the discriminator field inside finder JSON (e.g. FinderType), when the category uses bindings."
                    },
                    "acceptedBindings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Names of the binding kinds this variant accepts; null when it takes no finder."
                    },
                    "bindings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Binding name \u2014 the label referenced by a variant\u0027s AcceptedBindings."
                          },
                          "discriminatorValue": {
                            "type": "string",
                            "description": "Value to pass in the category\u0027s binding-discriminator parameter (and as the bindings.discriminator of AddAction/UpdateAction) to select this binding, e.g. \u0022XPathFinder\u0022."
                          },
                          "description": {
                            "type": "string",
                            "description": "Human-readable description of the binding; null when none is defined."
                          },
                          "fields": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "name": {
                                  "type": "string",
                                  "description": "Field name \u2014 the key to use in the bindings.scalars map (or in an array element row)."
                                },
                                "kind": {
                                  "type": "string",
                                  "description": "Value kind (ParameterKind name): String | Int | Bool | Double | Url | FilePath | Xpath | CssSelector | Regex | Enum | VariableName | ListName | TableName | GoogleSpreadsheetName | Json | OpenSchema."
                                },
                                "description": {
                                  "type": "string",
                                  "description": "Human-readable description of the field; null when none is defined."
                                },
                                "required": {
                                  "type": "boolean",
                                  "description": "True when the field must be supplied."
                                },
                                "possibleValues": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  },
                                  "description": "Closed list of allowed values for enum-like fields; null when the value is free-form."
                                },
                                "example": {
                                  "type": "string",
                                  "description": "Sample value illustrating the expected format; null when none is defined."
                                }
                              },
                              "required": [
                                "required"
                              ]
                            },
                            "description": "Scalar fields of the binding (keys for the bindings.scalars map)."
                          },
                          "nestedArrays": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "name": {
                                  "type": "string",
                                  "description": "Array name \u2014 the key to use in the bindings.nestedArrays map (e.g. \u0022SearchCondition\u0022)."
                                },
                                "description": {
                                  "type": "string",
                                  "description": "Human-readable description of the array; null when none is defined."
                                },
                                "minOneRequired": {
                                  "type": "boolean",
                                  "description": "True when at least one element row must be supplied."
                                },
                                "elementFields": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "name": {
                                        "type": "string",
                                        "description": "Field name \u2014 the key to use in the bindings.scalars map (or in an array element row)."
                                      },
                                      "kind": {
                                        "type": "string",
                                        "description": "Value kind (ParameterKind name): String | Int | Bool | Double | Url | FilePath | Xpath | CssSelector | Regex | Enum | VariableName | ListName | TableName | GoogleSpreadsheetName | Json | OpenSchema."
                                      },
                                      "description": {
                                        "type": "string",
                                        "description": "Human-readable description of the field; null when none is defined."
                                      },
                                      "required": {
                                        "type": "boolean",
                                        "description": "True when the field must be supplied."
                                      },
                                      "possibleValues": {
                                        "type": "array",
                                        "items": {
                                          "type": "string"
                                        },
                                        "description": "Closed list of allowed values for enum-like fields; null when the value is free-form."
                                      },
                                      "example": {
                                        "type": "string",
                                        "description": "Sample value illustrating the expected format; null when none is defined."
                                      }
                                    },
                                    "required": [
                                      "required"
                                    ]
                                  },
                                  "description": "Field definitions of each array element row."
                                }
                              },
                              "required": [
                                "minOneRequired"
                              ]
                            },
                            "description": "Repeated sub-groups of the binding (e.g. DomFinder\u0027s SearchCondition rows)."
                          }
                        }
                      },
                      "description": "Resolved definitions of the accepted bindings (field shapes); null when it takes no finder."
                    }
                  },
                  "required": [
                    "schemaVersion"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/structure": {
      "get": {
        "operationId": "project_structure_get",
        "summary": "List actions (without parameters)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "parameters": [
          {
            "name": "groupId",
            "in": "query",
            "required": false,
            "description": "Scope the returned nodes/edges to this single group (case-insensitive id). Omitted = the whole graph.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "actions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "actionId": {
                            "type": "string",
                            "description": "Unique id of the action (cube) within the project."
                          },
                          "groupId": {
                            "type": "string",
                            "description": "Id of the group the action belongs to."
                          },
                          "type": {
                            "type": "string",
                            "description": "Action type = its Category tag (e.g. \u0022WebBrowser\u0022, \u0022Logic\u0022, \u0022List\u0022, \u0022OwnCode\u0022)."
                          },
                          "action": {
                            "type": "string",
                            "description": "The action verb (project-XML Action attribute / 3rd creation-tag segment), e.g. \u0022CMD_NAVIGATE\u0022, \u0022Switch\u0022. Carried the name OptionTag on the graph side before the two spellings of the same field were merged into this one."
                          },
                          "label": {
                            "type": "string",
                            "description": "Display label \u2014 the cube\u0027s Comment, falling back to UserText; empty when neither is set."
                          },
                          "groupLabel": {
                            "type": "string",
                            "description": "Label (UserText) of the owning group; empty when unnamed."
                          },
                          "x": {
                            "type": "integer",
                            "description": "On-schema X of the owning group box (cubes have no own pixel coords in the model)."
                          },
                          "y": {
                            "type": "integer",
                            "description": "On-schema Y of the owning group box."
                          },
                          "indexInGroup": {
                            "type": "integer",
                            "description": "0-based position of the cube inside its group, i.e. the implicit execution order."
                          },
                          "isSwitch": {
                            "type": "boolean",
                            "description": "True for Logic/Switch cubes, which branch via Default/Case-N instead of OnSuccess."
                          },
                          "disabled": {
                            "type": "boolean",
                            "description": "True when the cube is disabled (skipped at run time)."
                          },
                          "breakpoint": {
                            "type": "boolean",
                            "description": "True when the debugger pauses before this cube."
                          },
                          "optional": {
                            "type": "boolean",
                            "description": "True when an error in this cube does not fail the project."
                          },
                          "isStart": {
                            "type": "boolean",
                            "description": "True when this cube is the project entry point (the Start block points at it)."
                          },
                          "onErrorPath": {
                            "type": "boolean",
                            "description": "True when the cube belongs to an error/cleanup branch \u2014 i.e. it is reachable from an OnError edge target by following normal (OnSuccess/Default/Case) edges. Best-effort marker."
                          }
                        },
                        "required": [
                          "x",
                          "y",
                          "indexInGroup",
                          "isSwitch",
                          "disabled",
                          "breakpoint",
                          "optional",
                          "isStart",
                          "onErrorPath"
                        ]
                      },
                      "description": "Graph nodes \u2014 one per placed cube (see ActionInfo)."
                    },
                    "links": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "actionId": {
                            "type": "string",
                            "description": "Id of the source action the branch originates from."
                          },
                          "groupId": {
                            "type": "string",
                            "description": "Id of the group containing the source action."
                          },
                          "branch": {
                            "type": "string",
                            "description": "\u0022OnSuccess\u0022 or \u0022OnError\u0022."
                          },
                          "targetActionId": {
                            "type": "string",
                            "description": "The action this branch jumps to. null or empty on writes means \u0022remove the explicit link and revert to the implicit next-in-group\u0022. On reads, null means there is no implicit successor either (last action of the group)."
                          },
                          "isImplicit": {
                            "type": "boolean",
                            "description": "Read-only. true when the link is computed from action ordering rather than stored explicitly. Always false in input to SetActionLinks (writing an \u0022implicit\u0022 link means clearing the explicit one \u2014 pass null TargetActionId)."
                          }
                        },
                        "required": [
                          "isImplicit"
                        ]
                      },
                      "description": "Graph edges \u2014 every outgoing branch of every cube. Each ActionLink is a source (ActionId/GroupId) \u2192 target (TargetActionId, a bare action id) hop on a branch (OnSuccess/OnError/Default/Case:N); IsImplicit marks the next-in-group OnSuccess fallback."
                    },
                    "startActionId": {
                      "type": "string",
                      "description": "Entry cube the Start block points at, or null when unwired/empty project."
                    },
                    "startGroupId": {
                      "type": "string",
                      "description": "Group of the entry cube, or null when unwired/empty project."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/diagram": {
      "get": {
        "operationId": "diagram_image_get",
        "summary": "PNG of the schema (mode=Full|Visible, maxWidth/maxHeight/scale)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "parameters": [
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "description": "Which part of the schema to draw: Full (every cube, group and static block, scaled to fit; the default) or Visible (only what the schema window is showing right now, at its zoom).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "maxWidth",
            "in": "query",
            "required": false,
            "description": "Largest image width in pixels; 0 or omitted = no width-specific limit. Values above 4000 are clamped. Cannot be combined with scale.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "maxHeight",
            "in": "query",
            "required": false,
            "description": "Largest image height in pixels; 0 or omitted = no height-specific limit. Values above 4000 are clamped. Cannot be combined with scale.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "scale",
            "in": "query",
            "required": false,
            "description": "Pixels per schema unit as a decimal with \u0027.\u0027 as the separator (1 = the schema window at 100% zoom); 0 or omitted = chosen automatically. Cannot be combined with maxWidth/maxHeight (400).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "imageBase64": {
                      "type": "string",
                      "description": "The PNG itself, base64-encoded (no data-URI prefix)."
                    },
                    "mimeType": {
                      "type": "string",
                      "description": "Media type of the encoded image. Always \u0022image/png\u0022."
                    },
                    "width": {
                      "type": "integer",
                      "description": "Image width in pixels."
                    },
                    "height": {
                      "type": "integer",
                      "description": "Image height in pixels."
                    },
                    "scale": {
                      "type": "number",
                      "description": "Pixels per schema unit actually used. To turn a pixel offset in the image back into schema coordinates, divide it by this and add the contentBounds x/y."
                    },
                    "mode": {
                      "type": "string",
                      "enum": [
                        "Full",
                        "Visible"
                      ],
                      "description": "Which mode produced this image."
                    },
                    "contentBounds": {
                      "type": "object",
                      "properties": {
                        "x": {
                          "type": "number",
                          "description": "Left edge. Can be negative, since groups may sit left of the origin."
                        },
                        "y": {
                          "type": "number",
                          "description": "Top edge. Can be negative."
                        },
                        "width": {
                          "type": "number",
                          "description": "Width in schema units."
                        },
                        "height": {
                          "type": "number",
                          "description": "Height in schema units."
                        }
                      },
                      "required": [
                        "x",
                        "y",
                        "width",
                        "height"
                      ],
                      "description": "The region of the schema that ended up in the frame, in schema coordinates."
                    },
                    "viewportBounds": {
                      "type": "object",
                      "properties": {
                        "x": {
                          "type": "number",
                          "description": "Left edge. Can be negative, since groups may sit left of the origin."
                        },
                        "y": {
                          "type": "number",
                          "description": "Top edge. Can be negative."
                        },
                        "width": {
                          "type": "number",
                          "description": "Width in schema units."
                        },
                        "height": {
                          "type": "number",
                          "description": "Height in schema units."
                        }
                      },
                      "required": [
                        "x",
                        "y",
                        "width",
                        "height"
                      ],
                      "description": "What the schema window is showing right now, in schema coordinates. In Visible mode this is the same region as contentBounds; in Full mode it says which slice of the whole picture the user is looking at. Null when there is no schema window to read it from."
                    },
                    "isTruncated": {
                      "type": "boolean",
                      "description": "True when the requested scale did not fit the 4000-pixel limit and part of the region was left out of the frame. Only an explicit scale can cause this; without one the image is scaled down to fit instead. contentBounds always describes what really made it into the frame."
                    },
                    "actionsInFrame": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "actionId": {
                            "type": "string",
                            "description": "Unique id of the cube within the project."
                          },
                          "groupId": {
                            "type": "string",
                            "description": "Id of the group the cube belongs to."
                          },
                          "type": {
                            "type": "string",
                            "description": "Cube type = its category tag (e.g. \u0022WebBrowser\u0022, \u0022Logic\u0022, \u0022OwnCode\u0022)."
                          },
                          "action": {
                            "type": "string",
                            "description": "The action verb, e.g. \u0022CMD_NAVIGATE\u0022, \u0022Switch\u0022."
                          },
                          "label": {
                            "type": "string",
                            "description": "The caption the cube shows on the schema: the name the user gave it, or the action\u0027s own display name when it has not been renamed."
                          },
                          "groupLabel": {
                            "type": "string",
                            "description": "Name of the owning group; empty when the group is unnamed."
                          }
                        }
                      },
                      "description": "The cubes inside the frame, in reading order (top row first, left to right within a row). This is what answers \u0022which cubes am I looking at\u0022: a cube carries no coordinates of its own, only its group\u0027s, so the graph alone cannot tell you which ones fell inside the frame."
                    },
                    "note": {
                      "type": "string",
                      "description": "Set only when the request was adjusted (scale clamped, region cropped); otherwise null."
                    }
                  },
                  "required": [
                    "width",
                    "height",
                    "scale",
                    "mode",
                    "isTruncated"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/actions/{groupId}/{actionId}": {
      "get": {
        "operationId": "action_get",
        "summary": "Action details (params/results/finder/links)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "parameters": [
          {
            "name": "groupId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "actionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "actionId": {
                      "type": "string",
                      "description": "Id of the inspected action."
                    },
                    "groupId": {
                      "type": "string",
                      "description": "Id of the group the action belongs to."
                    },
                    "name": {
                      "type": "string",
                      "description": "The action\u0027s display name, as shown on the schema and in the properties panel, and written by RenameAction. Empty when it was never named, in which case the editor draws an auto-caption derived from the action\u0027s type. This is the stored value, so it round-trips exactly what RenameAction wrote. The project graph reports the displayed name instead, which on a project converted from V3 falls back to the legacy comment field, so the graph can carry a label while this stays empty."
                    },
                    "type": {
                      "type": "string",
                      "description": "Action type (catalog category tag, e.g. \u0022WebBrowser\u0022) \u2014 ready to pass to UpdateAction."
                    },
                    "action": {
                      "type": "string",
                      "description": "Action tag within the type (e.g. \u0022CMD_STARTINSTANCE\u0022) \u2014 ready to pass to UpdateAction."
                    },
                    "parameters": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string"
                      },
                      "description": "Current parameter values, keyed by the schema parameter name. Only parameters declared in the catalog variant are included; absent values are returned as empty strings so the caller sees the full schema-defined surface."
                    },
                    "results": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string"
                      },
                      "description": "Current result-binding values (e.g. OutputVariable \u2192 variable macro)."
                    },
                    "finderType": {
                      "type": "string",
                      "description": "For actions that use a structured element finder (HtmlElement and similar): short name of the active finder \u2014 e.g. XPathFinder, DomFinder, IntelliSearch, ImageFinder, RawCoordinatesFinder. null for actions that do not use finders."
                    },
                    "finder": {
                      "type": "object",
                      "additionalProperties": {},
                      "description": "Generic field map of the active finder\u0027s sub-elements. Plain leaf elements become strings; repeated children with the same tag become arrays (e.g. DomFinder\u0027s SearchCondition list). null when the action has no finder."
                    },
                    "links": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "actionId": {
                            "type": "string",
                            "description": "Id of the source action the branch originates from."
                          },
                          "groupId": {
                            "type": "string",
                            "description": "Id of the group containing the source action."
                          },
                          "branch": {
                            "type": "string",
                            "description": "\u0022OnSuccess\u0022 or \u0022OnError\u0022."
                          },
                          "targetActionId": {
                            "type": "string",
                            "description": "The action this branch jumps to. null or empty on writes means \u0022remove the explicit link and revert to the implicit next-in-group\u0022. On reads, null means there is no implicit successor either (last action of the group)."
                          },
                          "isImplicit": {
                            "type": "boolean",
                            "description": "Read-only. true when the link is computed from action ordering rather than stored explicitly. Always false in input to SetActionLinks (writing an \u0022implicit\u0022 link means clearing the explicit one \u2014 pass null TargetActionId)."
                          }
                        },
                        "required": [
                          "isImplicit"
                        ]
                      },
                      "description": "Outgoing branches of the action: OnSuccess and OnError. Each entry\u0027s IsImplicit is true when the target is computed from the next-action-in-group rule rather than stored explicitly. null targetActionId means the action is the terminal step on that branch (no successor at all)."
                    },
                    "disabled": {
                      "type": "boolean",
                      "description": "True when the cube is skipped at run time."
                    },
                    "breakpoint": {
                      "type": "boolean",
                      "description": "True when the debugger pauses before this cube."
                    },
                    "optional": {
                      "type": "boolean",
                      "description": "True when an error in this cube does not fail the project."
                    },
                    "comment": {
                      "type": "string",
                      "description": "The cube\u0027s caption on the schema, empty when it has none. This is the user\u0027s own text, not the model\u0027s internal Comment attribute."
                    }
                  },
                  "required": [
                    "disabled",
                    "breakpoint",
                    "optional"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "action_update",
        "summary": "Update an action",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "parameters": [
          {
            "name": "groupId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "actionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "description": "Action type (catalog category tag) the action should carry \u2014 pass the value returned by GetActionDetails to keep the current type."
                  },
                  "action": {
                    "type": "string",
                    "description": "Action tag within the type \u2014 pass the value returned by GetActionDetails to keep the current action."
                  },
                  "parameters": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Parameter values keyed by the schema parameter name of the selected variant (see GetActionSchema). Validated against the catalog schema."
                  },
                  "results": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Result bindings keyed by the schema result name (e.g. OutputVariable). The value is the project variable name to store the result into; missing variables are created."
                  },
                  "bindings": {
                    "type": "object",
                    "properties": {
                      "discriminator": {
                        "type": "string",
                        "description": "Selects which binding the payload describes \u2014 the DiscriminatorValue of the target binding (e.g. \u0022XPathFinder\u0022, \u0022DomFinder\u0022). Must mirror the value of the category\u0027s binding-discriminator parameter (typically FinderType) passed in the action parameters."
                      },
                      "scalars": {
                        "type": "object",
                        "additionalProperties": {
                          "type": "string"
                        },
                        "description": "Scalar binding fields keyed by field name (see the binding\u0027s Fields in the catalog), e.g. XPath for XPathFinder."
                      },
                      "nestedArrays": {
                        "type": "object",
                        "additionalProperties": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        },
                        "description": "Repeated sub-groups keyed by array name; each entry is the list of element rows, a row being a field-name to value map (e.g. DomFinder\u0027s SearchCondition rows)."
                      }
                    },
                    "description": "Optional structured-binding payload \u2014 see Bindings."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "validationErrors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "parameterName": {
                            "type": "string",
                            "description": "Name of the parameter or field that failed validation."
                          },
                          "code": {
                            "type": "string",
                            "description": "Machine-readable validation failure code (e.g. \u0022REQUIRED\u0022, \u0022out_of_range\u0022)."
                          },
                          "message": {
                            "type": "string",
                            "description": "Human-readable explanation of the failure."
                          },
                          "expected": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Allowed values or constraint descriptions, when known; null otherwise."
                          },
                          "got": {
                            "type": "string",
                            "description": "The actual value that was received, when available; null otherwise."
                          }
                        }
                      },
                      "description": "Per-parameter validation failures when the input was rejected (ResultCode RESULT_INVALID_PARAMS); null on success."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "delete": {
        "operationId": "action_delete",
        "summary": "Delete an action",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "parameters": [
          {
            "name": "groupId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "actionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/actions": {
      "post": {
        "operationId": "action_add",
        "summary": "Add an action (OwnCode/CSharp category requires code:author, T3)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "description": "Action type (catalog category tag, e.g. \u0022WebBrowser\u0022, \u0022TextProcessing\u0022). Discover values via the actions catalog (GetActionsCatalog / FindActions)."
                  },
                  "action": {
                    "type": "string",
                    "description": "Action tag within the type (e.g. \u0022CMD_STARTINSTANCE\u0022, \u0022ToUpper\u0022). Together with Type it uniquely addresses one catalog variant."
                  },
                  "parameters": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Parameter values keyed by the schema parameter name of the selected variant (see GetActionSchema). Validated against the catalog schema; missing required parameters are rejected with validation errors."
                  },
                  "results": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Result bindings keyed by the schema result name (e.g. OutputVariable). The value is the project variable name to store the result into; variables that do not exist yet are created."
                  },
                  "bindings": {
                    "type": "object",
                    "properties": {
                      "discriminator": {
                        "type": "string",
                        "description": "Selects which binding the payload describes \u2014 the DiscriminatorValue of the target binding (e.g. \u0022XPathFinder\u0022, \u0022DomFinder\u0022). Must mirror the value of the category\u0027s binding-discriminator parameter (typically FinderType) passed in the action parameters."
                      },
                      "scalars": {
                        "type": "object",
                        "additionalProperties": {
                          "type": "string"
                        },
                        "description": "Scalar binding fields keyed by field name (see the binding\u0027s Fields in the catalog), e.g. XPath for XPathFinder."
                      },
                      "nestedArrays": {
                        "type": "object",
                        "additionalProperties": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        },
                        "description": "Repeated sub-groups keyed by array name; each entry is the list of element rows, a row being a field-name to value map (e.g. DomFinder\u0027s SearchCondition rows)."
                      }
                    },
                    "description": "Optional structured-binding payload (e.g. ElementFinder / XPathFinder). When non-null, the engine applies it to action.Parameters after writing flat parameters and before binding-validation."
                  },
                  "groupId": {
                    "type": "string",
                    "description": "Put the cube in this existing group instead of letting the cursor decide. Combined with AfterActionId it picks the slot; on its own the cube goes last in the group."
                  },
                  "afterActionId": {
                    "type": "string",
                    "description": "Put the cube straight after this one, inside its group. Implies the group, so GroupId can be left out."
                  },
                  "x": {
                    "type": "integer",
                    "description": "Left edge for the new group the cube starts. Pass both coordinates or neither, and not together with GroupId or AfterActionId, which place the cube in a group that already exists. Either mistake is rejected rather than half applied."
                  },
                  "y": {
                    "type": "integer",
                    "description": "Top edge for the new group the cube goes into."
                  },
                  "succesLink": {
                    "type": "string",
                    "description": "Reserved \u2014 currently ignored by the engine; wire the OnSuccess branch via SetActionLinks instead."
                  },
                  "failLink": {
                    "type": "string",
                    "description": "Reserved \u2014 currently ignored by the engine; wire the OnError branch via SetActionLinks instead."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "actionId": {
                      "type": "string",
                      "description": "Id assigned to the newly created action."
                    },
                    "groupId": {
                      "type": "string",
                      "description": "Id of the group the action was placed into."
                    },
                    "validationErrors": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "parameterName": {
                            "type": "string",
                            "description": "Name of the parameter or field that failed validation."
                          },
                          "code": {
                            "type": "string",
                            "description": "Machine-readable validation failure code (e.g. \u0022REQUIRED\u0022, \u0022out_of_range\u0022)."
                          },
                          "message": {
                            "type": "string",
                            "description": "Human-readable explanation of the failure."
                          },
                          "expected": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Allowed values or constraint descriptions, when known; null otherwise."
                          },
                          "got": {
                            "type": "string",
                            "description": "The actual value that was received, when available; null otherwise."
                          }
                        }
                      },
                      "description": "Per-parameter validation failures when the input was rejected (ResultCode RESULT_INVALID_PARAMS); null on success."
                    },
                    "layoutConflicts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "groupId": {
                            "type": "string",
                            "description": "The group that could not be placed."
                          },
                          "conflictingGroupIds": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "The groups already occupying that space."
                          },
                          "conflictingStaticBlocks": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Static blocks in the way, by display name, such as Start. They have no group id, and the editor refuses a drag onto them just the same."
                          }
                        }
                      },
                      "description": "What was already at the requested \u0027x\u0027/\u0027y\u0027, when the add was refused because a new group would have overlapped it. This never appears in a 200: a refusal is a 409, and the host carries these into the error body\u0027s layoutConflicts."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "failed_precondition: The requested position overlaps another group; the response lists the conflicting groups (RESULT_FAILED_PRECONDITION)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/actions/{groupId}/{actionId}/name": {
      "put": {
        "operationId": "action_rename",
        "summary": "Set an action\u0027s display name on the schema (empty string clears it)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "parameters": [
          {
            "name": "groupId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "actionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "The action\u0027s new display name, the same text the editor calls the cube\u0027s comment. Required; an empty string clears the name and the cube falls back to the auto-caption derived from its type. Free text, exactly as in the editor: no length limit, no character restrictions, and names need not be unique."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "actionId": {
                      "type": "string",
                      "description": "Id of the renamed action."
                    },
                    "groupId": {
                      "type": "string",
                      "description": "Id of the group the action belongs to."
                    },
                    "name": {
                      "type": "string",
                      "description": "The name the action now carries."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/actions/move": {
      "post": {
        "operationId": "actions_move",
        "summary": "Move actions into a group",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "actions": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "groupId": {
                          "type": "string",
                          "description": "Id of the group containing the action."
                        },
                        "actionId": {
                          "type": "string",
                          "description": "Id of the action within the group."
                        }
                      }
                    },
                    "description": "Actions to move, identified by (GroupId, ActionId). Order matters \u2014 the actions land in this order."
                  },
                  "targetGroupId": {
                    "type": "string",
                    "description": "Target group ID. Leave null/empty to create a NEW group and put the actions there."
                  },
                  "afterActionId": {
                    "type": "string",
                    "description": "Within the target group, insert the moved actions immediately AFTER this action. Null/empty means \u0022insert at the start of the target group\u0022 (or \u0022at the end\u0022 if the target is a fresh group). Must reference an action that exists in the target group BEFORE the move."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "targetGroupId": {
                      "type": "string",
                      "description": "ID of the destination group (the existing one, or the freshly created group when none was supplied)."
                    },
                    "movedActions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "groupId": {
                            "type": "string",
                            "description": "Id of the group containing the action."
                          },
                          "actionId": {
                            "type": "string",
                            "description": "Id of the action within the group."
                          }
                        }
                      },
                      "description": "Updated (GroupId, ActionId) pairs after the move \u2014 actions retain their IDs but now report the new GroupId."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/groups/{groupId}/name": {
      "put": {
        "operationId": "group_rename",
        "summary": "Set a group\u0027s caption above its frame (empty string clears it)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "parameters": [
          {
            "name": "groupId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "The group\u0027s new caption, drawn above its frame. Required; an empty string clears it and the frame loses its header. Free text with no length limit, no character restrictions and no uniqueness rule, exactly as in the editor. The frame grows to fit the caption, so the cubes inside shift down as it gets taller."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "groupId": {
                      "type": "string",
                      "description": "Id of the renamed group."
                    },
                    "name": {
                      "type": "string",
                      "description": "The name the group now carries."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/actions/links": {
      "post": {
        "operationId": "action_links_set",
        "summary": "Set OnSuccess/OnError links (batch)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "links": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "actionId": {
                          "type": "string",
                          "description": "Id of the source action the branch originates from."
                        },
                        "groupId": {
                          "type": "string",
                          "description": "Id of the group containing the source action."
                        },
                        "branch": {
                          "type": "string",
                          "description": "\u0022OnSuccess\u0022 or \u0022OnError\u0022."
                        },
                        "targetActionId": {
                          "type": "string",
                          "description": "The action this branch jumps to. null or empty on writes means \u0022remove the explicit link and revert to the implicit next-in-group\u0022. On reads, null means there is no implicit successor either (last action of the group)."
                        },
                        "isImplicit": {
                          "type": "boolean",
                          "description": "Read-only. true when the link is computed from action ordering rather than stored explicitly. Always false in input to SetActionLinks (writing an \u0022implicit\u0022 link means clearing the explicit one \u2014 pass null TargetActionId)."
                        }
                      },
                      "required": [
                        "isImplicit"
                      ]
                    },
                    "description": "Branch assignments to apply. Each item names the source action, the branch (\u0022OnSuccess\u0022 or \u0022OnError\u0022) and the target action; a null/empty target clears the explicit link. Processed as a batch \u2014 see the per-item outcomes in the result."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-link outcomes in input order (Name carries the source action id). Failed items do not prevent the other links from being applied."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/actions/{groupId}/{actionId}/properties": {
      "patch": {
        "operationId": "action_properties_set",
        "summary": "Set the cube\u0027s user flags: disabled/breakpoint/optional/comment (partial: a null field is left as it is)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "parameters": [
          {
            "name": "groupId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "actionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "disabled": {
                    "type": "boolean",
                    "description": "Skip the cube at run time. A disabled cube always succeeds and the flow continues down its OnSuccess branch. Setting this to true raises the project\u0027s MinVersion to 7.2.1.0."
                  },
                  "breakpoint": {
                    "type": "boolean",
                    "description": "Pause the debugger before this cube runs."
                  },
                  "optional": {
                    "type": "boolean",
                    "description": "Do not fail the project when this cube errors."
                  },
                  "comment": {
                    "type": "string",
                    "description": "The cube\u0027s caption on the schema. An empty string clears it, null leaves it alone."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "disabled": {
                      "type": "boolean",
                      "description": "True when the cube is skipped at run time."
                    },
                    "breakpoint": {
                      "type": "boolean",
                      "description": "True when the debugger pauses before this cube."
                    },
                    "optional": {
                      "type": "boolean",
                      "description": "True when an error in this cube does not fail the project."
                    },
                    "comment": {
                      "type": "string",
                      "description": "The cube\u0027s caption on the schema, empty when it has none."
                    }
                  },
                  "required": [
                    "disabled",
                    "breakpoint",
                    "optional"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "failed_precondition: The project is not in a state that allows this operation (RESULT_FAILED_PRECONDITION)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/layout": {
      "get": {
        "operationId": "layout_get",
        "summary": "Frame of every group on the schema (x/y/width/height)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "groups": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "groupId": {
                            "type": "string",
                            "description": "Id of the group."
                          },
                          "label": {
                            "type": "string",
                            "description": "The group\u0027s caption, empty when it has none."
                          },
                          "x": {
                            "type": "integer",
                            "description": "Left edge of the frame."
                          },
                          "y": {
                            "type": "integer",
                            "description": "Top edge of the frame."
                          },
                          "width": {
                            "type": "integer",
                            "description": "Frame width, driven by the theme rather than by the content."
                          },
                          "height": {
                            "type": "integer",
                            "description": "Frame height, which grows with the number of cubes and the caption."
                          },
                          "actionCount": {
                            "type": "integer",
                            "description": "How many cubes the group holds."
                          }
                        },
                        "required": [
                          "x",
                          "y",
                          "width",
                          "height",
                          "actionCount"
                        ]
                      },
                      "description": "Every group in the project, in project order."
                    },
                    "staticBlocks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Display name, which is what a refused move reports since these have no id."
                          },
                          "x": {
                            "type": "integer",
                            "description": "Left edge."
                          },
                          "y": {
                            "type": "integer",
                            "description": "Top edge."
                          },
                          "width": {
                            "type": "integer",
                            "description": "Width."
                          },
                          "height": {
                            "type": "integer",
                            "description": "Height."
                          }
                        },
                        "required": [
                          "x",
                          "y",
                          "width",
                          "height"
                        ]
                      },
                      "description": "The other things occupying space on the schema, such as Start and notes. They cannot be moved through the API, but a group cannot be placed over one, so they belong in any search for a free spot."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "layout_set",
        "summary": "Move several groups at once (one redraw, one undo step)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "groups": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "groupId": {
                          "type": "string",
                          "description": "Id of the group to move."
                        },
                        "x": {
                          "type": "integer",
                          "description": "New left edge of the frame."
                        },
                        "y": {
                          "type": "integer",
                          "description": "New top edge of the frame."
                        }
                      },
                      "required": [
                        "x",
                        "y"
                      ]
                    },
                    "description": "The groups to move. An empty or missing list is rejected."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "applied": {
                      "type": "integer",
                      "description": "How many groups were moved."
                    },
                    "groups": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "groupId": {
                            "type": "string",
                            "description": "Id of the group."
                          },
                          "label": {
                            "type": "string",
                            "description": "The group\u0027s caption, empty when it has none."
                          },
                          "x": {
                            "type": "integer",
                            "description": "Left edge of the frame."
                          },
                          "y": {
                            "type": "integer",
                            "description": "Top edge of the frame."
                          },
                          "width": {
                            "type": "integer",
                            "description": "Frame width, driven by the theme rather than by the content."
                          },
                          "height": {
                            "type": "integer",
                            "description": "Frame height, which grows with the number of cubes and the caption."
                          },
                          "actionCount": {
                            "type": "integer",
                            "description": "How many cubes the group holds."
                          }
                        },
                        "required": [
                          "x",
                          "y",
                          "width",
                          "height",
                          "actionCount"
                        ]
                      },
                      "description": "The frames of every group after the write, so a caller does not need a second read to see where things landed once the editor has had its say."
                    },
                    "layoutConflicts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "groupId": {
                            "type": "string",
                            "description": "The group that could not be placed."
                          },
                          "conflictingGroupIds": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "The groups already occupying that space."
                          },
                          "conflictingStaticBlocks": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Static blocks in the way, by display name, such as Start. They have no group id, and the editor refuses a drag onto them just the same."
                          }
                        }
                      },
                      "description": "The overlaps that made the batch refuse, one entry per group that could not be placed. This never appears in a 200: a refusal is a 409, and the host carries these into the error body\u0027s layoutConflicts."
                    }
                  },
                  "required": [
                    "applied"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "failed_precondition: The requested position overlaps another group; the response lists the conflicting groups (RESULT_FAILED_PRECONDITION)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/groups/{groupId}/position": {
      "put": {
        "operationId": "group_position_set",
        "summary": "Move one group; its actions and lines follow",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "parameters": [
          {
            "name": "groupId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "x": {
                    "type": "integer",
                    "description": "New left edge of the frame."
                  },
                  "y": {
                    "type": "integer",
                    "description": "New top edge of the frame."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                },
                "required": [
                  "x",
                  "y"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "x": {
                      "type": "integer",
                      "description": "Left edge of the frame after the move."
                    },
                    "y": {
                      "type": "integer",
                      "description": "Top edge of the frame after the move."
                    },
                    "layoutConflicts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "groupId": {
                            "type": "string",
                            "description": "The group that could not be placed."
                          },
                          "conflictingGroupIds": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "The groups already occupying that space."
                          },
                          "conflictingStaticBlocks": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Static blocks in the way, by display name, such as Start. They have no group id, and the editor refuses a drag onto them just the same."
                          }
                        }
                      },
                      "description": "What blocked the move, when it was refused. This never appears in a 200: a refusal is a 409, and the host carries these into the error body\u0027s layoutConflicts."
                    }
                  },
                  "required": [
                    "x",
                    "y"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "failed_precondition: The requested position overlaps another group; the response lists the conflicting groups (RESULT_FAILED_PRECONDITION)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/groups/{groupId}/copy": {
      "post": {
        "operationId": "group_copy",
        "summary": "Copy a group inside the open project, optionally at given coordinates",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "parameters": [
          {
            "name": "groupId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "x": {
                    "type": "integer",
                    "description": "Left edge for the copy. Leave both coordinates out to have the editor find a free spot beside the original."
                  },
                  "y": {
                    "type": "integer",
                    "description": "Top edge for the copy."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "newGroupId": {
                      "type": "string",
                      "description": "Id of the new group."
                    },
                    "actionIds": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Ids of the cubes in the copy, in group order."
                    },
                    "x": {
                      "type": "integer",
                      "description": "Left edge of the copy\u0027s frame."
                    },
                    "y": {
                      "type": "integer",
                      "description": "Top edge of the copy\u0027s frame."
                    },
                    "layoutConflicts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "groupId": {
                            "type": "string",
                            "description": "The group that could not be placed."
                          },
                          "conflictingGroupIds": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "The groups already occupying that space."
                          },
                          "conflictingStaticBlocks": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Static blocks in the way, by display name, such as Start. They have no group id, and the editor refuses a drag onto them just the same."
                          }
                        }
                      },
                      "description": "What blocked the copy, when it was refused and nothing was created. This never appears in a 200: a refusal is a 409, and the host carries these into the error body\u0027s layoutConflicts."
                    }
                  },
                  "required": [
                    "x",
                    "y"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "failed_precondition: The requested position overlaps another group; the response lists the conflicting groups (RESULT_FAILED_PRECONDITION)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/cursor": {
      "get": {
        "operationId": "cursor_get",
        "summary": "Cursor position",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "actionId": {
                      "type": "string",
                      "description": "Id of the action the ProjectMaker cursor (current selection) is on. ResultCode is RESULT_NOT_FOUND when nothing is selected."
                    },
                    "groupId": {
                      "type": "string",
                      "description": "Id of the group containing the selected action."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "cursor_set",
        "summary": "Set the cursor",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "actionId": {
                    "type": "string",
                    "description": "Id of the action to select (move the ProjectMaker cursor to). The action is resolved by this id alone."
                  },
                  "groupId": {
                    "type": "string",
                    "description": "Id of the group containing the action (accompanies ActionId; not used for the lookup)."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/actions/{groupId}/{actionId}/execute": {
      "post": {
        "operationId": "action_execute",
        "summary": "Execute a single action \u2014 RCE class",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 3,
        "x-implemented": true,
        "x-required-scope": "project:run",
        "parameters": [
          {
            "name": "groupId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "actionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "successActionId": {
                      "type": "string",
                      "description": "Id of the action execution continues with on success: the explicit OnSuccess link, or the implicit next action in the group when no link is set. Null when the action is terminal."
                    },
                    "failActionId": {
                      "type": "string",
                      "description": "Id of the action execution continues with on error \u2014 only when an explicit OnError link is set on this action. Null means no OnError branch."
                    },
                    "executeStatus": {
                      "type": "string",
                      "enum": [
                        "NotStarted",
                        "Executing",
                        "Success",
                        "Fail"
                      ],
                      "description": "Execution status of the action sampled right after the run was started: NotStarted | Executing | Success | Fail. When still Executing, poll the execute-status operation until it reaches a terminal state."
                    }
                  },
                  "required": [
                    "executeStatus"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/actions/{groupId}/{actionId}/execute/status": {
      "get": {
        "operationId": "action_execute_status",
        "summary": "Execution status of an action",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "parameters": [
          {
            "name": "groupId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "actionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "actionId": {
                      "type": "string",
                      "description": "Echo of the requested action id, so parallel status polls stay attributable."
                    },
                    "groupId": {
                      "type": "string",
                      "description": "Echo of the requested group id."
                    },
                    "successActionId": {
                      "type": "string",
                      "description": "Id of the action execution continues with on success: the explicit OnSuccess link, or the implicit next action in the group when no link is set. Null when the action is terminal."
                    },
                    "failActionId": {
                      "type": "string",
                      "description": "Id of the action execution continues with on error \u2014 only when an explicit OnError link is set on this action. Null means no OnError branch: the error propagates upward (there is no implicit next-in-group fallback for OnError)."
                    },
                    "executeStatus": {
                      "type": "string",
                      "enum": [
                        "NotStarted",
                        "Executing",
                        "Success",
                        "Fail"
                      ],
                      "description": "Current execution status of the action: NotStarted (never ran) | Executing | Success | Fail."
                    },
                    "executionError": {
                      "type": "string",
                      "description": "Message of the error that failed this action \u2014 set only when ExecuteStatus is Fail and the project\u0027s last error belongs to this action."
                    }
                  },
                  "required": [
                    "executeStatus"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/last-error": {
      "get": {
        "operationId": "last_error_get",
        "summary": "Last execution error",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "actionId": {
                      "type": "string",
                      "description": "Id of the action that raised the project\u0027s last execution error."
                    },
                    "groupId": {
                      "type": "string",
                      "description": "Id of the group containing that action."
                    },
                    "lastError": {
                      "type": "string",
                      "description": "Message of the last execution error. ResultCode is RESULT_NOT_FOUND when the project has no recorded error."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/logs": {
      "get": {
        "operationId": "logs_get",
        "summary": "Execution logs (filter by level)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "parameters": [
          {
            "name": "skip",
            "in": "query",
            "required": false,
            "description": "Paging offset: number of matching log entries to skip. Default 0.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "take",
            "in": "query",
            "required": false,
            "description": "Maximum number of entries to return. Default 100 when omitted or non-positive.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "logLevel",
            "in": "query",
            "required": false,
            "description": "Severity filter: level names (Info, Warning, Error \u2014 comma-separated to combine) or their flag sum (Info=1, Warning=2, Error=4). Omitted = all levels.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "logs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "actionId": {
                            "type": "string",
                            "description": "Id of the action the log entry relates to."
                          },
                          "groupId": {
                            "type": "string",
                            "description": "Id of the group containing that action."
                          },
                          "timeStamp": {
                            "type": "string",
                            "format": "date-time",
                            "description": "When the entry was written."
                          },
                          "level": {
                            "type": "string",
                            "enum": [
                              "Info",
                              "Warning",
                              "Error"
                            ],
                            "description": "Entry severity: Info | Warning | Error."
                          },
                          "message": {
                            "type": "string",
                            "description": "Log message text."
                          }
                        },
                        "required": [
                          "timeStamp",
                          "level"
                        ]
                      },
                      "description": "Matching execution-log entries after the skip/take paging window is applied."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/variables": {
      "get": {
        "operationId": "variables_list",
        "summary": "List variables",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "variables": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the variable. Required."
                          },
                          "newName": {
                            "type": "string",
                            "description": "New name when renaming on UpdateVariables. Null/empty means no rename."
                          },
                          "defaultValue": {
                            "type": "string",
                            "description": "Design-time default value the variable starts with on each project run."
                          },
                          "value": {
                            "type": "string",
                            "description": "Current (runtime) value \u2014 what the ProjectMaker variables panel shows in its \u0022Value\u0022 column. Populated on reads; on AddVariables/UpdateVariables a non-null value sets the current value (same effect and risk tier as variable_value_set), null leaves it untouched \u2014 the batch statics \u0022null = do not modify\u0022 convention."
                          },
                          "comment": {
                            "type": "string",
                            "description": "Free-form comment describing the variable\u0027s purpose."
                          },
                          "group": {
                            "type": "string",
                            "description": "\u0022AutoGenerated\u0022 or \u0022UserDefined\u0022."
                          }
                        }
                      },
                      "description": "All project variables with their full definitions and current values."
                    },
                    "totalCount": {
                      "type": "integer",
                      "description": "Total number of variables in the project."
                    }
                  },
                  "required": [
                    "totalCount"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "post": {
        "operationId": "variables_add",
        "summary": "Add variables (batch)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "variables": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Identifier of the variable. Required."
                        },
                        "newName": {
                          "type": "string",
                          "description": "New name when renaming on UpdateVariables. Null/empty means no rename."
                        },
                        "defaultValue": {
                          "type": "string",
                          "description": "Design-time default value the variable starts with on each project run."
                        },
                        "value": {
                          "type": "string",
                          "description": "Current (runtime) value \u2014 what the ProjectMaker variables panel shows in its \u0022Value\u0022 column. Populated on reads; on AddVariables/UpdateVariables a non-null value sets the current value (same effect and risk tier as variable_value_set), null leaves it untouched \u2014 the batch statics \u0022null = do not modify\u0022 convention."
                        },
                        "comment": {
                          "type": "string",
                          "description": "Free-form comment describing the variable\u0027s purpose."
                        },
                        "group": {
                          "type": "string",
                          "description": "\u0022AutoGenerated\u0022 or \u0022UserDefined\u0022."
                        }
                      }
                    },
                    "description": "Definitions of the variables to create. Each definition is processed independently; per-item outcomes are returned."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-item outcomes, one per input definition; a failed item does not fail the rest of the batch."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "variables_update",
        "summary": "Update variables (batch; rename via newName)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "variables": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Identifier of the variable. Required."
                        },
                        "newName": {
                          "type": "string",
                          "description": "New name when renaming on UpdateVariables. Null/empty means no rename."
                        },
                        "defaultValue": {
                          "type": "string",
                          "description": "Design-time default value the variable starts with on each project run."
                        },
                        "value": {
                          "type": "string",
                          "description": "Current (runtime) value \u2014 what the ProjectMaker variables panel shows in its \u0022Value\u0022 column. Populated on reads; on AddVariables/UpdateVariables a non-null value sets the current value (same effect and risk tier as variable_value_set), null leaves it untouched \u2014 the batch statics \u0022null = do not modify\u0022 convention."
                        },
                        "comment": {
                          "type": "string",
                          "description": "Free-form comment describing the variable\u0027s purpose."
                        },
                        "group": {
                          "type": "string",
                          "description": "\u0022AutoGenerated\u0022 or \u0022UserDefined\u0022."
                        }
                      }
                    },
                    "description": "Definitions of the variables to update, matched by Name; null fields are left unchanged. Each definition is processed independently."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-item outcomes, one per input definition; a failed item does not fail the rest of the batch."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "delete": {
        "operationId": "variables_delete",
        "summary": "Delete variables by name",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "names": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Names of the variables to remove. Each name is processed independently; per-item outcomes are returned."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-item outcomes, one per input name; a failed item does not fail the rest of the batch."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/variables/{name}/value": {
      "get": {
        "operationId": "variable_value_get",
        "summary": "Runtime \u002B default value",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string",
                      "description": "Variable name echoed from the request."
                    },
                    "value": {
                      "type": "string",
                      "description": "Current (runtime) value of the variable."
                    },
                    "defaultValue": {
                      "type": "string",
                      "description": "Design-time default value the variable starts with on each project run."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "variable_value_set",
        "summary": "Set runtime value",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "value": {
                    "type": "string",
                    "description": "New current (runtime) value for the variable. Does not change the variable\u0027s design-time default value."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/lists": {
      "get": {
        "operationId": "lists_list",
        "summary": "List the project\u0027s Lists",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "lists": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the list. Required."
                          },
                          "newName": {
                            "type": "string",
                            "description": "New name when renaming on UpdateLists. Null/empty means no rename."
                          },
                          "splitter": {
                            "type": "string",
                            "description": "Item delimiter. Default is the macro \u0022{-String.Enter-}\u0022."
                          },
                          "splitterType": {
                            "type": "string",
                            "description": "Splitter type \u2014 \u0022Text\u0022 or \u0022Regex\u0022."
                          },
                          "bindToFile": {
                            "type": "boolean",
                            "description": "If true, the list content is loaded from the file on disk given by BindedFile instead of DefaultItems."
                          },
                          "syncWithFile": {
                            "type": "boolean",
                            "description": "If true, changes made to the list at runtime are written back to the bound file."
                          },
                          "bindedFile": {
                            "type": "string",
                            "description": "File path the list is bound to (only meaningful when BindToFile is true)."
                          },
                          "leaveBlankFile": {
                            "type": "boolean",
                            "description": "If true, a bound file that becomes empty is kept on disk as an empty file; by default it is deleted."
                          },
                          "defaultItems": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Default items of the list. Each entry is one item."
                          }
                        }
                      },
                      "description": "All project lists with their full definitions."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "post": {
        "operationId": "lists_add",
        "summary": "Add lists (batch)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "lists": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Identifier of the list. Required."
                        },
                        "newName": {
                          "type": "string",
                          "description": "New name when renaming on UpdateLists. Null/empty means no rename."
                        },
                        "splitter": {
                          "type": "string",
                          "description": "Item delimiter. Default is the macro \u0022{-String.Enter-}\u0022."
                        },
                        "splitterType": {
                          "type": "string",
                          "description": "Splitter type \u2014 \u0022Text\u0022 or \u0022Regex\u0022."
                        },
                        "bindToFile": {
                          "type": "boolean",
                          "description": "If true, the list content is loaded from the file on disk given by BindedFile instead of DefaultItems."
                        },
                        "syncWithFile": {
                          "type": "boolean",
                          "description": "If true, changes made to the list at runtime are written back to the bound file."
                        },
                        "bindedFile": {
                          "type": "string",
                          "description": "File path the list is bound to (only meaningful when BindToFile is true)."
                        },
                        "leaveBlankFile": {
                          "type": "boolean",
                          "description": "If true, a bound file that becomes empty is kept on disk as an empty file; by default it is deleted."
                        },
                        "defaultItems": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Default items of the list. Each entry is one item."
                        }
                      }
                    },
                    "description": "Definitions of the lists to create. Each definition is processed independently; per-item outcomes are returned."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-item outcomes, one per input definition; a failed item does not fail the rest of the batch."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "lists_update",
        "summary": "Update lists (batch; rename via newName)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "lists": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Identifier of the list. Required."
                        },
                        "newName": {
                          "type": "string",
                          "description": "New name when renaming on UpdateLists. Null/empty means no rename."
                        },
                        "splitter": {
                          "type": "string",
                          "description": "Item delimiter. Default is the macro \u0022{-String.Enter-}\u0022."
                        },
                        "splitterType": {
                          "type": "string",
                          "description": "Splitter type \u2014 \u0022Text\u0022 or \u0022Regex\u0022."
                        },
                        "bindToFile": {
                          "type": "boolean",
                          "description": "If true, the list content is loaded from the file on disk given by BindedFile instead of DefaultItems."
                        },
                        "syncWithFile": {
                          "type": "boolean",
                          "description": "If true, changes made to the list at runtime are written back to the bound file."
                        },
                        "bindedFile": {
                          "type": "string",
                          "description": "File path the list is bound to (only meaningful when BindToFile is true)."
                        },
                        "leaveBlankFile": {
                          "type": "boolean",
                          "description": "If true, a bound file that becomes empty is kept on disk as an empty file; by default it is deleted."
                        },
                        "defaultItems": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Default items of the list. Each entry is one item."
                        }
                      }
                    },
                    "description": "Definitions of the lists to update, matched by Name; null fields are left unchanged. Each definition is processed independently."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-item outcomes, one per input definition; a failed item does not fail the rest of the batch."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "delete": {
        "operationId": "lists_delete",
        "summary": "Delete lists by name",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "names": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Names of the lists to remove. Each name is processed independently; per-item outcomes are returned."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-item outcomes, one per input name; a failed item does not fail the rest of the batch."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/lists/{name}/items": {
      "get": {
        "operationId": "list_items_get",
        "summary": "Runtime list items (skip/take)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "skip",
            "in": "query",
            "required": false,
            "description": "Paging offset: number of items to skip. Default 0.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "take",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return. Default 100 when omitted or non-positive.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "skip": {
                    "type": "integer",
                    "description": "Number of items to skip from the start of the list. Default is 0."
                  },
                  "take": {
                    "type": "integer",
                    "description": "Maximum number of items to return. Default is 1000."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                },
                "required": [
                  "skip",
                  "take"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string",
                      "description": "List name echoed from the request."
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Requested page of list items, in list order."
                    },
                    "totalCount": {
                      "type": "integer",
                      "description": "Total number of items in the list (before Skip/Take paging)."
                    }
                  },
                  "required": [
                    "totalCount"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "post": {
        "operationId": "list_items_add",
        "summary": "Add list items",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Items to append to the end of the list, one entry per item."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/tables": {
      "get": {
        "operationId": "tables_list",
        "summary": "List tables",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tables": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the table. Required."
                          },
                          "newName": {
                            "type": "string",
                            "description": "New name when renaming the table on UpdateTables. Null/empty means no rename. Renaming updates all references in the project."
                          },
                          "colSeparator": {
                            "type": "string",
                            "description": "Column delimiter. Default is \u0022;\u0022."
                          },
                          "colSeparatorType": {
                            "type": "string",
                            "description": "Type of column delimiter \u2014 e.g. \u0022Text\u0022, \u0022Regex\u0022, \u0022CharArray\u0022."
                          },
                          "rowSeparator": {
                            "type": "string",
                            "description": "Row delimiter. Default is the macro \u0022{-String.Enter-}\u0022."
                          },
                          "rowSeparatorType": {
                            "type": "string",
                            "description": "Type of row delimiter \u2014 same set as ColSeparatorType."
                          },
                          "csvSeparator": {
                            "type": "string",
                            "description": "CSV-specific separator (used when reading/writing .csv files)."
                          },
                          "isFirstRowContainsHeaders": {
                            "type": "boolean",
                            "description": "If true, the first row holds column header text instead of data. Columns themselves are index-addressed (A, B, C, ...); headers are just the first-row cells."
                          },
                          "bindToFile": {
                            "type": "boolean",
                            "description": "If true, the table content is loaded from the file on disk given by BindedFile instead of DefaultItems."
                          },
                          "syncWithFile": {
                            "type": "boolean",
                            "description": "If true, changes made to the table at runtime are written back to the bound file."
                          },
                          "bindedFile": {
                            "type": "string",
                            "description": "File path the table is bound to (only meaningful when BindToFile is true)."
                          },
                          "useSpecializedFormat": {
                            "type": "boolean",
                            "description": "If true, the bound file is read/written in its native spreadsheet format (xls/xlsx/csv) instead of plain text split by the row/column separators."
                          },
                          "leaveBlankFile": {
                            "type": "boolean",
                            "description": "If true, a bound file that becomes empty is kept on disk as an empty file; by default it is deleted."
                          },
                          "tryParseType": {
                            "type": "boolean",
                            "description": "If true, cell values are type-detected (numbers, dates) when written to a spreadsheet-format file instead of being stored as plain text."
                          },
                          "isCorrectDisplayInExcel": {
                            "type": "boolean",
                            "description": "If true, a UTF-8 BOM is added when saving the bound file so Excel displays non-ASCII text correctly."
                          },
                          "defaultItems": {
                            "type": "string",
                            "description": "Default contents of the table as a single string (rows separated by RowSeparator, cells by ColSeparator)."
                          }
                        }
                      },
                      "description": "All project tables with their full definitions."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "post": {
        "operationId": "tables_add",
        "summary": "Add tables (batch)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tables": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Identifier of the table. Required."
                        },
                        "newName": {
                          "type": "string",
                          "description": "New name when renaming the table on UpdateTables. Null/empty means no rename. Renaming updates all references in the project."
                        },
                        "colSeparator": {
                          "type": "string",
                          "description": "Column delimiter. Default is \u0022;\u0022."
                        },
                        "colSeparatorType": {
                          "type": "string",
                          "description": "Type of column delimiter \u2014 e.g. \u0022Text\u0022, \u0022Regex\u0022, \u0022CharArray\u0022."
                        },
                        "rowSeparator": {
                          "type": "string",
                          "description": "Row delimiter. Default is the macro \u0022{-String.Enter-}\u0022."
                        },
                        "rowSeparatorType": {
                          "type": "string",
                          "description": "Type of row delimiter \u2014 same set as ColSeparatorType."
                        },
                        "csvSeparator": {
                          "type": "string",
                          "description": "CSV-specific separator (used when reading/writing .csv files)."
                        },
                        "isFirstRowContainsHeaders": {
                          "type": "boolean",
                          "description": "If true, the first row holds column header text instead of data. Columns themselves are index-addressed (A, B, C, ...); headers are just the first-row cells."
                        },
                        "bindToFile": {
                          "type": "boolean",
                          "description": "If true, the table content is loaded from the file on disk given by BindedFile instead of DefaultItems."
                        },
                        "syncWithFile": {
                          "type": "boolean",
                          "description": "If true, changes made to the table at runtime are written back to the bound file."
                        },
                        "bindedFile": {
                          "type": "string",
                          "description": "File path the table is bound to (only meaningful when BindToFile is true)."
                        },
                        "useSpecializedFormat": {
                          "type": "boolean",
                          "description": "If true, the bound file is read/written in its native spreadsheet format (xls/xlsx/csv) instead of plain text split by the row/column separators."
                        },
                        "leaveBlankFile": {
                          "type": "boolean",
                          "description": "If true, a bound file that becomes empty is kept on disk as an empty file; by default it is deleted."
                        },
                        "tryParseType": {
                          "type": "boolean",
                          "description": "If true, cell values are type-detected (numbers, dates) when written to a spreadsheet-format file instead of being stored as plain text."
                        },
                        "isCorrectDisplayInExcel": {
                          "type": "boolean",
                          "description": "If true, a UTF-8 BOM is added when saving the bound file so Excel displays non-ASCII text correctly."
                        },
                        "defaultItems": {
                          "type": "string",
                          "description": "Default contents of the table as a single string (rows separated by RowSeparator, cells by ColSeparator)."
                        }
                      }
                    },
                    "description": "Definitions of the tables to create. Each definition is processed independently; per-item outcomes are returned."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-input outcome, in the same order as the input items."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "tables_update",
        "summary": "Update tables (batch; rename via newName)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tables": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Identifier of the table. Required."
                        },
                        "newName": {
                          "type": "string",
                          "description": "New name when renaming the table on UpdateTables. Null/empty means no rename. Renaming updates all references in the project."
                        },
                        "colSeparator": {
                          "type": "string",
                          "description": "Column delimiter. Default is \u0022;\u0022."
                        },
                        "colSeparatorType": {
                          "type": "string",
                          "description": "Type of column delimiter \u2014 e.g. \u0022Text\u0022, \u0022Regex\u0022, \u0022CharArray\u0022."
                        },
                        "rowSeparator": {
                          "type": "string",
                          "description": "Row delimiter. Default is the macro \u0022{-String.Enter-}\u0022."
                        },
                        "rowSeparatorType": {
                          "type": "string",
                          "description": "Type of row delimiter \u2014 same set as ColSeparatorType."
                        },
                        "csvSeparator": {
                          "type": "string",
                          "description": "CSV-specific separator (used when reading/writing .csv files)."
                        },
                        "isFirstRowContainsHeaders": {
                          "type": "boolean",
                          "description": "If true, the first row holds column header text instead of data. Columns themselves are index-addressed (A, B, C, ...); headers are just the first-row cells."
                        },
                        "bindToFile": {
                          "type": "boolean",
                          "description": "If true, the table content is loaded from the file on disk given by BindedFile instead of DefaultItems."
                        },
                        "syncWithFile": {
                          "type": "boolean",
                          "description": "If true, changes made to the table at runtime are written back to the bound file."
                        },
                        "bindedFile": {
                          "type": "string",
                          "description": "File path the table is bound to (only meaningful when BindToFile is true)."
                        },
                        "useSpecializedFormat": {
                          "type": "boolean",
                          "description": "If true, the bound file is read/written in its native spreadsheet format (xls/xlsx/csv) instead of plain text split by the row/column separators."
                        },
                        "leaveBlankFile": {
                          "type": "boolean",
                          "description": "If true, a bound file that becomes empty is kept on disk as an empty file; by default it is deleted."
                        },
                        "tryParseType": {
                          "type": "boolean",
                          "description": "If true, cell values are type-detected (numbers, dates) when written to a spreadsheet-format file instead of being stored as plain text."
                        },
                        "isCorrectDisplayInExcel": {
                          "type": "boolean",
                          "description": "If true, a UTF-8 BOM is added when saving the bound file so Excel displays non-ASCII text correctly."
                        },
                        "defaultItems": {
                          "type": "string",
                          "description": "Default contents of the table as a single string (rows separated by RowSeparator, cells by ColSeparator)."
                        }
                      }
                    },
                    "description": "Definitions of the tables to update, matched by Name; null fields are left unchanged. Each definition is processed independently."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-item outcomes, one per input definition; a failed item does not fail the rest of the batch."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "delete": {
        "operationId": "tables_delete",
        "summary": "Delete tables by name",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "names": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Names of the tables to remove. Each name is processed independently; per-item outcomes are returned."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-item outcomes, one per input name; a failed item does not fail the rest of the batch."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/tables/{name}/columns": {
      "get": {
        "operationId": "table_columns_get",
        "summary": "Table columns",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "columns": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Column names in table order. Table columns are index-addressed and unnamed, so these are Excel-style letters (A, B, C, ...)."
                    },
                    "hasHeaders": {
                      "type": "boolean",
                      "description": "True when the table\u0027s first row holds column header text (IsFirstRowContainsHeaders)."
                    },
                    "columnHeaders": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Header text taken from the first row, one entry per column. Empty when HasHeaders is false."
                    }
                  },
                  "required": [
                    "hasHeaders"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "post": {
        "operationId": "table_column_add",
        "summary": "Add a column (optional header)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "header": {
                    "type": "string",
                    "description": "Optional header text for the new column, written into the first (header) row. Allowed only when the table is marked as having a header row \u2014 otherwise the request fails with 400. On an empty table the header materializes the header row."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "columnName": {
                      "type": "string",
                      "description": "Excel-style name (A, B, C, ...) assigned to the newly added column, derived from its index \u2014 table columns are index-addressed, not named."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/tables/{name}/rows": {
      "get": {
        "operationId": "table_rows_get",
        "summary": "Table rows (skip/take)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "skip",
            "in": "query",
            "required": false,
            "description": "Paging offset: number of items to skip. Default 0.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "take",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return. Default 100 when omitted or non-positive.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "skip": {
                    "type": "integer",
                    "description": "Number of rows to skip from the start of the table. Default is 0."
                  },
                  "take": {
                    "type": "integer",
                    "description": "Maximum number of rows to return. Default is 1000."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                },
                "required": [
                  "skip",
                  "take"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "rows": {
                      "type": "array",
                      "items": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "description": "Requested page of rows; each row is an array of cell values in the same order as Columns. When the table has a header row it is stored as part of the data and returned as the first row."
                    },
                    "columns": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Excel-style column names (A, B, C, ...) giving the order of cells within each row \u2014 table columns are index-addressed, not named."
                    },
                    "totalCount": {
                      "type": "integer",
                      "description": "Total number of rows in the table (before Skip/Take paging)."
                    }
                  },
                  "required": [
                    "totalCount"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "post": {
        "operationId": "table_row_add",
        "summary": "Add a row",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "values": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Cell values of the row appended to the table, in column order."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/google-spreadsheets": {
      "get": {
        "operationId": "google_spreadsheets_list",
        "summary": "List Google Spreadsheets",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "googleSpreadsheets": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the GoogleSpreadsheet static. Required."
                          },
                          "newName": {
                            "type": "string",
                            "description": "New name when renaming on UpdateGoogleSpreadsheets. Null/empty means no rename. Renaming updates all references in the project."
                          },
                          "bindedURL": {
                            "type": "string",
                            "description": "Google Sheet URL or id this static is bound to. Empty until BindToGoogle runs."
                          },
                          "syncWithGoogle": {
                            "type": "boolean",
                            "description": "If true, runtime keeps the in-memory table synchronised with the live Google Sheet."
                          },
                          "colSeparator": {
                            "type": "string",
                            "description": "Column delimiter. Default is \u0022;\u0022."
                          },
                          "colSeparatorType": {
                            "type": "string",
                            "description": "Type of column delimiter \u2014 e.g. \u0022Text\u0022, \u0022Regex\u0022, \u0022CharArray\u0022."
                          },
                          "rowSeparator": {
                            "type": "string",
                            "description": "Row delimiter. Default is the macro \u0022{-String.Enter-}\u0022."
                          },
                          "rowSeparatorType": {
                            "type": "string",
                            "description": "Type of row delimiter \u2014 same set as ColSeparatorType."
                          },
                          "isFirstRowContainsHeaders": {
                            "type": "boolean",
                            "description": "If true, the first row holds column header text instead of data. Columns themselves are index-addressed (A, B, C, ...); headers are just the first-row cells."
                          },
                          "isUseAtomicAppending": {
                            "type": "boolean",
                            "description": "If true, append operations bundle into a single atomic batch sent to Google."
                          },
                          "isMemorizePinnedRowsAndCols": {
                            "type": "boolean",
                            "description": "If true, the runtime remembers pinned rows/cols between syncs."
                          },
                          "defaultItems": {
                            "type": "string",
                            "description": "Default contents of the spreadsheet as a single string (rows separated by RowSeparator, cells by ColSeparator)."
                          }
                        }
                      },
                      "description": "All GoogleSpreadsheet statics of the project with their full definitions."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "post": {
        "operationId": "google_spreadsheets_add",
        "summary": "Add Google Spreadsheets (batch)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "googleSpreadsheets": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Identifier of the GoogleSpreadsheet static. Required."
                        },
                        "newName": {
                          "type": "string",
                          "description": "New name when renaming on UpdateGoogleSpreadsheets. Null/empty means no rename. Renaming updates all references in the project."
                        },
                        "bindedURL": {
                          "type": "string",
                          "description": "Google Sheet URL or id this static is bound to. Empty until BindToGoogle runs."
                        },
                        "syncWithGoogle": {
                          "type": "boolean",
                          "description": "If true, runtime keeps the in-memory table synchronised with the live Google Sheet."
                        },
                        "colSeparator": {
                          "type": "string",
                          "description": "Column delimiter. Default is \u0022;\u0022."
                        },
                        "colSeparatorType": {
                          "type": "string",
                          "description": "Type of column delimiter \u2014 e.g. \u0022Text\u0022, \u0022Regex\u0022, \u0022CharArray\u0022."
                        },
                        "rowSeparator": {
                          "type": "string",
                          "description": "Row delimiter. Default is the macro \u0022{-String.Enter-}\u0022."
                        },
                        "rowSeparatorType": {
                          "type": "string",
                          "description": "Type of row delimiter \u2014 same set as ColSeparatorType."
                        },
                        "isFirstRowContainsHeaders": {
                          "type": "boolean",
                          "description": "If true, the first row holds column header text instead of data. Columns themselves are index-addressed (A, B, C, ...); headers are just the first-row cells."
                        },
                        "isUseAtomicAppending": {
                          "type": "boolean",
                          "description": "If true, append operations bundle into a single atomic batch sent to Google."
                        },
                        "isMemorizePinnedRowsAndCols": {
                          "type": "boolean",
                          "description": "If true, the runtime remembers pinned rows/cols between syncs."
                        },
                        "defaultItems": {
                          "type": "string",
                          "description": "Default contents of the spreadsheet as a single string (rows separated by RowSeparator, cells by ColSeparator)."
                        }
                      }
                    },
                    "description": "Definitions of the GoogleSpreadsheet statics to create. Each definition is processed independently; per-item outcomes are returned."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-input outcome, in the same order as the input items."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "google_spreadsheets_update",
        "summary": "Update Google Spreadsheets (batch)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "googleSpreadsheets": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Identifier of the GoogleSpreadsheet static. Required."
                        },
                        "newName": {
                          "type": "string",
                          "description": "New name when renaming on UpdateGoogleSpreadsheets. Null/empty means no rename. Renaming updates all references in the project."
                        },
                        "bindedURL": {
                          "type": "string",
                          "description": "Google Sheet URL or id this static is bound to. Empty until BindToGoogle runs."
                        },
                        "syncWithGoogle": {
                          "type": "boolean",
                          "description": "If true, runtime keeps the in-memory table synchronised with the live Google Sheet."
                        },
                        "colSeparator": {
                          "type": "string",
                          "description": "Column delimiter. Default is \u0022;\u0022."
                        },
                        "colSeparatorType": {
                          "type": "string",
                          "description": "Type of column delimiter \u2014 e.g. \u0022Text\u0022, \u0022Regex\u0022, \u0022CharArray\u0022."
                        },
                        "rowSeparator": {
                          "type": "string",
                          "description": "Row delimiter. Default is the macro \u0022{-String.Enter-}\u0022."
                        },
                        "rowSeparatorType": {
                          "type": "string",
                          "description": "Type of row delimiter \u2014 same set as ColSeparatorType."
                        },
                        "isFirstRowContainsHeaders": {
                          "type": "boolean",
                          "description": "If true, the first row holds column header text instead of data. Columns themselves are index-addressed (A, B, C, ...); headers are just the first-row cells."
                        },
                        "isUseAtomicAppending": {
                          "type": "boolean",
                          "description": "If true, append operations bundle into a single atomic batch sent to Google."
                        },
                        "isMemorizePinnedRowsAndCols": {
                          "type": "boolean",
                          "description": "If true, the runtime remembers pinned rows/cols between syncs."
                        },
                        "defaultItems": {
                          "type": "string",
                          "description": "Default contents of the spreadsheet as a single string (rows separated by RowSeparator, cells by ColSeparator)."
                        }
                      }
                    },
                    "description": "Definitions of the GoogleSpreadsheet statics to update, matched by Name; null fields are left unchanged. Each definition is processed independently."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-item outcomes, one per input definition; a failed item does not fail the rest of the batch."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "delete": {
        "operationId": "google_spreadsheets_delete",
        "summary": "Delete Google Spreadsheets by name",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "names": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Names of the GoogleSpreadsheet statics to remove. Each name is processed independently; per-item outcomes are returned."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-item outcomes, one per input name; a failed item does not fail the rest of the batch."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/input-settings": {
      "get": {
        "operationId": "project_input_settings_list",
        "summary": "List input settings (values of a list type come back both raw and parsed)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "settings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifies the setting. Required. This is the stored name, which for a setting with an option list carries that list in braces (Country{RU|US}). On update and delete the stored name is matched first; if nothing matches, DisplayName is tried instead, so callers can address Country without repeating its options. An ambiguous display name (two settings share it) is rejected rather than guessed."
                          },
                          "newName": {
                            "type": "string",
                            "description": "New name when renaming on update. Null or empty means no rename. This replaces the visible part only and keeps whatever the braces hold, so renaming a drop-down does not drop its options. Pass a name that itself contains a brace to set the stored name verbatim, which is the escape hatch for the type-specific brace contents (Text{multiline} and FileName{\u2026}); that cannot be combined with Values."
                          },
                          "displayName": {
                            "type": "string",
                            "description": "The setting\u0027s name as the user sees it: Name with any brace section removed. Read-only, populated on reads and ignored on writes."
                          },
                          "type": {
                            "type": "string",
                            "description": "The control the setting is rendered as, one of: Boolean, Select, Text, FileName, Number, Label, DropDown, Tab, Comment, DropDownMultiSelect, CaptchaModules, SmsServices, TranslateServices, Password. Matched without regard to case; an unrecognised value is rejected rather than silently replaced. Label, Tab and Comment are decoration rather than input, so they need no variable."
                          },
                          "defaultValue": {
                            "type": "string",
                            "description": "The value the field starts with. This is also the value the setting contributes when the project runs inside ProjectMaker, which never shows the form."
                          },
                          "help": {
                            "type": "string",
                            "description": "Hint text shown next to the field."
                          },
                          "variable": {
                            "type": "string",
                            "description": "Plain name of the project variable the entered value is written into (the project stores it as a macro; the conversion is done here). A variable that does not exist yet is created. Without one the setting is shown but the runtime discards whatever the user typed, so it is required for every type except Label, Tab and Comment. An empty string clears the binding. The pair of name and variable has to be unique, because that pair is what the runtime matches a submitted value against."
                          },
                          "values": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "value": {
                                  "type": "string",
                                  "description": "The value written into the setting\u0027s variable when the user picks this option. Required. Cannot contain {, }, | or :, which are the option list\u0027s own separators, and cannot contain \u0022, \u0022 because DropDownMultiSelect joins the picked values with it."
                                },
                                "label": {
                                  "type": "string",
                                  "description": "What the user sees for this option, when it should read differently from Value. Null or empty means the value is shown as-is. Labels are all-or-nothing within one setting: either every option carries one or none does, because the project\u0027s encoding cannot express a mix. Same character restrictions as Value. Not supported for the Select type, which always shows the value itself."
                                }
                              }
                            },
                            "description": "The options offered by Select, DropDown and DropDownMultiSelect, replacing whatever the setting\u0027s braces held. An empty list removes the options. Null leaves them untouched, so a setting\u0027s help or default can be patched without restating its options. Rejected for the other types, whose braces mean something else entirely."
                          }
                        }
                      },
                      "description": "The project\u0027s input settings in the order the form shows them. Empty when the project has no input settings block at all."
                    },
                    "totalCount": {
                      "type": "integer",
                      "description": "Number of settings returned."
                    },
                    "settingsType": {
                      "type": "string",
                      "description": "Which parameter form the project actually uses at run time: InputSettings for these settings, BotUI when the project carries a BotUI block, which takes precedence and makes these settings dead weight, or None when it has neither. Writes are refused while this reads BotUI."
                    }
                  },
                  "required": [
                    "totalCount"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "post": {
        "operationId": "project_input_settings_add",
        "summary": "Add input settings (batch)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "settings": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Identifies the setting. Required. This is the stored name, which for a setting with an option list carries that list in braces (Country{RU|US}). On update and delete the stored name is matched first; if nothing matches, DisplayName is tried instead, so callers can address Country without repeating its options. An ambiguous display name (two settings share it) is rejected rather than guessed."
                        },
                        "newName": {
                          "type": "string",
                          "description": "New name when renaming on update. Null or empty means no rename. This replaces the visible part only and keeps whatever the braces hold, so renaming a drop-down does not drop its options. Pass a name that itself contains a brace to set the stored name verbatim, which is the escape hatch for the type-specific brace contents (Text{multiline} and FileName{\u2026}); that cannot be combined with Values."
                        },
                        "displayName": {
                          "type": "string",
                          "description": "The setting\u0027s name as the user sees it: Name with any brace section removed. Read-only, populated on reads and ignored on writes."
                        },
                        "type": {
                          "type": "string",
                          "description": "The control the setting is rendered as, one of: Boolean, Select, Text, FileName, Number, Label, DropDown, Tab, Comment, DropDownMultiSelect, CaptchaModules, SmsServices, TranslateServices, Password. Matched without regard to case; an unrecognised value is rejected rather than silently replaced. Label, Tab and Comment are decoration rather than input, so they need no variable."
                        },
                        "defaultValue": {
                          "type": "string",
                          "description": "The value the field starts with. This is also the value the setting contributes when the project runs inside ProjectMaker, which never shows the form."
                        },
                        "help": {
                          "type": "string",
                          "description": "Hint text shown next to the field."
                        },
                        "variable": {
                          "type": "string",
                          "description": "Plain name of the project variable the entered value is written into (the project stores it as a macro; the conversion is done here). A variable that does not exist yet is created. Without one the setting is shown but the runtime discards whatever the user typed, so it is required for every type except Label, Tab and Comment. An empty string clears the binding. The pair of name and variable has to be unique, because that pair is what the runtime matches a submitted value against."
                        },
                        "values": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "value": {
                                "type": "string",
                                "description": "The value written into the setting\u0027s variable when the user picks this option. Required. Cannot contain {, }, | or :, which are the option list\u0027s own separators, and cannot contain \u0022, \u0022 because DropDownMultiSelect joins the picked values with it."
                              },
                              "label": {
                                "type": "string",
                                "description": "What the user sees for this option, when it should read differently from Value. Null or empty means the value is shown as-is. Labels are all-or-nothing within one setting: either every option carries one or none does, because the project\u0027s encoding cannot express a mix. Same character restrictions as Value. Not supported for the Select type, which always shows the value itself."
                              }
                            }
                          },
                          "description": "The options offered by Select, DropDown and DropDownMultiSelect, replacing whatever the setting\u0027s braces held. An empty list removes the options. Null leaves them untouched, so a setting\u0027s help or default can be patched without restating its options. Rejected for the other types, whose braces mean something else entirely."
                        }
                      }
                    },
                    "description": "Definitions of the settings to append to the form, in order. Each is processed independently and per-item outcomes are returned. The project\u0027s input settings block is created if it does not exist yet."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-item outcomes, one per input definition; a failed item does not fail the rest of the batch. The item\u0027s name is the stored name the setting ended up with, braces included."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "failed_precondition: The project is not in a state that allows this operation (RESULT_FAILED_PRECONDITION)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "project_input_settings_update",
        "summary": "Update input settings (batch; rename via newName)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "settings": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Identifies the setting. Required. This is the stored name, which for a setting with an option list carries that list in braces (Country{RU|US}). On update and delete the stored name is matched first; if nothing matches, DisplayName is tried instead, so callers can address Country without repeating its options. An ambiguous display name (two settings share it) is rejected rather than guessed."
                        },
                        "newName": {
                          "type": "string",
                          "description": "New name when renaming on update. Null or empty means no rename. This replaces the visible part only and keeps whatever the braces hold, so renaming a drop-down does not drop its options. Pass a name that itself contains a brace to set the stored name verbatim, which is the escape hatch for the type-specific brace contents (Text{multiline} and FileName{\u2026}); that cannot be combined with Values."
                        },
                        "displayName": {
                          "type": "string",
                          "description": "The setting\u0027s name as the user sees it: Name with any brace section removed. Read-only, populated on reads and ignored on writes."
                        },
                        "type": {
                          "type": "string",
                          "description": "The control the setting is rendered as, one of: Boolean, Select, Text, FileName, Number, Label, DropDown, Tab, Comment, DropDownMultiSelect, CaptchaModules, SmsServices, TranslateServices, Password. Matched without regard to case; an unrecognised value is rejected rather than silently replaced. Label, Tab and Comment are decoration rather than input, so they need no variable."
                        },
                        "defaultValue": {
                          "type": "string",
                          "description": "The value the field starts with. This is also the value the setting contributes when the project runs inside ProjectMaker, which never shows the form."
                        },
                        "help": {
                          "type": "string",
                          "description": "Hint text shown next to the field."
                        },
                        "variable": {
                          "type": "string",
                          "description": "Plain name of the project variable the entered value is written into (the project stores it as a macro; the conversion is done here). A variable that does not exist yet is created. Without one the setting is shown but the runtime discards whatever the user typed, so it is required for every type except Label, Tab and Comment. An empty string clears the binding. The pair of name and variable has to be unique, because that pair is what the runtime matches a submitted value against."
                        },
                        "values": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "value": {
                                "type": "string",
                                "description": "The value written into the setting\u0027s variable when the user picks this option. Required. Cannot contain {, }, | or :, which are the option list\u0027s own separators, and cannot contain \u0022, \u0022 because DropDownMultiSelect joins the picked values with it."
                              },
                              "label": {
                                "type": "string",
                                "description": "What the user sees for this option, when it should read differently from Value. Null or empty means the value is shown as-is. Labels are all-or-nothing within one setting: either every option carries one or none does, because the project\u0027s encoding cannot express a mix. Same character restrictions as Value. Not supported for the Select type, which always shows the value itself."
                              }
                            }
                          },
                          "description": "The options offered by Select, DropDown and DropDownMultiSelect, replacing whatever the setting\u0027s braces held. An empty list removes the options. Null leaves them untouched, so a setting\u0027s help or default can be patched without restating its options. Rejected for the other types, whose braces mean something else entirely."
                        }
                      }
                    },
                    "description": "Patches to apply, each identified by its name. Every other field is optional and null leaves that part of the setting alone. Each patch is processed independently and per-item outcomes are returned. Positions are not affected; use the reorder operation for that."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-item outcomes, one per patch; a failed item does not fail the rest of the batch. The item\u0027s name is the stored name the setting ended up with, so a rename or a change of options is visible in the reply."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "failed_precondition: The project is not in a state that allows this operation (RESULT_FAILED_PRECONDITION)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "delete": {
        "operationId": "project_input_settings_delete",
        "summary": "Delete input settings by name",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "names": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Names of the settings to remove, either the stored name or the name as displayed. Each is processed independently and per-item outcomes are returned. Removing the last setting keeps the (now empty) block, matching what the editor does. The variables the settings were bound to are left in the project."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Identifier of the input item this outcome refers to (e.g. the list/table/variable name)."
                          },
                          "resultCode": {
                            "type": "string",
                            "enum": [
                              "RESULT_OK",
                              "RESULT_ERROR",
                              "RESULT_NOT_FOUND",
                              "RESULT_INVALID_PARAMS",
                              "RESULT_UNSUPPORTED_FEATURE",
                              "RESULT_PERMISSION_DENIED",
                              "RESULT_FAILED_PRECONDITION",
                              "RESULT_PROJECT_NOT_OPEN"
                            ],
                            "description": "Per-item result code; RESULT_OK when the item was processed successfully."
                          },
                          "error": {
                            "type": "string",
                            "description": "Per-item error message when the item failed; null on success."
                          }
                        },
                        "required": [
                          "resultCode"
                        ]
                      },
                      "description": "Per-item outcomes, one per requested name; a failed item does not fail the rest of the batch."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "failed_precondition: The project is not in a state that allows this operation (RESULT_FAILED_PRECONDITION)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/input-settings/order": {
      "put": {
        "operationId": "project_input_settings_reorder",
        "summary": "Reorder input settings by listing every name",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "names": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Every setting\u0027s name, in the order the form should show them. Either the stored names or the displayed ones. The list has to account for all of them exactly once: a list that skips or repeats a setting is refused outright rather than applied in part, because there is no sensible place to put the settings it left out. Reordering is all-or-nothing, so nothing moves unless the whole list checks out."
                  },
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "names": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The stored names in the order they now sit in, so the caller can confirm the move without reading the list again."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "failed_precondition: The project is not in a state that allows this operation (RESULT_FAILED_PRECONDITION)."
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/input-settings/block": {
      "delete": {
        "operationId": "project_input_settings_block_delete",
        "summary": "Delete the entire input settings block (idempotent; removed:false when there is no block to delete)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "session": {
                    "type": "string",
                    "description": "Optional legacy session identifier kept for wire compatibility. Ignored by v1 hosts \u2014 no host reads it; authentication is carried by the API key header instead."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "removed": {
                      "type": "boolean",
                      "description": "True when a block was present and has been removed; false when the project had no input settings block (idempotent \u2014 the call succeeds either way)."
                    },
                    "settingsType": {
                      "type": "string",
                      "description": "The settings type that was in effect before the operation: \u0022InputSettings\u0022 when a block existed, \u0022BotUI\u0022 when a BotUI block was in use instead, \u0022None\u0022 when no block was present."
                    }
                  },
                  "required": [
                    "removed"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/recording": {
      "get": {
        "operationId": "recording_get",
        "summary": "Recorder state",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "isRecording": {
                      "type": "boolean",
                      "description": "True when ProjectMaker is currently in recording mode (user/browser actions are captured as cubes)."
                    }
                  },
                  "required": [
                    "isRecording"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "recording_set",
        "summary": "Toggle action recording",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 2,
        "x-implemented": true,
        "x-required-scope": "project:record",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "isRecording": {
                    "type": "boolean",
                    "description": "Pass true to start recording, false to stop it."
                  }
                },
                "required": [
                  "isRecording"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {}
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/code-api": {
      "get": {
        "operationId": "code_api_get",
        "summary": "C# API surface for OwnCode (optional ?typeName=)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "code:read",
        "parameters": [
          {
            "name": "typeName",
            "in": "query",
            "required": false,
            "description": "Fully-qualified or short name of one type to describe in full; omitted = the summary index of all types.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sources": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "assembly": {
                            "type": "string",
                            "description": "Simple name of an assembly the code-api digest covers."
                          },
                          "version": {
                            "type": "string",
                            "description": "Version of that assembly at digest generation time."
                          }
                        }
                      },
                      "description": "Index mode: the assemblies the digest was generated from."
                    },
                    "types": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Short type name."
                          },
                          "fullName": {
                            "type": "string",
                            "description": "Namespace-qualified type name \u2014 the exact typeName to request in type mode."
                          },
                          "ns": {
                            "type": "string",
                            "description": "Namespace. Short wire name (\u0022ns\u0022) kept for LLM token economy."
                          },
                          "kind": {
                            "type": "string",
                            "description": "Type kind: \u0022class\u0022 | \u0022interface\u0022 | \u0022struct\u0022 | \u0022enum\u0022 | \u0022delegate\u0022."
                          },
                          "summary": {
                            "type": "string",
                            "description": "XML-doc summary of the type; null when it has none."
                          },
                          "memberCount": {
                            "type": "integer",
                            "description": "Number of public members \u2014 fetch them by requesting the type in type mode."
                          }
                        },
                        "required": [
                          "memberCount"
                        ]
                      },
                      "description": "Index mode: compact list of available types (no members)."
                    },
                    "type": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Short type name."
                        },
                        "fullName": {
                          "type": "string",
                          "description": "Namespace-qualified type name \u2014 the exact typeName to request in type mode."
                        },
                        "ns": {
                          "type": "string",
                          "description": "Namespace. Short wire name (\u0022ns\u0022) kept for LLM token economy."
                        },
                        "kind": {
                          "type": "string",
                          "description": "Type kind: \u0022class\u0022 | \u0022interface\u0022 | \u0022struct\u0022 | \u0022enum\u0022 | \u0022delegate\u0022."
                        },
                        "summary": {
                          "type": "string",
                          "description": "XML-doc summary of the type; null when it has none."
                        },
                        "baseType": {
                          "type": "string",
                          "description": "Base type name; null when there is no notable base."
                        },
                        "interfaces": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Interfaces the type implements."
                        },
                        "members": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "kind": {
                                "type": "string",
                                "description": "Member kind: \u0022property\u0022 | \u0022method\u0022 | \u0022field\u0022 | \u0022event\u0022 | \u0022enum-value\u0022."
                              },
                              "name": {
                                "type": "string",
                                "description": "Member name."
                              },
                              "signature": {
                                "type": "string",
                                "description": "Compact C# signature of the member."
                              },
                              "summary": {
                                "type": "string",
                                "description": "XML-doc summary of the member; null when it has none."
                              },
                              "parameters": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "name": {
                                      "type": "string",
                                      "description": "Parameter name."
                                    },
                                    "type": {
                                      "type": "string",
                                      "description": "C# type name of the parameter."
                                    },
                                    "summary": {
                                      "type": "string",
                                      "description": "XML-doc description of the parameter; null when absent."
                                    }
                                  }
                                },
                                "description": "Parameter descriptions for methods; null for other member kinds."
                              },
                              "returns": {
                                "type": "string",
                                "description": "XML-doc \u0022returns\u0022 text of a method; null when absent."
                              },
                              "isStatic": {
                                "type": "boolean",
                                "description": "True for static members (no instance needed)."
                              },
                              "isObsolete": {
                                "type": "boolean",
                                "description": "True when the member is marked [Obsolete] \u2014 prefer its replacement."
                              },
                              "refersTo": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "Other catalog types this member references \u2014 drive \u0022look here next\u0022 navigation."
                              }
                            },
                            "required": [
                              "isStatic",
                              "isObsolete"
                            ]
                          },
                          "description": "Public members of the type with signatures and summaries."
                        }
                      },
                      "description": "Type mode: the requested type with its full member list."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced project/action/variable/list/table/spreadsheet does not exist (RESULT_NOT_FOUND)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/shared-code": {
      "get": {
        "operationId": "shared_code_get",
        "summary": "Using directives, common code, load-from-file mode and path",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "code:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "usings": {
                      "type": "string",
                      "description": "The user\u0027s using directives, one per line. Does not include the default ones."
                    },
                    "commonCode": {
                      "type": "string",
                      "description": "The common code: members shared by every C# cube of the project."
                    },
                    "loadCodeFromFile": {
                      "type": "boolean",
                      "description": "True when the common code is loaded from LocalPath instead of the project."
                    },
                    "localPath": {
                      "type": "string",
                      "description": "Path to the .cs file the common code is loaded from. May contain project macros."
                    }
                  },
                  "required": [
                    "loadCodeFromFile"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "shared_code_set",
        "summary": "Change the shared code (partial: a null field is left as it is)",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 3,
        "x-implemented": true,
        "x-required-scope": "code:author",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "usings": {
                    "type": "string",
                    "description": "Replaces the user\u0027s using directives, one per line."
                  },
                  "commonCode": {
                    "type": "string",
                    "description": "Replaces the common code."
                  },
                  "loadCodeFromFile": {
                    "type": "boolean",
                    "description": "Turns the \u0022load the common code from a file\u0022 mode on or off."
                  },
                  "localPath": {
                    "type": "string",
                    "description": "Replaces the path the common code is loaded from."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "blockCreated": {
                      "type": "boolean",
                      "description": "True when the project had no static code block and one was created for this change."
                    }
                  },
                  "required": [
                    "blockCreated"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/projects/current/gac-references": {
      "get": {
        "operationId": "gac_references_get",
        "summary": "The project\u0027s GAC assembly references",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "project:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "references": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "One entry per reference, in the form the compiler and the IntelliSense resolver receive it: either an assembly name (\u0022System.Drawing\u0022 or a full strong name) or an external DLL marked as \u0022[external]Name[external]\u0022."
                    },
                    "totalCount": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "totalCount"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "gac_references_set",
        "summary": "Replace the whole GAC reference list",
        "tags": [
          "ProjectMaker"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "project:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "references": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Assembly names, or \u0022[external]Name[external]\u0022 for a DLL from the external assemblies folder. Same form References returns."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "references": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The references the project holds after the replacement. Not always the list that was sent: blank entries are dropped and duplicates collapsed, so this is what actually got stored."
                    },
                    "totalCount": {
                      "type": "integer",
                      "description": "Number of references the project holds after the replacement."
                    },
                    "blockCreated": {
                      "type": "boolean",
                      "description": "True when the project had no \u0022GAC references\u0022 block and one was created."
                    }
                  },
                  "required": [
                    "totalCount",
                    "blockCreated"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "409": {
            "description": "project_not_open: No project is open in the editor \u2014 open or create one first (RESULT_PROJECT_NOT_OPEN)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks": {
      "get": {
        "operationId": "tasks_list",
        "summary": "List tasks",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "task:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tasks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Task GUID."
                          },
                          "name": {
                            "type": "string",
                            "description": "Task display name."
                          },
                          "projectPath": {
                            "type": "string",
                            "description": "Path to the project file the task references."
                          }
                        }
                      },
                      "description": "All tasks currently present in the ZennoPoster task list, one summary entry each."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "post": {
        "operationId": "task_create",
        "summary": "Add a task \u2014 imports a project whose code (incl. OwnCode) runs on start (RCE class)",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 3,
        "x-implemented": true,
        "x-required-scope": "task:edit",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "path": {
                    "type": "string",
                    "description": "Absolute path to an existing project file (.zp/.zpproj/.vsproj)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "GUID assigned to the newly imported task; use it to address the task in all other endpoints."
                    },
                    "name": {
                      "type": "string",
                      "description": "Display name of the created task, taken from the imported project."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks/{id}": {
      "get": {
        "operationId": "task_get",
        "summary": "Task info",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "task:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Task GUID."
                    },
                    "name": {
                      "type": "string",
                      "description": "Task display name."
                    },
                    "projectPath": {
                      "type": "string",
                      "description": "Path to the referenced project file."
                    },
                    "isSchedulerOwned": {
                      "type": "boolean",
                      "description": "True when the task is owned by a scheduler job (created via the scheduler wizard): such tasks cannot be deleted or edited directly through the API."
                    },
                    "createTime": {
                      "type": "string",
                      "description": "Task creation time (ISO-8601)."
                    },
                    "settingsType": {
                      "type": "string",
                      "description": "Settings block kind of the referenced project: \u0022BotUI\u0022 | \u0022InputSettings\u0022 | \u0022None\u0022 . GET/PUT /tasks/{id}/config serves BOTH kinds (the unified settings view). Can be empty until the project has been scanned at least once."
                    },
                    "browserType": {
                      "type": "string",
                      "description": "Browser type stored on the task, or null when unset."
                    }
                  },
                  "required": [
                    "isSchedulerOwned"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "delete": {
        "operationId": "task_delete",
        "summary": "Remove a task (interrupts running threads first)",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "task:edit",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "409": {
            "description": "task_scheduler_owned: The task is owned by a scheduler job and cannot be deleted directly."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks/{id}/start": {
      "post": {
        "operationId": "task_start",
        "summary": "Start a task \u2014 executes project code incl. OwnCode (RCE class)",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 3,
        "x-implemented": true,
        "x-required-scope": "task:control",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "description": "Outcome of the control operation: \u0022started\u0022 | \u0022stopped\u0022 | \u0022interrupted\u0022."
                    },
                    "id": {
                      "type": "string",
                      "description": "GUID of the task the operation acted on."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks/{id}/stop": {
      "post": {
        "operationId": "task_stop",
        "summary": "Stop a task",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 2,
        "x-implemented": true,
        "x-required-scope": "task:control",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "description": "Outcome of the control operation: \u0022started\u0022 | \u0022stopped\u0022 | \u0022interrupted\u0022."
                    },
                    "id": {
                      "type": "string",
                      "description": "GUID of the task the operation acted on."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks/{id}/interrupt": {
      "post": {
        "operationId": "task_interrupt",
        "summary": "Interrupt a task",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 2,
        "x-implemented": true,
        "x-required-scope": "task:control",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "description": "Outcome of the control operation: \u0022started\u0022 | \u0022stopped\u0022 | \u0022interrupted\u0022."
                    },
                    "id": {
                      "type": "string",
                      "description": "GUID of the task the operation acted on."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks/{id}/threads/max": {
      "get": {
        "operationId": "task_threads_max_get",
        "summary": "Thread limit (LimitOfThreads)",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "task:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "maxThreads": {
                      "type": "integer",
                      "description": "The task\u0027s thread limit, always \u003E= 1. On PUT this is the value actually applied, re-read after the commit."
                    }
                  },
                  "required": [
                    "maxThreads"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "task_threads_max_set",
        "summary": "Set the thread limit",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "task:edit",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "maxThreads": {
                    "type": "integer",
                    "description": "New thread limit for the task. Must be \u003E= 1; rejected with 400 otherwise."
                  }
                },
                "required": [
                  "maxThreads"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "maxThreads": {
                      "type": "integer",
                      "description": "The task\u0027s thread limit, always \u003E= 1. On PUT this is the value actually applied, re-read after the commit."
                    }
                  },
                  "required": [
                    "maxThreads"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks/{id}/tries": {
      "get": {
        "operationId": "task_tries_get",
        "summary": "Queued tries (NumberOfTries); -1 means the task runs forever",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "task:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tries": {
                      "type": "integer",
                      "description": "The queued-tries counter: \u003E= 0, or -1 when the task runs forever. On PUT this is the value actually applied, re-read after the commit."
                    }
                  },
                  "required": [
                    "tries"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "task_tries_set",
        "summary": "Set tries, or -1 to run forever \u2014 starts a ready task (gated like task_start when it would start)",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "task:edit",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tries": {
                    "type": "integer",
                    "description": "New value for the queued-tries counter. Must be \u003E= 0, or -1 to make the task run forever; anything else is rejected with 400. A task on -1 keeps running until it is stopped, because the counter is never counted down. Setting a non-zero value on a ready task starts it."
                  }
                },
                "required": [
                  "tries"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tries": {
                      "type": "integer",
                      "description": "The queued-tries counter: \u003E= 0, or -1 when the task runs forever. On PUT this is the value actually applied, re-read after the commit."
                    }
                  },
                  "required": [
                    "tries"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks/{id}/tries/add": {
      "post": {
        "operationId": "task_tries_add",
        "summary": "Add tries, or -1 to run forever \u2014 starts a ready task (gated like task_start when it would start)",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "task:edit",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "count": {
                    "type": "integer",
                    "description": "Number of run tries to add to the task\u0027s queue. Must be \u003E= 1, or -1 to make the task run forever; anything else is rejected with 400. Use PUT /tasks/{id}/tries to lower the queue. -1 does not add anything: it switches the task to endless execution, the same as the \u0022Perform infinitely\u0022 button in ZennoPoster. Adding tries to a ready task starts it."
                  }
                },
                "required": [
                  "count"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "totalTries": {
                      "type": "integer",
                      "description": "The queued-tries counter after the add, re-read from the task (actually applied, not an echo). -1 means the task now runs forever."
                    },
                    "addedTries": {
                      "type": "integer",
                      "description": "Number of tries this call added (echoes the request\u0027s count), or -1 when the call switched the task to running forever."
                    }
                  },
                  "required": [
                    "totalTries",
                    "addedTries"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks/{id}/settings/execution": {
      "get": {
        "operationId": "task_execution_get",
        "summary": "Execution settings",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "task:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "limitOfThreads": {
                      "type": "integer",
                      "description": "Thread limit for the task, at least 1."
                    },
                    "numberOfTries": {
                      "type": "integer",
                      "description": "Number of tries to queue: 0 or more, or -1 to run forever. A non-zero value on a ready task starts it \u2014 gated like task_start."
                    },
                    "priority": {
                      "type": "integer",
                      "description": "Priority: 10 low, 50 medium, 100 high, 100000 critical."
                    },
                    "proxy": {
                      "type": "string",
                      "description": "Proxy usage mode, one of: DoNotUseProxy, IfPossible, UseProxyWithoutRemove, UseProxy."
                    },
                    "proxyLabels": {
                      "type": "string",
                      "description": "Comma-separated proxy labels."
                    },
                    "groupLabels": {
                      "type": "string",
                      "description": "Comma-separated group labels."
                    },
                    "maxNumOfSuccessStop": {
                      "type": "integer",
                      "description": "Stop after N successes: -1 = unlimited, otherwise at least 1."
                    },
                    "maxNumOfFailStop": {
                      "type": "integer",
                      "description": "Stop after N consecutive failures: -1 = unlimited, otherwise at least 1."
                    },
                    "timeout": {
                      "type": "integer",
                      "description": "Per-try timeout in minutes: -1 = none, otherwise at least 1."
                    },
                    "traceTask": {
                      "type": "boolean",
                      "description": "Trace the task."
                    },
                    "performBadEndOnInterrupt": {
                      "type": "boolean",
                      "description": "Run the BadEnd branch on project interrupt."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "task_execution_set",
        "summary": "Update execution settings (merge semantics; may start a ready task \u2014 gated like task_start)",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "task:edit",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "limitOfThreads": {
                    "type": "integer",
                    "description": "Thread limit for the task, at least 1."
                  },
                  "numberOfTries": {
                    "type": "integer",
                    "description": "Number of tries to queue: 0 or more, or -1 to run forever. A non-zero value on a ready task starts it \u2014 gated like task_start."
                  },
                  "priority": {
                    "type": "integer",
                    "description": "Priority: 10 low, 50 medium, 100 high, 100000 critical."
                  },
                  "proxy": {
                    "type": "string",
                    "description": "Proxy usage mode, one of: DoNotUseProxy, IfPossible, UseProxyWithoutRemove, UseProxy."
                  },
                  "proxyLabels": {
                    "type": "string",
                    "description": "Comma-separated proxy labels."
                  },
                  "groupLabels": {
                    "type": "string",
                    "description": "Comma-separated group labels."
                  },
                  "maxNumOfSuccessStop": {
                    "type": "integer",
                    "description": "Stop after N successes: -1 = unlimited, otherwise at least 1."
                  },
                  "maxNumOfFailStop": {
                    "type": "integer",
                    "description": "Stop after N consecutive failures: -1 = unlimited, otherwise at least 1."
                  },
                  "timeout": {
                    "type": "integer",
                    "description": "Per-try timeout in minutes: -1 = none, otherwise at least 1."
                  },
                  "traceTask": {
                    "type": "boolean",
                    "description": "Trace the task."
                  },
                  "performBadEndOnInterrupt": {
                    "type": "boolean",
                    "description": "Run the BadEnd branch on project interrupt."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Short outcome word for the operation, e.g. \u0022imported\u0022, \u0022updated\u0022 or \u0022cleared\u0022."
                    },
                    "id": {
                      "type": "string",
                      "description": "GUID of the affected task when the operation targets one; null otherwise."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks/{id}/settings/scheduler": {
      "get": {
        "operationId": "task_scheduler_get",
        "summary": "Scheduler settings",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "task:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "isActive": {
                      "type": "boolean",
                      "description": "Scheduler enabled. Required. Activating the schedule is a deferred start of the project\u0027s code, so isActive:true runs the same content-classification gate as task_start and requires a real executePeriod (400 on NULL)."
                    },
                    "executePeriod": {
                      "type": "string",
                      "description": "Execution period name: OneTime | EveryDay | EveryWeek | EveryMonth | OnDemand | NULL (no schedule). Required."
                    },
                    "daysOfWeek": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Day names for EveryWeek: English day names, \u0022Monday\u0022 \u2026 \u0022Sunday\u0022 (other casings are normalized; unknown names are rejected with 400)."
                    },
                    "daysOfMonth": {
                      "type": "string",
                      "description": "Days of month for EveryMonth, in the scheduler\u0027s human-view form (e.g. \u00221,5,10\u0022)."
                    },
                    "fileName": {
                      "type": "string",
                      "description": "Trigger file path for OnDemand."
                    },
                    "isNeedDeleteFile": {
                      "type": "boolean",
                      "description": "Delete the trigger file after firing, for OnDemand."
                    },
                    "startDateType": {
                      "type": "string",
                      "description": "Start-date type: Immediately | OnDate."
                    },
                    "startDate": {
                      "type": "string",
                      "description": "Start date when StartDateType == OnDate: an invariant-culture date-time string in the MACHINE\u0027S LOCAL TIME, no time zone (e.g. \u002208/30/2026 09:00:00\u0022) \u2014 a deliberate exception to the API-wide absolute-UTC convention, because the scheduler runs on the machine\u0027s clock."
                    },
                    "attemptsRange": {
                      "type": "string",
                      "description": "Attempts per run: \u0022n\u0022 or \u0022a-b\u0022 (SchedulerAttempts.AttemptsRange human view). Required."
                    },
                    "isClearSuccess": {
                      "type": "boolean",
                      "description": "Clear success counter each run. Required."
                    },
                    "intervals": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Time-of-day intervals as \u0022HH:mm-HH:mm\u0022. An end of \u002200:00\u0022 means 24:00 (end of day); a single time (\u002209:30\u0022) is a point interval. Optional."
                    },
                    "stopExecutionOutsideOfIntervals": {
                      "type": "boolean",
                      "description": "Stop execution outside the intervals."
                    },
                    "repeatType": {
                      "type": "string",
                      "description": "Repeat type: Continued | ContinuedWithPause | Regularly | Count."
                    },
                    "repeatCountDayRange": {
                      "type": "string",
                      "description": "Per-day repeat count \u0022n\u0022 or \u0022a-b\u0022; required unless Continued."
                    },
                    "endDateType": {
                      "type": "string",
                      "description": "End-date type: Infinity | OnDate | Count."
                    },
                    "endDate": {
                      "type": "string",
                      "description": "End date when EndDateType == OnDate \u2014 same format and local-time semantics as StartDate."
                    },
                    "repeatCountTotalRange": {
                      "type": "string",
                      "description": "Total repeat count \u0022n\u0022 or \u0022a-b\u0022 when EndDateType == Count."
                    }
                  },
                  "required": [
                    "isActive",
                    "isNeedDeleteFile",
                    "isClearSuccess",
                    "stopExecutionOutsideOfIntervals"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "task_scheduler_set",
        "summary": "Update scheduler settings (activation gated like task_start)",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "task:edit",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "isActive": {
                    "type": "boolean",
                    "description": "Scheduler enabled. Required. Activating the schedule is a deferred start of the project\u0027s code, so isActive:true runs the same content-classification gate as task_start and requires a real executePeriod (400 on NULL)."
                  },
                  "executePeriod": {
                    "type": "string",
                    "description": "Execution period name: OneTime | EveryDay | EveryWeek | EveryMonth | OnDemand | NULL (no schedule). Required."
                  },
                  "daysOfWeek": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Day names for EveryWeek: English day names, \u0022Monday\u0022 \u2026 \u0022Sunday\u0022 (other casings are normalized; unknown names are rejected with 400)."
                  },
                  "daysOfMonth": {
                    "type": "string",
                    "description": "Days of month for EveryMonth, in the scheduler\u0027s human-view form (e.g. \u00221,5,10\u0022)."
                  },
                  "fileName": {
                    "type": "string",
                    "description": "Trigger file path for OnDemand."
                  },
                  "isNeedDeleteFile": {
                    "type": "boolean",
                    "description": "Delete the trigger file after firing, for OnDemand."
                  },
                  "startDateType": {
                    "type": "string",
                    "description": "Start-date type: Immediately | OnDate."
                  },
                  "startDate": {
                    "type": "string",
                    "description": "Start date when StartDateType == OnDate: an invariant-culture date-time string in the MACHINE\u0027S LOCAL TIME, no time zone (e.g. \u002208/30/2026 09:00:00\u0022) \u2014 a deliberate exception to the API-wide absolute-UTC convention, because the scheduler runs on the machine\u0027s clock."
                  },
                  "attemptsRange": {
                    "type": "string",
                    "description": "Attempts per run: \u0022n\u0022 or \u0022a-b\u0022 (SchedulerAttempts.AttemptsRange human view). Required."
                  },
                  "isClearSuccess": {
                    "type": "boolean",
                    "description": "Clear success counter each run. Required."
                  },
                  "intervals": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Time-of-day intervals as \u0022HH:mm-HH:mm\u0022. An end of \u002200:00\u0022 means 24:00 (end of day); a single time (\u002209:30\u0022) is a point interval. Optional."
                  },
                  "stopExecutionOutsideOfIntervals": {
                    "type": "boolean",
                    "description": "Stop execution outside the intervals."
                  },
                  "repeatType": {
                    "type": "string",
                    "description": "Repeat type: Continued | ContinuedWithPause | Regularly | Count."
                  },
                  "repeatCountDayRange": {
                    "type": "string",
                    "description": "Per-day repeat count \u0022n\u0022 or \u0022a-b\u0022; required unless Continued."
                  },
                  "endDateType": {
                    "type": "string",
                    "description": "End-date type: Infinity | OnDate | Count."
                  },
                  "endDate": {
                    "type": "string",
                    "description": "End date when EndDateType == OnDate \u2014 same format and local-time semantics as StartDate."
                  },
                  "repeatCountTotalRange": {
                    "type": "string",
                    "description": "Total repeat count \u0022n\u0022 or \u0022a-b\u0022 when EndDateType == Count."
                  }
                },
                "required": [
                  "isActive",
                  "isNeedDeleteFile",
                  "isClearSuccess",
                  "stopExecutionOutsideOfIntervals"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Short outcome word for the operation, e.g. \u0022imported\u0022, \u0022updated\u0022 or \u0022cleared\u0022."
                    },
                    "id": {
                      "type": "string",
                      "description": "GUID of the affected task when the operation targets one; null otherwise."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks/{id}/success/clear": {
      "post": {
        "operationId": "task_success_clear",
        "summary": "Reset success counter",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "task:edit",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Short outcome word for the operation, e.g. \u0022imported\u0022, \u0022updated\u0022 or \u0022cleared\u0022."
                    },
                    "id": {
                      "type": "string",
                      "description": "GUID of the affected task when the operation targets one; null otherwise."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks/{id}/fails/clear": {
      "post": {
        "operationId": "task_fails_clear",
        "summary": "Reset fail counter",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "task:edit",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "description": "Short outcome word for the operation, e.g. \u0022imported\u0022, \u0022updated\u0022 or \u0022cleared\u0022."
                    },
                    "id": {
                      "type": "string",
                      "description": "GUID of the affected task when the operation targets one; null otherwise."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks/{id}/state": {
      "get": {
        "operationId": "task_state_get",
        "summary": "Runtime state",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "task:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Task GUID."
                    },
                    "status": {
                      "type": "string",
                      "description": "Task status name, one of: Newbie (never ran), Complete, NotComplete, Schedule (waiting for the scheduler), WaitPerform (queued to run), Perform (running), WaitProxy, Stopping, Stop, Fail."
                    },
                    "doneSuccessfully": {
                      "type": "integer",
                      "description": "Successful completions so far."
                    },
                    "doneAll": {
                      "type": "integer",
                      "description": "Total completions so far."
                    },
                    "numberOfTries": {
                      "type": "integer",
                      "description": "Remaining tries queued."
                    },
                    "numOfFailStop": {
                      "type": "integer",
                      "description": "Consecutive failures counter."
                    },
                    "countOfThreads": {
                      "type": "integer",
                      "description": "Currently running threads for the task."
                    },
                    "limitOfThreads": {
                      "type": "integer",
                      "description": "The user-set thread limit \u2014 same value as GET /tasks/{id}/threads/max."
                    },
                    "maxAllowOfThreads": {
                      "type": "integer",
                      "description": "Read-only system thread ceiling: written by the core on every project scan (and by ZennoBox for purchased templates), not settable through the API."
                    },
                    "failurePoints": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "threadId": {
                            "type": "string",
                            "description": "Managed thread id of the worker thread that hit this failure."
                          },
                          "uowId": {
                            "type": "string",
                            "description": "Task attempt id."
                          },
                          "port": {
                            "type": "integer",
                            "description": "Browser instance port, or -1 if no browser instance was involved."
                          },
                          "isHardStop": {
                            "type": "boolean",
                            "description": "True for a hard stop (task-failing error); false for a soft failure where the OnError branch was taken and execution continued."
                          },
                          "actionId": {
                            "type": "string",
                            "description": "Id of the action that failed."
                          },
                          "actionGroupId": {
                            "type": "string",
                            "description": "Id of the action group containing the failed action."
                          },
                          "actionComment": {
                            "type": "string",
                            "description": "User-facing comment/text for the failed action."
                          },
                          "onErrorTargetGroupId": {
                            "type": "string",
                            "description": "Group id of the OnError branch target, if OnError was wired for the failed action."
                          },
                          "onErrorTargetActionId": {
                            "type": "string",
                            "description": "Action id of the OnError branch target, if OnError was wired for the failed action."
                          },
                          "exceptionType": {
                            "type": "string",
                            "description": "CLR exception type name, if the failure was caused by an exception."
                          },
                          "exceptionMessage": {
                            "type": "string",
                            "description": "Exception message, if the failure was caused by an exception."
                          },
                          "projectName": {
                            "type": "string",
                            "description": "Name of the project that was executing when the failure happened."
                          },
                          "timestamp": {
                            "type": "string",
                            "description": "UTC timestamp of the failure, ISO-8601 (\u0022o\u0022)."
                          },
                          "variables": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "name": {
                                  "type": "string",
                                  "description": "Variable name."
                                },
                                "value": {
                                  "type": "string",
                                  "description": "Variable value; redacted for sensitive names, truncated if too long."
                                }
                              }
                            },
                            "description": "Project-level variables at the moment of failure (filtered/truncated)."
                          }
                        },
                        "required": [
                          "port",
                          "isHardStop"
                        ]
                      },
                      "description": "SNAPSHOT of the last observed failure per worker thread/instance (hard stop or soft OnError-continued) \u2014 NOT an event queue: reading is non-destructive and repeated GETs return the same entries. An entry is overwritten in place when its thread fails again (keyed by taskId\u002BthreadId), expires after 2 hours, is capped at 64 entries per task, and is cleared only when the task is deleted. Deduplicate client-side by (threadId, timestamp) or uowId. The variables snapshot inside may contain sensitive values (readable at T0 task:read)."
                    }
                  },
                  "required": [
                    "doneSuccessfully",
                    "doneAll",
                    "numberOfTries",
                    "numOfFailStop",
                    "countOfThreads",
                    "limitOfThreads",
                    "maxAllowOfThreads"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/tasks/{id}/config": {
      "get": {
        "operationId": "task_config_get",
        "summary": "User settings (unified: InputSettings and BotUI)",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "task:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "settings": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "description": "Setting name."
                          },
                          "value": {
                            "type": "string",
                            "description": "Current value."
                          },
                          "variable": {
                            "type": "string",
                            "description": "Bound project variable."
                          }
                        }
                      },
                      "description": "The task\u0027s user settings. On PUT this is a batch merge by setting name: names that match a setting of the task are applied, unknown names are skipped (see InputSettingsApplyResponse)."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "task_config_set",
        "summary": "Update user settings (reports applied/skipped names)",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "task:edit",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "settings": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Setting name."
                        },
                        "value": {
                          "type": "string",
                          "description": "Current value."
                        },
                        "variable": {
                          "type": "string",
                          "description": "Bound project variable."
                        }
                      }
                    },
                    "description": "The task\u0027s user settings. On PUT this is a batch merge by setting name: names that match a setting of the task are applied, unknown names are skipped (see InputSettingsApplyResponse)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "applied": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Setting names (with their resolved variable) that matched and were applied."
                    },
                    "skipped": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Setting names that matched no setting of the task and were skipped."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/sessions": {
      "get": {
        "operationId": "sessions_list",
        "summary": "Open WaitForUserAction windows",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "task:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sessions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "sessionId": {
                            "type": "string",
                            "description": "Opaque session id, minted when the window opens."
                          },
                          "taskId": {
                            "type": "string",
                            "description": "Task GUID the window belongs to."
                          },
                          "projectName": {
                            "type": "string",
                            "description": "Project name of the running task."
                          },
                          "instanceId": {
                            "type": "integer",
                            "description": "Instance port, the id used to address the Instance contract."
                          },
                          "started": {
                            "type": "string",
                            "description": "UTC timestamp (ISO-8601) the window opened."
                          },
                          "prompt": {
                            "type": "string",
                            "description": "Comment the project passed to WaitForUserAction. Empty when none."
                          },
                          "timeoutSeconds": {
                            "type": "integer",
                            "description": "Timeout in seconds set on the action. Zero when there is no timeout."
                          },
                          "deadline": {
                            "type": "string",
                            "description": "UTC timestamp (ISO-8601) when the window expires. Empty when there is no timeout."
                          }
                        },
                        "required": [
                          "instanceId",
                          "timeoutSeconds"
                        ]
                      },
                      "description": "The requested page of open windows, ordered by open time."
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total number of open windows matching the filter, before paging."
                    }
                  },
                  "required": [
                    "total"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/sessions/{id}": {
      "get": {
        "operationId": "session_get",
        "summary": "Window details",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "task:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sessionId": {
                      "type": "string",
                      "description": "Opaque session id, minted when the window opens."
                    },
                    "taskId": {
                      "type": "string",
                      "description": "Task GUID the window belongs to."
                    },
                    "projectName": {
                      "type": "string",
                      "description": "Project name of the running task."
                    },
                    "instanceId": {
                      "type": "integer",
                      "description": "Instance port, the id used to address the Instance contract."
                    },
                    "started": {
                      "type": "string",
                      "description": "UTC timestamp (ISO-8601) the window opened."
                    },
                    "prompt": {
                      "type": "string",
                      "description": "Comment the project passed to WaitForUserAction. Empty when none."
                    },
                    "timeoutSeconds": {
                      "type": "integer",
                      "description": "Timeout in seconds set on the action. Zero when there is no timeout."
                    },
                    "deadline": {
                      "type": "string",
                      "description": "UTC timestamp (ISO-8601) when the window expires. Empty when there is no timeout."
                    }
                  },
                  "required": [
                    "instanceId",
                    "timeoutSeconds"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "session_not_found: No open WaitForUserAction window with this id."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/sessions/events": {
      "get": {
        "operationId": "sessions_events",
        "summary": "Long-poll: window open/close events (?timeoutSeconds=N)",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "task:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "eventType": {
                            "type": "string",
                            "description": "\u0022opened\u0022 when a WaitForUserAction window opened; \u0022closed\u0022 when it closed (completed, timed out, or the task stopped)."
                          },
                          "sessionId": {
                            "type": "string",
                            "description": "Id of the session the event is about."
                          },
                          "taskId": {
                            "type": "string",
                            "description": "Task GUID the window belongs to."
                          },
                          "instanceId": {
                            "type": "integer",
                            "description": "Instance port, the id used to address the Instance contract."
                          },
                          "prompt": {
                            "type": "string",
                            "description": "Comment the project passed to WaitForUserAction. Empty when none."
                          },
                          "deadline": {
                            "type": "string",
                            "description": "UTC timestamp (ISO-8601) when the window expires. Empty when there is no timeout."
                          }
                        },
                        "required": [
                          "instanceId"
                        ]
                      },
                      "description": "Events collected during this poll, oldest first. Empty when the poll timed out."
                    },
                    "timedOut": {
                      "type": "boolean",
                      "description": "True when the timeout elapsed with no events (the events list is empty)."
                    }
                  },
                  "required": [
                    "timedOut"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/sessions/{id}/complete": {
      "post": {
        "operationId": "session_complete",
        "summary": "Complete the action, resume thread (success branch)",
        "tags": [
          "ZennoPoster"
        ],
        "x-risk-tier": 2,
        "x-implemented": true,
        "x-required-scope": "task:control",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "summary": {
                    "type": "string",
                    "description": "Optional free-text summary of what was done, for the audit trail. Does not affect how the thread resumes."
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": {},
                    "description": "Optional arbitrary key/value payload accompanying the completion, for the audit trail. Does not affect how the thread resumes."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sessionId": {
                      "type": "string",
                      "description": "Id of the session that was completed."
                    },
                    "status": {
                      "type": "string",
                      "description": "Always \u0022completed\u0022 \u2014 the only terminal state this endpoint produces."
                    },
                    "threadResumedOn": {
                      "type": "string",
                      "description": "Branch the paused task thread resumed on. Always \u0022success\u0022: there is no fail/cancel branch yet."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "session_not_found: No open WaitForUserAction window with this id."
          },
          "409": {
            "description": "no_active_interaction: The WaitForUserAction window with this id is no longer open."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/instances": {
      "get": {
        "operationId": "instances_list",
        "summary": "List active instances",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "instance:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "instances": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "browserType": {
                            "type": "string",
                            "description": "Browser engine of the instance \u2014 a BrowserType enum name, e.g. \u0022Chromium\u0022 or \u0022Firefox45\u0022."
                          },
                          "id": {
                            "type": "integer",
                            "description": "Port of the browser instance; the single ProjectMaker instance has a real port too."
                          },
                          "profileDir": {
                            "type": "string",
                            "description": "Path to the browser profile the instance runs with."
                          }
                        },
                        "required": [
                          "id"
                        ]
                      },
                      "description": "The running browser instances the host exposes (a single entry on a ProjectMaker host)."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "post": {
        "operationId": "instance_create",
        "summary": "Start/get an instance",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 2,
        "x-implemented": true,
        "x-required-scope": "instance:control",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "browserType": {
                    "type": "string",
                    "description": "Browser engine to launch \u2014 a BrowserType enum name, case-insensitive (e.g. \u0022Chromium\u0022, \u0022Firefox45\u0022). Null/empty falls back to the host default (Chromium); an unrecognized value is rejected with 400."
                  },
                  "browserArgs": {
                    "type": "string",
                    "description": "Extra command-line arguments passed to the browser process. Null/empty for none."
                  },
                  "isolated": {
                    "type": "boolean",
                    "description": "Launch the browser in its own dedicated base process instead of sharing one with other instances \u2014 the same \u0022isolated process\u0022 option a project\u0027s static settings offer. Only Firefox45 can actually share a base process, so this flag matters for Firefox45 alone; every other browser type (Chromium included) is single-instance and gets a dedicated process regardless of this flag. Honored by the ZennoPoster runner; the ProjectMaker host\u0027s singleton editor instance ignores it."
                  },
                  "ownerUowId": {
                    "type": "string",
                    "description": "SERVER-SET: the unit of work the creating caller acts for, taken from the X-Zenno-Uow-Id header by the Instance host (a client-supplied value is overwritten). The ZennoPoster runner records the new browser as owned by this unit of work, so the AI action\u0027s self-started browsers get the same cross-task protection as task browsers; null (no header) leaves the browser unowned, as before."
                  }
                },
                "required": [
                  "isolated"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "browserType": {
                      "type": "string",
                      "description": "Browser engine of the instance \u2014 a BrowserType enum name, e.g. \u0022Chromium\u0022 or \u0022Firefox45\u0022."
                    },
                    "id": {
                      "type": "integer",
                      "description": "Port of the browser instance; the single ProjectMaker instance has a real port too."
                    },
                    "profileDir": {
                      "type": "string",
                      "description": "Path to the browser profile the instance runs with."
                    }
                  },
                  "required": [
                    "id"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/instances/{id}": {
      "get": {
        "operationId": "instance_get",
        "summary": "Instance metadata",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "instance:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "browserType": {
                      "type": "string",
                      "description": "Browser engine of the instance \u2014 a BrowserType enum name, e.g. \u0022Chromium\u0022 or \u0022Firefox45\u0022."
                    },
                    "id": {
                      "type": "integer",
                      "description": "Port of the browser instance; the single ProjectMaker instance has a real port too."
                    },
                    "profileDir": {
                      "type": "string",
                      "description": "Path to the browser profile the instance runs with."
                    }
                  },
                  "required": [
                    "id"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "delete": {
        "operationId": "instance_release",
        "summary": "Release the instance back to the pool (the pool decides restart-vs-close; not a forced close)",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "instance:control",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "409": {
            "description": "instance_busy: The instance is owned by a running task\u0027s worker thread and cannot be released."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/instances/{id}/show": {
      "post": {
        "operationId": "instance_show",
        "summary": "Show the window (409 when the view is protected)",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "instance:control",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "True when the mutation was performed (errors surface as non-2xx ApiError responses instead of false)."
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "409": {
            "description": "instance_view_protected: The browser\u0027s view is protected and no WaitForUserAction window is open."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/instances/{id}/hide": {
      "post": {
        "operationId": "instance_hide",
        "summary": "Hide the window",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "instance:control",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "True when the mutation was performed (errors surface as non-2xx ApiError responses instead of false)."
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/instances/{id}/tabs": {
      "get": {
        "operationId": "tabs_list",
        "summary": "List tabs",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "instance:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tabs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "tabName": {
                            "type": "string",
                            "description": "Display name of the tab."
                          },
                          "tabId": {
                            "type": "integer",
                            "description": "Tab id. 0 is reserved as the \u0022active tab\u0022 sentinel."
                          }
                        },
                        "required": [
                          "tabId"
                        ]
                      },
                      "description": "All open tabs of the instance."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "post": {
        "operationId": "tab_create",
        "summary": "New tab",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "instance:interact",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tabName": {
                    "type": "string",
                    "description": "Name for the new tab."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tabName": {
                      "type": "string",
                      "description": "Display name of the tab."
                    },
                    "tabId": {
                      "type": "integer",
                      "description": "Tab id. 0 is reserved as the \u0022active tab\u0022 sentinel."
                    }
                  },
                  "required": [
                    "tabId"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/instances/{id}/tabs/{tabId}/activate": {
      "post": {
        "operationId": "tab_activate",
        "summary": "Activate tab",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "instance:interact",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tabId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "True when the mutation was performed (errors surface as non-2xx ApiError responses instead of false)."
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/instances/{id}/tabs/{tabId}": {
      "delete": {
        "operationId": "tab_close",
        "summary": "Close tab",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "instance:interact",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tabId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "True when the mutation was performed (errors surface as non-2xx ApiError responses instead of false)."
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/instances/{id}/tabs/{tabId}/navigate": {
      "post": {
        "operationId": "tab_navigate",
        "summary": "Navigate to URL",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "instance:interact",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tabId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "Absolute URL to navigate the tab to."
                  },
                  "timeout": {
                    "type": "integer",
                    "description": "Page-load timeout in seconds applied to this navigation (sets the tab\u0027s NavigateTimeout)."
                  }
                },
                "required": [
                  "timeout"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "True when the mutation was performed (errors surface as non-2xx ApiError responses instead of false)."
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/instances/{id}/tabs/{tabId}/dom": {
      "get": {
        "operationId": "tab_dom_get",
        "summary": "DOM text (tag filter, pagination)",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "instance:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tabId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "content": {
                      "type": "string",
                      "description": "The requested chunk of the (optionally tag-filtered) DOM text, starting at the requested startIndex."
                    },
                    "totalLength": {
                      "type": "integer",
                      "description": "Total length in characters of the full filtered text, across all chunks."
                    },
                    "nextIndex": {
                      "type": "integer",
                      "description": "Offset to pass as startIndex on the next call, or null if there is no more content."
                    },
                    "isTruncated": {
                      "type": "boolean",
                      "description": "True when more content remains after this chunk \u2014 continue from NextIndex."
                    }
                  },
                  "required": [
                    "totalLength",
                    "isTruncated"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "409": {
            "description": "dom_unavailable: DOM text could not be retrieved right now (e.g. the page is navigating)."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/instances/{id}/tabs/{tabId}/elements/attribute": {
      "get": {
        "operationId": "element_attribute_get",
        "summary": "Get attribute by XPath",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "instance:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tabId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "value": {
                      "type": "string",
                      "description": "Current value of the requested attribute; null when the element has no such attribute."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "put": {
        "operationId": "element_attribute_set",
        "summary": "Set attribute by XPath",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "instance:interact",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tabId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "xPath": {
                    "type": "string",
                    "description": "XPath selecting the target element."
                  },
                  "attributeName": {
                    "type": "string",
                    "description": "Attribute to set. \u0022value\u0022 (case-insensitive) is special: the text is typed via real keyboard emulation, firing trusted keydown/input/change events and interpreting tokens like {ENTER}; any other attribute is set directly on the element."
                  },
                  "attributeValue": {
                    "type": "string",
                    "description": "Value to assign \u2014 the text to type, when the attribute is \u0022value\u0022."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "True when the mutation was performed (errors surface as non-2xx ApiError responses instead of false)."
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/instances/{id}/tabs/{tabId}/elements/event": {
      "post": {
        "operationId": "element_event",
        "summary": "Raise a DOM event (click/input/submit/...)",
        "tags": [
          "Instance"
        ],
        "x-risk-tier": 1,
        "x-implemented": true,
        "x-required-scope": "instance:interact",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tabId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "xPath": {
                    "type": "string",
                    "description": "XPath selecting the target element."
                  },
                  "eventName": {
                    "type": "string",
                    "description": "DOM event to raise on the element, e.g. \u0022click\u0022, \u0022input\u0022, \u0022change\u0022. A click additionally requires the element to be actually rendered (visible, non-zero size)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "True when the mutation was performed (errors surface as non-2xx ApiError responses instead of false)."
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/android/devices": {
      "get": {
        "operationId": "devices_list",
        "summary": "List the devices this process drives",
        "tags": [
          "Android"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "instance:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "devices": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "description": "Device id on the wire \u2014 the UI port used by the device instance window."
                          },
                          "name": {
                            "type": "string",
                            "description": "Device name that uniquely identifies the device, e.g. \u0022emulator-5554\u0022 or the phone\u0027s serial."
                          },
                          "title": {
                            "type": "string",
                            "description": "Display title of the device as shown in Device Manager."
                          },
                          "isRunning": {
                            "type": "boolean",
                            "description": "True when the device is ready for work: the screen is being captured and the device is started and connected (emulator) or connected (real phone)."
                          }
                        },
                        "required": [
                          "id",
                          "isRunning"
                        ]
                      },
                      "description": "The devices this process drives (a single entry on a ProjectMaker host)."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/android/devices/{id}/start": {
      "post": {
        "operationId": "device_start",
        "summary": "Start/attach the device and wait until it is ready",
        "tags": [
          "Android"
        ],
        "x-risk-tier": 2,
        "x-implemented": true,
        "x-required-scope": "instance:control",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "description": "True when the device came up and is ready for work."
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/android/devices/{id}": {
      "get": {
        "operationId": "device_get",
        "summary": "Device metadata (id, name, running state)",
        "tags": [
          "Android"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "instance:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer",
                      "description": "Device id on the wire \u2014 the UI port used by the device instance window."
                    },
                    "name": {
                      "type": "string",
                      "description": "Device name that uniquely identifies the device, e.g. \u0022emulator-5554\u0022 or the phone\u0027s serial."
                    },
                    "title": {
                      "type": "string",
                      "description": "Display title of the device as shown in Device Manager."
                    },
                    "isRunning": {
                      "type": "boolean",
                      "description": "True when the device is ready for work: the screen is being captured and the device is started and connected (emulator) or connected (real phone)."
                    }
                  },
                  "required": [
                    "id",
                    "isRunning"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/android/devices/{id}/screen": {
      "get": {
        "operationId": "device_screen_get",
        "summary": "Real screen resolution in pixels",
        "tags": [
          "Android"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "instance:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "width": {
                      "type": "integer",
                      "description": "Screen width in physical pixels."
                    },
                    "height": {
                      "type": "integer",
                      "description": "Screen height in physical pixels."
                    }
                  },
                  "required": [
                    "width",
                    "height"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/android/devices/{id}/source": {
      "get": {
        "operationId": "device_source_get",
        "summary": "Current UI tree (raw page source)",
        "tags": [
          "Android"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "instance:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "source": {
                      "type": "string",
                      "description": "Raw XML page source; empty when the device exposes none right now."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/android/devices/{id}/apps": {
      "get": {
        "operationId": "device_apps_get",
        "summary": "Applications installed on the device",
        "tags": [
          "Android"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "instance:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "applications": {
                      "type": "string",
                      "description": "Driver-reported application listing, verbatim."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/auth/keys": {
      "post": {
        "operationId": "auth_keys_create",
        "summary": "Issue an ApiKey (raw key shown once)",
        "tags": [
          "CrossCutting"
        ],
        "x-risk-tier": 3,
        "x-implemented": true,
        "x-required-scope": "admin",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string",
                    "description": "Optional human-readable label to identify the key in listings and the UI."
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Scopes to grant, e.g. \u0022task:read\u0022, \u0022project:edit\u0022, \u0022instance:interact\u0022 (see the ApiScope constants). A request exceeding the host\u0027s policy ceiling is rejected with 403 policy_violation."
                  },
                  "maxTier": {
                    "type": "string",
                    "enum": [
                      "T0",
                      "T1",
                      "T2",
                      "T3"
                    ],
                    "description": "Highest risk tier the key may invoke: T0 (read) .. T3 (host/RCE). Defaults to T0."
                  },
                  "expiresAt": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Absolute expiry (ISO-8601 with offset on the wire); null = non-expiring. A value in the past is rejected with 400."
                  }
                },
                "required": [
                  "maxTier"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Stable key id used to address the key in later calls (list/revoke/enable); not a secret."
                    },
                    "label": {
                      "type": "string",
                      "description": "Human-readable label copied from the issue request; null when none was given."
                    },
                    "rawKey": {
                      "type": "string",
                      "description": "The secret API key itself. Returned only in this response \u2014 it is not stored and cannot be retrieved again."
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Scopes granted to the key, e.g. \u0022task:read\u0022 (see the ApiScope constants)."
                    },
                    "maxTier": {
                      "type": "string",
                      "enum": [
                        "T0",
                        "T1",
                        "T2",
                        "T3"
                      ],
                      "description": "Highest risk tier the key may invoke: T0 (read) .. T3 (host/RCE)."
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Absolute expiry of the key; null for a non-expiring key."
                    },
                    "enabled": {
                      "type": "boolean",
                      "description": "True when the key can authenticate; a freshly issued key is always enabled."
                    }
                  },
                  "required": [
                    "maxTier",
                    "enabled"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      },
      "get": {
        "operationId": "auth_keys_list",
        "summary": "List keys (no raw key)",
        "tags": [
          "CrossCutting"
        ],
        "x-risk-tier": 3,
        "x-implemented": true,
        "x-required-scope": "admin",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "Stable key id used to address the key (revoke/enable); not a secret."
                      },
                      "label": {
                        "type": "string",
                        "description": "Human-readable label given at issue time; null when none was given."
                      },
                      "scopes": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "Scopes granted to the key, e.g. \u0022task:read\u0022 (see the ApiScope constants)."
                      },
                      "maxTier": {
                        "type": "string",
                        "enum": [
                          "T0",
                          "T1",
                          "T2",
                          "T3"
                        ],
                        "description": "Highest risk tier the key may invoke: T0 (read) .. T3 (host/RCE)."
                      },
                      "expiresAt": {
                        "type": "string",
                        "format": "date-time",
                        "description": "Absolute expiry of the key; null for a non-expiring key."
                      },
                      "enabled": {
                        "type": "boolean",
                        "description": "False when the key has been disabled: it fails authentication but stays listed until revoked."
                      },
                      "createdAt": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the key was issued."
                      },
                      "lastUsedAt": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the key last authenticated a request; null if never used. Best-effort display statistic."
                      },
                      "usageCount": {
                        "type": "integer",
                        "description": "Number of requests the key has authenticated. Best-effort display statistic (concurrent hosts may under-count)."
                      },
                      "systemProvisioned": {
                        "type": "boolean",
                        "description": "True for keys the host auto-provisioned for its own built-in MCP servers \u2014 the user never created them, and the \u0022My keys\u0022 UI hides them. GET /auth/keys labels them explicitly and can exclude them with ?includeSystemProvisioned=false."
                      },
                      "status": {
                        "type": "string",
                        "description": "Effective key state at listing time: \u0022active\u0022 | \u0022expired\u0022 | \u0022disabled\u0022. An expired or disabled key fails authentication but stays listed until it is revoked (revoke removes the record physically)."
                      }
                    },
                    "required": [
                      "maxTier",
                      "enabled",
                      "createdAt",
                      "usageCount",
                      "systemProvisioned"
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/auth/keys/{id}": {
      "delete": {
        "operationId": "auth_keys_revoke",
        "summary": "Revoke a key (immediate)",
        "tags": [
          "CrossCutting"
        ],
        "x-risk-tier": 3,
        "x-implemented": true,
        "x-required-scope": "admin",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "404": {
            "description": "not_found: The referenced resource (task/instance/tab/element/key) does not exist."
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/auth/whoami": {
      "get": {
        "operationId": "auth_whoami",
        "summary": "Scopes/tier of the current key",
        "tags": [
          "CrossCutting"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keyId": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "maxTier": {
                      "type": "integer"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "maxTier"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/audit": {
      "get": {
        "operationId": "audit_get",
        "summary": "Audit log of calls",
        "tags": [
          "CrossCutting"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "x-required-scope": "admin",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "timestamp": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the call was handled (UTC)."
                      },
                      "keyId": {
                        "type": "string",
                        "description": "Id of the calling key, or null when the call was unauthenticated (401)."
                      },
                      "keyLabel": {
                        "type": "string",
                        "description": "Human label of the calling key (never the token), or null."
                      },
                      "method": {
                        "type": "string",
                        "description": "HTTP method, e.g. POST."
                      },
                      "path": {
                        "type": "string",
                        "description": "Request path, e.g. /api/v1/auth/keys."
                      },
                      "statusCode": {
                        "type": "integer",
                        "description": "Resulting HTTP status code (200/204/401/403/\u2026)."
                      },
                      "tier": {
                        "type": "integer",
                        "description": "Risk tier of the operation (0..3)."
                      },
                      "requiredScope": {
                        "type": "string",
                        "description": "Scope the operation required, or null if none."
                      },
                      "durationMs": {
                        "type": "integer",
                        "description": "How long the call took to handle, in milliseconds."
                      }
                    },
                    "required": [
                      "timestamp",
                      "statusCode",
                      "tier",
                      "durationMs"
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "403": {
            "description": "Missing scope or tier exceeded"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/capabilities": {
      "get": {
        "operationId": "capabilities",
        "summary": "Manifest: operations, tiers, required scopes",
        "tags": [
          "CrossCutting"
        ],
        "x-risk-tier": 0,
        "x-implemented": true,
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "host": {
                      "type": "string",
                      "description": "Host identity, e.g. \u0022projectmaker\u0022 / \u0022zennoposter\u0022."
                    },
                    "version": {
                      "type": "string",
                      "description": "Semantic version of the contract this host serves."
                    },
                    "productVersion": {
                      "type": "string",
                      "description": "Version of the product serving this API, e.g. \u00227.9.2.0\u0022. Empty when the host does not report one \u2014 read that as unknown, not as old."
                    },
                    "currentScopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Scopes granted to the current key."
                    },
                    "currentMaxTier": {
                      "type": "integer",
                      "description": "Highest tier the current key may invoke (0..3)."
                    },
                    "operations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "operationId": {
                            "type": "string",
                            "description": "Stable operation identifier from the catalog, snake_case (e.g. \u0022task_list\u0022, \u0022session_complete\u0022)."
                          },
                          "method": {
                            "type": "string",
                            "description": "Uppercase HTTP verb (GET/POST/PUT/DELETE)."
                          },
                          "path": {
                            "type": "string",
                            "description": "Full path including the version prefix, e.g. /api/v1/sessions/{id}/complete."
                          },
                          "tier": {
                            "type": "integer",
                            "description": "Numeric tier (0..3)."
                          },
                          "requiredScope": {
                            "type": "string",
                            "description": "Required scope, or null for open operations."
                          },
                          "isAvailable": {
                            "type": "boolean",
                            "description": "True when the current key may invoke this operation on this host right now."
                          },
                          "unavailableReason": {
                            "type": "string",
                            "description": "Machine-readable reason the operation is unavailable, or null when it is available. Lets a client tell \u0022my key is not allowed\u0022 from \u0022this host has no such thing right now\u0022 without probing for 403/409. See CapabilityUnavailableReasons."
                          }
                        },
                        "required": [
                          "tier",
                          "isAvailable"
                        ]
                      },
                      "description": "Every operation of the host\u0027s domains, one entry each \u2014 including operations the current key cannot invoke (their isAvailable is false)."
                    },
                    "tierLegend": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string"
                      },
                      "description": "Static legend of the tier taxonomy for client display."
                    }
                  },
                  "required": [
                    "currentMaxTier"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/confirmations": {
      "get": {
        "operationId": "confirmations_list",
        "summary": "Pending HITL confirmations",
        "tags": [
          "CrossCutting"
        ],
        "x-risk-tier": 0,
        "x-implemented": false,
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/confirmations/{id}/approve": {
      "post": {
        "operationId": "confirmation_approve",
        "summary": "Approve an operation (UI only)",
        "tags": [
          "CrossCutting"
        ],
        "x-risk-tier": 0,
        "x-implemented": false,
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    },
    "/api/v1/confirmations/{id}/reject": {
      "post": {
        "operationId": "confirmation_reject",
        "summary": "Reject an operation (UI only)",
        "tags": [
          "CrossCutting"
        ],
        "x-risk-tier": 0,
        "x-implemented": false,
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "Bad request"
          },
          "401": {
            "description": "Missing or invalid key"
          },
          "500": {
            "description": "Internal error"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Opaque ApiKey: Authorization: Bearer \u003Capi-key\u003E"
      }
    }
  }
}