{
  "openapi": "3.1.0",
  "info": {
    "title": "TestArmy API",
    "version": "1.0.0",
    "description": "AI-powered browser automation API for QA testing. Automate web testing workflows using natural language prompts."
  },
  "servers": [
    {
      "url": "https://tester.army/api",
      "description": "Production API server"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API Key",
        "description": "API key authentication using Bearer token format. The CLI's `ta auth` access tokens are also accepted; because they name a user rather than a workspace, a user in several workspaces selects one with the `x-testerarmy-team` header (workspace id or slug)."
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Error code or type"
          },
          "message": {
            "type": "string",
            "description": "Human-readable error message"
          }
        },
        "required": ["error", "message"]
      },
      "ProjectDetail": {
        "type": "object",
        "properties": {
          "browserRegion": {
            "type": ["string", "null"],
            "enum": ["us", "us-dynamic", "eu", "pl", null],
            "description": "Default exit region for web runs. null uses the default, us (static IPs). us-dynamic exits from a US IP that usually changes between runs. Web projects only."
          },
          "prTestingEnabled": {
            "type": "boolean",
            "description": "Test PR deployments automatically."
          },
          "prTestingInstructions": {
            "type": ["string", "null"],
            "maxLength": 2000,
            "description": "Free-form instructions for the PR exploration agent."
          },
          "agentInstructions": {
            "type": ["string", "null"],
            "maxLength": 4000,
            "description": "Free-form instructions injected into the QA agent's system prompt on every run of this project."
          },
          "prTestingDebounceMinutes": {
            "type": "integer",
            "minimum": 0,
            "maximum": 60,
            "description": "Quiet period before a PR deployment is tested. 0 disables debouncing."
          },
          "prTestingBlockMerge": {
            "type": "boolean",
            "description": "Conclude the GitHub check run as failed when tests fail, so a required TesterArmy check blocks the merge. Off by default."
          },
          "includeExampleMobileApp": {
            "type": "boolean",
            "description": "Offer the example app as a run target. Mobile projects only."
          },
          "autoDeleteOldestMobileApp": {
            "type": "boolean",
            "description": "Delete the oldest unused app builds when an upload exceeds the storage quota. Mobile projects only."
          },
          "accessibilityAuditEnabled": {
            "type": "boolean",
            "description": "Scan visited pages with axe-core during web runs and report critical accessibility violations as non-blocking warnings. On by default. Web projects only."
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "shortId": {
            "type": ["string", "null"]
          },
          "name": {
            "type": "string"
          },
          "url": {
            "type": ["string", "null"]
          },
          "projectType": {
            "type": "string",
            "enum": ["web", "mobile"]
          },
          "description": {
            "type": ["string", "null"]
          },
          "environments": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "name": {
                  "type": "string"
                },
                "slug": {
                  "type": "string"
                },
                "kind": {
                  "type": "string",
                  "enum": ["production", "pr_preview", "static"]
                },
                "url": {
                  "type": ["string", "null"]
                }
              },
              "required": ["id", "name", "slug", "kind", "url"]
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "shortId", "name", "url", "projectType", "description", "environments"]
      },
      "DynamicPrRunRequest": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "targetUrl": {
                "type": "string",
                "format": "uri"
              },
              "platform": {
                "type": "string",
                "enum": ["web"]
              },
              "pullRequest": {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": ["github"],
                    "default": "github"
                  },
                  "number": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 65536
                  },
                  "baseBranch": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "headBranch": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "commitSha": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  }
                },
                "required": ["number", "title", "commitSha"],
                "additionalProperties": false
              }
            },
            "required": ["targetUrl", "pullRequest"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "platform": {
                "type": "string",
                "enum": ["ios", "android"]
              },
              "pullRequest": {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "enum": ["github"],
                    "default": "github"
                  },
                  "number": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 65536
                  },
                  "baseBranch": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "headBranch": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "commitSha": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  }
                },
                "required": ["number", "title", "commitSha"],
                "additionalProperties": false
              },
              "mobile": {
                "type": "object",
                "properties": {
                  "appId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "bundleId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "artifactUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "artifactFilename": {
                    "type": "string",
                    "minLength": 1
                  },
                  "buildId": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "additionalProperties": false
              },
              "simulatorRegion": {
                "type": "string",
                "enum": ["eu-north1", "us-west1"]
              },
              "deeplink": {
                "type": "string",
                "maxLength": 2048,
                "format": "uri",
                "description": "Deep link the test harness opens on the device after launching the app and before any test step runs (e.g. an Expo update-channel or backend-selection link). Applied deterministically; the QA agent is told the setup is already done."
              }
            },
            "required": ["platform", "pullRequest"],
            "additionalProperties": false
          }
        ]
      },
      "DiscoveryRunResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["queued"]
          },
          "runId": {
            "type": "string",
            "format": "uuid"
          },
          "projectId": {
            "type": "string",
            "format": "uuid"
          },
          "platform": {
            "type": "string",
            "enum": ["web", "ios", "android"]
          }
        },
        "required": ["status", "runId", "projectId", "platform"]
      },
      "DiscoveryRunRequest": {
        "type": "object",
        "properties": {
          "goal": {
            "type": "string",
            "minLength": 8,
            "maxLength": 2000,
            "description": "The exploration goal for the free-roam QA agent, e.g. \"Explore the checkout flow and find bugs\". The agent decides what to test; there is no predefined step list."
          },
          "targetUrl": {
            "type": "string",
            "format": "uri",
            "description": "Optional URL to explore instead of the project's production URL. Web only."
          },
          "platform": {
            "type": "string",
            "enum": ["web", "ios", "android"],
            "description": "Target platform; defaults to web. Mobile platforms explore the uploaded app."
          },
          "appId": {
            "type": "string",
            "description": "Uploaded mobile app ID to explore. Defaults to the project's latest app for the platform."
          },
          "deviceModel": {
            "type": "string",
            "enum": ["iphone", "ipad"],
            "description": "Mobile device variant within the platform (e.g. ipad on iOS). Omit for the default phone-sized device."
          }
        },
        "required": ["goal"],
        "additionalProperties": false
      },
      "ProjectEnvironment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": ["production", "pr_preview", "static"]
          },
          "url": {
            "type": ["string", "null"]
          }
        },
        "required": ["id", "name", "slug", "kind", "url"]
      },
      "CredentialSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": ["login", "inbox"]
          },
          "authMethod": {
            "type": "string",
            "enum": ["password", "google", "github", "custom"]
          },
          "label": {
            "type": "string"
          },
          "description": {
            "type": ["string", "null"]
          },
          "username": {
            "type": "string"
          },
          "hasAuthInstructions": {
            "type": "boolean"
          },
          "hasTotpSecret": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "kind",
          "authMethod",
          "label",
          "description",
          "username",
          "hasAuthInstructions",
          "hasTotpSecret",
          "createdAt"
        ]
      },
      "ProjectMemory": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "category": {
            "type": "string",
            "enum": ["site_structure", "test_insights", "user_preferences"]
          },
          "title": {
            "type": "string"
          },
          "content": {
            "type": "string"
          },
          "importance": {
            "type": "string",
            "enum": ["high", "medium", "low"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "category", "title", "content", "importance", "createdAt", "updatedAt"]
      },
      "ProjectIssue": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "projectId": {
            "type": "string",
            "format": "uuid"
          },
          "testId": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": ["open", "resolved", "false_positive"],
            "description": "Triage status. Resolved issues reopen automatically if a run surfaces them again."
          },
          "issueType": {
            "type": "string",
            "enum": ["issue", "warning"]
          },
          "source": {
            "type": "string",
            "enum": ["agent_report", "step_failure"],
            "description": "How the tracker learned about the issue: an explicit agent report or a failed test step."
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "url": {
            "type": ["string", "null"]
          },
          "severity": {
            "type": ["integer", "null"],
            "description": "1 (low) to 5 (critical), when reported."
          },
          "category": {
            "type": ["string", "null"]
          },
          "reproductionSteps": {
            "type": ["array", "null"],
            "items": {
              "type": "string"
            }
          },
          "expectedBehavior": {
            "type": ["string", "null"]
          },
          "actualBehavior": {
            "type": ["string", "null"]
          },
          "screenshotUrl": {
            "type": ["string", "null"]
          },
          "environment": {
            "type": "string",
            "enum": ["production", "staging", "preview", "custom"],
            "description": "Deployment bucket the issue is tracked on."
          },
          "environmentName": {
            "type": "string",
            "description": "Resolved environment label (\"Production\", \"Staging\", \"QA EU\", ...). Issues are tracked per environment: the same bug on different environments is separate issues."
          },
          "occurrenceCount": {
            "type": "integer",
            "description": "Number of runs that surfaced this issue."
          },
          "firstSeenRunId": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "lastSeenRunId": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "lastSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "resolvedAt": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "projectId",
          "testId",
          "status",
          "issueType",
          "source",
          "name",
          "description",
          "url",
          "severity",
          "category",
          "reproductionSteps",
          "expectedBehavior",
          "actualBehavior",
          "screenshotUrl",
          "environment",
          "environmentName",
          "occurrenceCount",
          "firstSeenRunId",
          "lastSeenRunId",
          "lastSeenAt",
          "resolvedAt",
          "createdAt",
          "updatedAt"
        ]
      },
      "ProjectIssueOccurrence": {
        "type": "object",
        "properties": {
          "runId": {
            "type": "string",
            "format": "uuid"
          },
          "runTitle": {
            "type": ["string", "null"]
          },
          "tMs": {
            "type": ["integer", "null"],
            "description": "Recording offset (ms) when the issue was reported in that run."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["runId", "runTitle", "tMs", "createdAt"]
      },
      "ProjectFileSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "projectId": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "filename": {
            "type": "string"
          },
          "mediaType": {
            "type": "string"
          },
          "fileSize": {
            "type": "integer"
          },
          "description": {
            "type": ["string", "null"]
          },
          "summary": {
            "type": ["string", "null"]
          },
          "createdAt": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "projectId",
          "filename",
          "mediaType",
          "fileSize",
          "description",
          "summary",
          "createdAt"
        ]
      },
      "TestDefinition": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": ["string", "null"]
          },
          "enabled": {
            "type": "boolean"
          },
          "platform": {
            "type": "string",
            "enum": ["web", "mobile"]
          },
          "settings": {
            "$ref": "#/components/schemas/TestSettings"
          },
          "steps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TestStep"
            }
          },
          "projectId": {
            "type": "string",
            "format": "uuid"
          },
          "projectUrl": {
            "type": ["string", "null"],
            "format": "uri"
          },
          "projectName": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["id", "title", "steps"]
      },
      "TestSettings": {
        "type": "object",
        "properties": {
          "executionMode": {
            "type": "string",
            "enum": ["fast", "deep"],
            "description": "Deprecated and ignored. Deep mode was removed; every run uses the same mode."
          },
          "browserRegion": {
            "type": ["string", "null"],
            "enum": ["us", "us-dynamic", "eu", "pl", null],
            "description": "Per-test proxy exit region. null falls back to the project's region."
          },
          "simulatorRegion": {
            "type": "string",
            "enum": ["eu-north1", "us-west1"],
            "description": "Region the simulator or emulator runs in. Mobile tests only."
          },
          "viewport": {
            "type": ["string", "null"],
            "enum": ["desktop", "desktop-hd", "mobile", "tablet", null],
            "description": "Browser viewport preset: desktop (1280x800), desktop-hd (1920x1080), mobile (390x844), tablet (768x1024). null restores the default. Web tests only."
          },
          "webSearchEnabled": {
            "type": "boolean",
            "description": "Allow the test to use internet search for factual checks."
          },
          "prepGroupId": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "Group whose preparation test a solo run of this test uses."
          }
        }
      },
      "TestStep": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1,
                "maxLength": 2000,
                "description": "Action to perform. Reference a project file for upload by writing @ followed by its exact filename (e.g. @receipt.jpg); the run resolves it by name."
              },
              "type": {
                "type": "string",
                "enum": ["act"]
              },
              "disabled": {
                "type": "boolean",
                "description": "When true, the step stays saved on the test but is skipped during runs."
              }
            },
            "required": ["title", "type"]
          },
          {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1,
                "maxLength": 2000
              },
              "type": {
                "type": "string",
                "enum": ["assert"]
              },
              "disabled": {
                "type": "boolean",
                "description": "When true, the step stays saved on the test but is skipped during runs."
              }
            },
            "required": ["title", "type"]
          },
          {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "maxLength": 2000
              },
              "type": {
                "type": "string",
                "enum": ["login"]
              },
              "credentialId": {
                "type": "string",
                "format": "uuid"
              },
              "temporaryEmail": {
                "type": "boolean"
              },
              "disabled": {
                "type": "boolean",
                "description": "When true, the step stays saved on the test but is skipped during runs."
              }
            },
            "required": ["title", "type"]
          },
          {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "maxLength": 2000
              },
              "type": {
                "type": "string",
                "enum": ["files"]
              },
              "fileIds": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "disabled": {
                "type": "boolean",
                "description": "When true, the step stays saved on the test but is skipped during runs."
              }
            },
            "required": ["title", "type", "fileIds"]
          },
          {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "maxLength": 2000
              },
              "type": {
                "type": "string",
                "enum": ["screenshot"]
              },
              "disabled": {
                "type": "boolean",
                "description": "When true, the step stays saved on the test but is skipped during runs."
              }
            },
            "required": ["type"]
          },
          {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "maxLength": 2000
              },
              "type": {
                "type": "string",
                "enum": ["javascript"]
              },
              "code": {
                "type": "string",
                "maxLength": 10000,
                "description": "JavaScript run in the browser page. Runs as an awaited function body; passes unless it throws or returns { success: false, reason }; any other return value, including diagnostic data, counts as a pass. Web tests only."
              },
              "disabled": {
                "type": "boolean",
                "description": "When true, the step stays saved on the test but is skipped during runs."
              }
            },
            "required": ["type", "code"]
          },
          {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "maxLength": 2000
              },
              "type": {
                "type": "string",
                "enum": ["microphone"]
              },
              "fileId": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "uuid"
                  },
                  {
                    "type": "string",
                    "enum": [""]
                  }
                ],
                "description": "Project file ID (UUID) of the audio file (e.g. MP3) to play through the microphone. Empty string marks an unconfigured draft that must have a file attached before the test runs."
              },
              "mode": {
                "type": "string",
                "enum": ["blocking", "loop"],
                "description": "blocking: the agent waits for playback to finish before continuing. loop: playback repeats until the run ends and the agent continues immediately. Web tests only."
              },
              "disabled": {
                "type": "boolean",
                "description": "When true, the step stays saved on the test but is skipped during runs."
              }
            },
            "required": ["type", "fileId", "mode"]
          }
        ]
      },
      "TestDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/TestDefinition"
          },
          {
            "type": "object",
            "properties": {
              "groups": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "name": {
                      "type": "string"
                    },
                    "isDefault": {
                      "type": "boolean"
                    }
                  },
                  "required": ["id", "name", "isDefault"]
                }
              }
            }
          }
        ]
      },
      "GroupDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "isDefault": {
            "type": "boolean"
          },
          "runMode": {
            "type": "string",
            "enum": ["concurrent", "sequential"]
          },
          "maxConcurrentRuns": {
            "type": ["integer", "null"],
            "minimum": 1,
            "description": "Concurrent groups only: max tests executing at once per group run. Capped at your team's concurrent-run limit; null follows the plan limit."
          },
          "prepTestId": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "projectId": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "isDefault",
          "runMode",
          "maxConcurrentRuns",
          "prepTestId",
          "projectId"
        ]
      },
      "GroupSchedule": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "groupId": {
            "type": "string",
            "format": "uuid"
          },
          "projectId": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "frequency": {
            "type": "string",
            "enum": ["every_1h", "every_3h", "every_6h", "every_12h", "daily", "weekly", "custom"]
          },
          "minute": {
            "type": "integer",
            "minimum": 0,
            "maximum": 59
          },
          "hour": {
            "type": ["integer", "null"],
            "minimum": 0,
            "maximum": 23
          },
          "dayOfWeek": {
            "type": ["integer", "null"],
            "minimum": 0,
            "maximum": 6
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone the cron is evaluated in."
          },
          "cronExpression": {
            "type": "string",
            "description": "The 5-field cron the scheduler runs, derived from the preset or given as custom."
          },
          "projectEnvironmentId": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "Saved environment the schedule runs against; null runs Production."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "groupId",
          "projectId",
          "name",
          "frequency",
          "minute",
          "hour",
          "dayOfWeek",
          "timezone",
          "cronExpression",
          "projectEnvironmentId",
          "createdAt",
          "updatedAt"
        ]
      },
      "GroupScheduleRequest": {
        "type": "object",
        "properties": {
          "frequency": {
            "type": "string",
            "enum": ["every_1h", "every_3h", "every_6h", "every_12h", "daily", "weekly", "custom"],
            "description": "Preset cadence. The interval presets take `minute`; `daily` adds `hour`; `weekly` adds `hour` and `dayOfWeek`; `custom` takes `cronExpression`."
          },
          "minute": {
            "type": "integer",
            "minimum": 0,
            "maximum": 59,
            "default": 0,
            "description": "Minute of the hour (0-59). Defaults to 0. Ignored for custom."
          },
          "hour": {
            "type": "integer",
            "minimum": 0,
            "maximum": 23,
            "description": "Hour of the day (0-23) in `timezone`. Required for daily and weekly."
          },
          "dayOfWeek": {
            "type": "integer",
            "minimum": 0,
            "maximum": 6,
            "description": "0 = Sunday through 6 = Saturday. Required for weekly."
          },
          "cronExpression": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Standard 5-field cron (minute hour day-of-month month day-of-week), e.g. \"*/30 * * * *\" for every 30 minutes. Seconds are not supported. Required for custom."
          },
          "timezone": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "default": "UTC",
            "description": "IANA timezone the schedule is evaluated in, e.g. \"Europe/Warsaw\". Defaults to UTC."
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "description": "Display name shown in the dashboard."
          },
          "projectEnvironmentId": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "Saved environment the schedule runs against, from the project's environments. Omit or pass null for Production. PR Preview cannot be scheduled."
          }
        },
        "required": ["frequency"],
        "additionalProperties": false
      },
      "RunListResponse": {
        "type": "object",
        "properties": {
          "runs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RunResponse"
            },
            "description": "List of runs"
          },
          "nextCursor": {
            "type": ["string", "null"],
            "description": "Cursor for fetching the next page"
          }
        },
        "required": ["runs"]
      },
      "RunResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique run identifier"
          },
          "type": {
            "type": "string",
            "enum": ["ci", "test", "discovery"],
            "description": "Run type"
          },
          "status": {
            "type": "string",
            "enum": ["queued", "running", "completed", "failed", "cancelled"],
            "description": "Current run status"
          },
          "platform": {
            "type": ["string", "null"],
            "enum": ["web", "ios", "android", null],
            "description": "Target platform"
          },
          "deviceModel": {
            "type": ["string", "null"],
            "enum": ["iphone", "ipad", null],
            "description": "Mobile device the run used (iOS: iphone | ipad). Null for web runs and platforms without device variants."
          },
          "source": {
            "type": ["string", "null"],
            "enum": [
              "api",
              "github_action",
              "github_app",
              "scheduled",
              "webhook",
              "structured_test",
              null
            ],
            "description": "Run source"
          },
          "projectId": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "Linked project ID"
          },
          "input": {
            "type": "object",
            "additionalProperties": {},
            "description": "Original request input"
          },
          "output": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TestOutput"
              },
              {
                "$ref": "#/components/schemas/PlannerSkippedOutput"
              },
              {
                "type": "null"
              }
            ],
            "description": "Run output when completed or skipped"
          },
          "testPlan": {
            "type": ["object", "null"],
            "properties": {
              "instructions": {
                "type": "string",
                "description": "Natural language instructions for the QA agent"
              },
              "focusAreas": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Focus areas derived from changed files"
              },
              "complexity": {
                "type": "string",
                "enum": ["simple", "moderate", "complex"],
                "description": "Estimated test complexity (affects timeout)"
              },
              "changeType": {
                "type": "string",
                "enum": ["frontend", "backend", "mixed", "infra"],
                "description": "Classify this PR: frontend = UI/component changes, backend = API/DB/service changes with no visible UI effect, mixed = both, infra = CI/config/docs only"
              },
              "steps": {
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "properties": {
                        "title": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 500,
                          "description": "Concise description of what to do or verify"
                        },
                        "type": {
                          "type": "string",
                          "enum": ["act"],
                          "description": "Perform an action"
                        }
                      },
                      "required": ["title", "type"]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "title": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 500,
                          "description": "Concise description of what to do or verify"
                        },
                        "type": {
                          "type": "string",
                          "enum": ["assert"],
                          "description": "Verify a condition"
                        }
                      },
                      "required": ["title", "type"]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "title": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 500,
                          "description": "Concise description of the login step"
                        },
                        "type": {
                          "type": "string",
                          "enum": ["login"],
                          "description": "Authenticate using a credential"
                        },
                        "credentialId": {
                          "type": "string",
                          "description": "ID of the credential to use"
                        },
                        "temporaryEmail": {
                          "type": "boolean",
                          "description": "Set to true to create a temporary email inbox at run time"
                        }
                      },
                      "required": ["title", "type"]
                    },
                    {
                      "type": "object",
                      "properties": {
                        "title": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 500,
                          "description": "Description of what page state to capture"
                        },
                        "type": {
                          "type": "string",
                          "enum": ["screenshot"],
                          "description": "Capture visual evidence of the current page state"
                        }
                      },
                      "required": ["title", "type"]
                    }
                  ]
                },
                "minItems": 1,
                "maxItems": 10,
                "description": "Ordered list of concrete test steps the agent must execute one-by-one"
              },
              "executionConfig": {
                "type": "object",
                "properties": {
                  "viewport": {
                    "type": "object",
                    "properties": {
                      "width": {
                        "type": "integer",
                        "minimum": 320,
                        "maximum": 3840
                      },
                      "height": {
                        "type": "integer",
                        "minimum": 240,
                        "maximum": 2160
                      }
                    },
                    "required": ["width", "height"]
                  }
                },
                "description": "Pre-run execution configuration selected by the planner."
              }
            },
            "required": ["instructions", "focusAreas", "complexity", "changeType", "steps"],
            "description": "Generated test plan (CI runs only)"
          },
          "error": {
            "type": ["object", "null"],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable error code"
              },
              "message": {
                "type": "string",
                "description": "Human-readable error message"
              },
              "stage": {
                "type": "string",
                "description": "Run lifecycle stage where the error occurred (e.g. provider_acquisition)"
              },
              "retryable": {
                "type": "boolean",
                "description": "Whether re-running the test could succeed without changes"
              }
            },
            "required": ["code", "message"],
            "description": "Error details when failed"
          },
          "durationMs": {
            "type": ["number", "null"],
            "description": "Execution time in milliseconds"
          },
          "webhookUrl": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "Webhook delivery URL"
          },
          "webhookStatus": {
            "type": ["string", "null"],
            "enum": ["pending", "delivered", "failed", null],
            "description": "Webhook delivery status"
          },
          "testId": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "Linked test ID"
          },
          "stepResults": {
            "type": ["array", "null"],
            "items": {
              "$ref": "#/components/schemas/StepResult"
            },
            "description": "Step-level results for structured test runs"
          },
          "userName": {
            "type": ["string", "null"],
            "description": "Display name of the user who triggered the run"
          },
          "externalRef": {
            "type": ["object", "null"],
            "additionalProperties": {},
            "description": "External integration metadata (e.g. GitHub PR/deployment IDs)"
          },
          "executionMode": {
            "type": ["string", "null"],
            "enum": ["fast", "deep", null],
            "description": "Execution mode used for this run"
          },
          "autoRetryCount": {
            "type": ["integer", "null"],
            "description": "Number of times the run was automatically retried after a temporary failure. Failed attempts are not counted toward usage."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the run was created"
          },
          "startedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "When execution started"
          },
          "completedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "When execution finished"
          }
        },
        "required": ["id", "type", "status", "input", "createdAt"]
      },
      "TestOutput": {
        "type": "object",
        "properties": {
          "featureName": {
            "type": "string",
            "description": "Name of the feature being tested"
          },
          "result": {
            "type": "string",
            "enum": ["PASS", "FAILED", "BLOCKED"],
            "description": "Test result - PASS if no issues found, FAILED if any issues were reported, BLOCKED if an environment/setup problem or an automation limitation prevented a product verdict"
          },
          "blockedReason": {
            "$ref": "#/components/schemas/BlockedReason"
          },
          "description": {
            "type": "string",
            "description": "Short summary of what was tested and the final result; include a compact grouped issue summary only when the user explicitly asks for one"
          },
          "issues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Issue"
            },
            "default": [],
            "description": "Issues reported during the session via the report_issue tool"
          },
          "screenshots": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Array of screenshot URLs captured during testing"
          },
          "steps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TestOutputStep"
            },
            "description": "Per-step summaries with timing information"
          },
          "uiActionIntervals": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UiActionInterval"
            },
            "description": "Recording-time windows when the agent was visibly acting on screen (clicks, typing, scrolling, navigation); used by replay smart speed"
          },
          "recording": {
            "type": "object",
            "properties": {
              "storageKey": {
                "type": "string",
                "description": "Internal storage key of the recording artifact"
              },
              "fileName": {
                "type": "string",
                "description": "Recording file name"
              },
              "mediaType": {
                "type": "string",
                "description": "Recording media type (video/mp4)"
              }
            },
            "required": ["storageKey", "fileName", "mediaType"],
            "description": "Pointer to the run's video recording artifact, present on completed runs that captured a recording. The bytes are not fetchable through the public API; use the dashboard or a share link to view the recording."
          }
        },
        "required": ["featureName", "result", "description", "screenshots"]
      },
      "BlockedReason": {
        "type": "object",
        "properties": {
          "category": {
            "type": "string",
            "enum": ["environment", "seed_data", "credentials", "test_setup", "automation"],
            "description": "Why the run was blocked: an environment/setup problem or an automation limitation"
          },
          "summary": {
            "type": "string",
            "description": "Plain-language explanation of what blocked the run"
          },
          "errorCodes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "AUTH_CREDENTIAL_UNAVAILABLE",
                "AUTH_CREDENTIAL_INVALID",
                "AUTH_BASIC_REQUIRED",
                "VERCEL_BYPASS_REQUIRED",
                "ENVIRONMENT_UNAVAILABLE",
                "SEED_DATA_MISSING",
                "MOBILE_RELEASE_BUILD_REQUIRED",
                "VIEWPORT_RESIZE_UNSUPPORTED",
                "PROJECT_FILE_MISSING",
                "AUTOMATION_CAPABILITY_UNSUPPORTED",
                "STEP_TOOL_LIMIT_EXHAUSTED",
                "STEP_DEADLINE_EXHAUSTED",
                "STEP_NO_CONCLUSION"
              ]
            },
            "description": "Step error codes that produced the blocked verdict"
          }
        },
        "required": ["category", "summary", "errorCodes"],
        "description": "Structured explanation, present only when result is BLOCKED"
      },
      "Issue": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["issue", "warning"],
            "default": "issue",
            "description": "issue = confirmed bug, warning = non-blocking observation"
          },
          "name": {
            "type": "string",
            "description": "Short name of the issue (e.g. 'Login form rejects valid email')"
          },
          "description": {
            "type": "string",
            "description": "What was tested, what happened, and what was expected"
          },
          "url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "description": "Where the issue happened: the exact page URL on web, or the app identifier and screen on mobile (e.g. com.example.app/login)"
          },
          "severity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5,
            "description": "Issue severity from 1 (minor) to 5 (critical)"
          },
          "reproductionSteps": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Short reproduction steps in execution order"
          },
          "expectedBehavior": {
            "type": "string",
            "description": "What should have happened"
          },
          "actualBehavior": {
            "type": "string",
            "description": "What actually happened"
          },
          "screenshotUrl": {
            "type": "string",
            "description": "Screenshot URL showing the issue"
          },
          "tMs": {
            "type": "integer",
            "description": "Milliseconds elapsed since the recording reference time when the issue was reported"
          },
          "accessibility": {
            "$ref": "#/components/schemas/IssueAccessibilityDetail"
          }
        },
        "required": ["name", "description", "url"]
      },
      "IssueAccessibilityDetail": {
        "type": "object",
        "properties": {
          "ruleId": {
            "type": "string",
            "description": "axe-core rule id, e.g. image-alt"
          },
          "impact": {
            "type": "string",
            "enum": ["minor", "moderate", "serious", "critical"]
          },
          "helpUrl": {
            "type": "string",
            "description": "Deque University fix-guidance URL"
          },
          "wcagTags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "axe rule tags (wcag2a, wcag21aa, ...)"
          },
          "nodeCount": {
            "type": "integer",
            "minimum": 0,
            "description": "Total failing nodes across pages"
          },
          "pageCount": {
            "type": "integer",
            "minimum": 0,
            "description": "Total distinct pages where the rule failed; `urls` is a bounded sample"
          },
          "urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Pages where the rule failed (bounded sample)"
          },
          "sampleTargets": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "CSS selector paths to example failing elements (bounded sample)"
          }
        },
        "required": [
          "ruleId",
          "impact",
          "helpUrl",
          "wcagTags",
          "nodeCount",
          "urls",
          "sampleTargets"
        ],
        "description": "Structured detail present on warnings produced by the automated axe-core accessibility audit"
      },
      "TestOutputStep": {
        "type": "object",
        "properties": {
          "stepIndex": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": ["act", "assert", "login", "files", "screenshot", "javascript", "microphone"]
          },
          "status": {
            "type": "string",
            "enum": ["passed", "failed"]
          },
          "summary": {
            "type": "string"
          },
          "error": {
            "type": ["string", "null"]
          },
          "errorCode": {
            "type": "string",
            "enum": [
              "AUTH_CREDENTIAL_UNAVAILABLE",
              "AUTH_CREDENTIAL_INVALID",
              "AUTH_BASIC_REQUIRED",
              "VERCEL_BYPASS_REQUIRED",
              "ENVIRONMENT_UNAVAILABLE",
              "SEED_DATA_MISSING",
              "MOBILE_RELEASE_BUILD_REQUIRED",
              "VIEWPORT_RESIZE_UNSUPPORTED",
              "PROJECT_FILE_MISSING",
              "AUTOMATION_CAPABILITY_UNSUPPORTED",
              "STEP_TOOL_LIMIT_EXHAUSTED",
              "STEP_DEADLINE_EXHAUSTED",
              "STEP_NO_CONCLUSION"
            ]
          },
          "startedAtMs": {
            "type": "integer",
            "description": "Milliseconds elapsed since recording reference when the step started"
          },
          "completedAtMs": {
            "type": "integer",
            "description": "Milliseconds elapsed since recording reference when the step completed"
          },
          "reusableActionTrace": {
            "$ref": "#/components/schemas/ReusableActionTrace"
          }
        },
        "required": ["stepIndex", "title", "status"]
      },
      "ReusableActionTrace": {
        "type": "object",
        "properties": {
          "version": {
            "type": "number",
            "enum": [1]
          },
          "stepKey": {
            "type": "string",
            "maxLength": 160
          },
          "stepTitle": {
            "type": "string",
            "maxLength": 200
          },
          "stepType": {
            "type": "string",
            "enum": ["act", "assert", "login", "files", "screenshot", "javascript", "microphone"]
          },
          "actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReusableActionStep"
            },
            "minItems": 1,
            "maxItems": 50
          },
          "truncated": {
            "type": "boolean",
            "description": "Actions were dropped at a cap; the trace is guidance-only, never replayable"
          },
          "startPath": {
            "type": "string",
            "maxLength": 300,
            "description": "Pathname where the step began at record time"
          },
          "startScreen": {
            "type": "string",
            "maxLength": 120,
            "description": "Mobile: app under test (bundle id / package name) when the step began"
          },
          "startScreenSignature": {
            "type": "string",
            "maxLength": 32,
            "description": "Mobile: hashed structural signature of the starting screen (shadow data in v1)"
          },
          "confidence": {
            "type": "string",
            "enum": ["medium", "high"]
          }
        },
        "required": ["version", "stepKey", "stepTitle", "actions", "confidence"]
      },
      "ReusableActionStep": {
        "type": "object",
        "properties": {
          "order": {
            "type": "integer",
            "minimum": 0
          },
          "toolName": {
            "type": "string",
            "maxLength": 64
          },
          "summary": {
            "type": "string",
            "maxLength": 300
          },
          "gap": {
            "type": "boolean",
            "description": "Placeholder for a tool the recorder saw run but did not capture (tool name only, no payload) - e.g. a file upload or a failed state-changing attempt. Gaps keep the trace honest about what actually happened: during cached replay, read-only gaps are skipped and state-changing gaps stop the replay so the agent performs that part live instead of it being silently skipped"
          },
          "navigated": {
            "type": "boolean",
            "description": "The action changed the page URL at record time; replay keeps its full settle pipeline"
          },
          "target": {
            "$ref": "#/components/schemas/ReusableActionTarget"
          },
          "source": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ReusableActionTarget"
              },
              {
                "description": "Drag-and-drop source endpoint, when the action has two targets"
              }
            ]
          },
          "input": {
            "type": "object",
            "properties": {
              "url": {
                "type": "string",
                "maxLength": 300
              },
              "field": {
                "type": "string",
                "enum": ["username", "password", "totp"]
              },
              "option": {
                "type": "string",
                "maxLength": 120
              },
              "key": {
                "type": "string",
                "maxLength": 60
              },
              "direction": {
                "type": "string",
                "enum": ["up", "down", "left", "right"]
              },
              "amount": {
                "type": "integer"
              },
              "deltaX": {
                "type": "number"
              },
              "deltaY": {
                "type": "number"
              },
              "targetPosition": {
                "type": "string",
                "enum": ["center", "top", "bottom", "left", "right"]
              },
              "fromEdge": {
                "type": "boolean"
              },
              "focused": {
                "type": "boolean"
              },
              "sequentially": {
                "type": "boolean"
              },
              "text": {
                "type": "string",
                "maxLength": 140
              },
              "assertion": {
                "type": "string",
                "maxLength": 300
              },
              "role": {
                "type": "string",
                "maxLength": 60
              },
              "name": {
                "type": "string",
                "maxLength": 120
              },
              "durationMs": {
                "type": "integer",
                "exclusiveMinimum": 0
              },
              "latitude": {
                "type": "number"
              },
              "longitude": {
                "type": "number"
              },
              "state": {
                "type": "string",
                "enum": ["offline", "online"]
              }
            }
          }
        },
        "required": ["order", "toolName", "summary"]
      },
      "ReusableActionTarget": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": ["role", "css", "vision", "focused", "none", "mobile"]
          },
          "role": {
            "type": "string",
            "maxLength": 60
          },
          "name": {
            "type": "string",
            "maxLength": 120
          },
          "nth": {
            "type": "integer",
            "minimum": 0
          },
          "selector": {
            "type": "string",
            "maxLength": 240
          },
          "element": {
            "type": "string",
            "maxLength": 140
          },
          "type": {
            "type": "string",
            "maxLength": 80,
            "description": "Mobile: raw platform element class (XCUIElementTypeButton, android.widget.Button)"
          },
          "identifier": {
            "type": "string",
            "maxLength": 120,
            "description": "Mobile: platform identifier when the app sets one (AXUniqueId / resource-id)"
          },
          "label": {
            "type": "string",
            "maxLength": 120,
            "description": "Mobile: stable accessible label (labels mirroring a typed value are excluded)"
          },
          "matchCount": {
            "type": "integer",
            "minimum": 0,
            "description": "Mobile: same-signature match count at record time; relocation rejects when the live count differs"
          }
        },
        "required": ["kind"]
      },
      "UiActionInterval": {
        "type": "object",
        "properties": {
          "startMs": {
            "type": "integer",
            "minimum": 0,
            "description": "Milliseconds elapsed since the recording reference time when the action began"
          },
          "endMs": {
            "type": "integer",
            "minimum": 0,
            "description": "Milliseconds elapsed since the recording reference time when the action finished"
          },
          "kind": {
            "type": "string",
            "enum": ["click", "type", "scroll", "navigate", "other"],
            "description": "Coarse action category; absent on runs recorded before kinds were tracked"
          }
        },
        "required": ["startMs", "endMs"]
      },
      "PlannerSkippedOutput": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": ["planner_skipped"]
          },
          "reason": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2000
          }
        },
        "required": ["kind", "reason"]
      },
      "StepResult": {
        "type": "object",
        "properties": {
          "stepIndex": {
            "type": "integer",
            "description": "Zero-based index of the saved test step"
          },
          "status": {
            "type": "string",
            "enum": ["pending", "running", "passed", "failed", "skipped", "cancelled"],
            "description": "Step execution status"
          },
          "startedAt": {
            "type": ["string", "null"],
            "description": "ISO timestamp when the step started"
          },
          "completedAt": {
            "type": ["string", "null"],
            "description": "ISO timestamp when the step completed"
          },
          "error": {
            "type": ["string", "null"],
            "description": "Human-readable step failure description"
          },
          "errorCode": {
            "type": ["string", "null"],
            "enum": [
              "AUTH_CREDENTIAL_UNAVAILABLE",
              "AUTH_CREDENTIAL_INVALID",
              "AUTH_BASIC_REQUIRED",
              "VERCEL_BYPASS_REQUIRED",
              "ENVIRONMENT_UNAVAILABLE",
              "SEED_DATA_MISSING",
              "MOBILE_RELEASE_BUILD_REQUIRED",
              "VIEWPORT_RESIZE_UNSUPPORTED",
              "PROJECT_FILE_MISSING",
              "AUTOMATION_CAPABILITY_UNSUPPORTED",
              "STEP_TOOL_LIMIT_EXHAUSTED",
              "STEP_DEADLINE_EXHAUSTED",
              "STEP_NO_CONCLUSION",
              null
            ],
            "description": "Machine-readable step failure code"
          },
          "summary": {
            "type": ["string", "null"],
            "description": "Agent summary of what happened"
          },
          "retried": {
            "type": "boolean",
            "description": "Whether the step was retried"
          },
          "startedAtMs": {
            "type": ["integer", "null"],
            "description": "Milliseconds elapsed since recording reference when the step started"
          },
          "completedAtMs": {
            "type": ["integer", "null"],
            "description": "Milliseconds elapsed since recording reference when the step completed"
          }
        },
        "required": ["stepIndex", "status", "startedAt", "completedAt", "error", "retried"]
      },
      "RunMessagesResponse": {
        "type": "object",
        "properties": {
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RunMessage"
            },
            "description": "Full agent transcript ordered by creation time"
          }
        },
        "required": ["messages"]
      },
      "RunMessage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Message ID"
          },
          "role": {
            "type": "string",
            "enum": ["user", "assistant"],
            "description": "Message author"
          },
          "parts": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/RunMessageTextPart"
                },
                {
                  "$ref": "#/components/schemas/RunMessageToolPart"
                }
              ]
            },
            "description": "Ordered transcript parts: `text`/`reasoning` entries carry what the agent said, `tool` entries carry each tool call with its input and output."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was recorded"
          }
        },
        "required": ["id", "role", "parts", "createdAt"]
      },
      "RunMessageTextPart": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["text", "reasoning"],
            "description": "What the agent said or reasoned"
          },
          "text": {
            "type": "string",
            "description": "Agent text"
          }
        },
        "required": ["type", "text"]
      },
      "RunMessageToolPart": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["tool"]
          },
          "toolName": {
            "type": "string",
            "description": "Tool the agent called (e.g. ui_navigate, ui_click)"
          },
          "status": {
            "type": "string",
            "enum": ["completed", "error", "pending"],
            "description": "Tool call outcome; absent on redacted calls"
          },
          "summary": {
            "type": "string",
            "description": "One-line human-readable description of what the tool call did; read these in order to follow the run without parsing raw payloads"
          },
          "input": {
            "description": "Tool call input"
          },
          "output": {
            "description": "Tool call output when the call completed"
          },
          "errorText": {
            "type": "string",
            "description": "Failure description when the call errored"
          },
          "redacted": {
            "type": "boolean",
            "description": "True when a credential-bearing tool call was redacted"
          }
        },
        "required": ["type", "toolName"]
      },
      "RunTelemetryResponse": {
        "type": "object",
        "properties": {
          "version": {
            "type": "number",
            "enum": [1],
            "description": "Telemetry payload schema version"
          },
          "console": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RunTelemetryConsoleEntry"
            },
            "description": "Browser console entries (web) or app log lines (mobile) in capture order"
          },
          "network": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RunTelemetryNetworkEntry"
            },
            "description": "Network requests in capture order (document, fetch, and XHR prioritized)"
          },
          "counts": {
            "type": "object",
            "properties": {
              "console": {
                "type": "integer",
                "description": "Console entries captured"
              },
              "network": {
                "type": "integer",
                "description": "Network entries captured"
              },
              "droppedConsole": {
                "type": "integer",
                "description": "Console entries dropped after the buffer cap"
              },
              "droppedNetwork": {
                "type": "integer",
                "description": "Network entries dropped after the buffer cap"
              }
            },
            "required": ["console", "network", "droppedConsole", "droppedNetwork"],
            "description": "Capture counts including entries dropped by ring-buffer limits"
          }
        },
        "required": ["version", "console", "network", "counts"]
      },
      "RunTelemetryConsoleEntry": {
        "type": "object",
        "properties": {
          "seq": {
            "type": "integer",
            "description": "Monotonic sequence number across console and network entries"
          },
          "ts": {
            "type": "string",
            "description": "ISO timestamp of the entry"
          },
          "type": {
            "type": "string",
            "enum": ["console_log", "console_error"],
            "description": "Entry kind"
          },
          "level": {
            "type": "string",
            "description": "Console level (log, info, warning, error, debug, ...)"
          },
          "text": {
            "type": "string",
            "description": "Console message text"
          },
          "args": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Stringified console arguments"
          },
          "url": {
            "type": "string",
            "description": "Page URL when the entry was emitted"
          },
          "sourceUrl": {
            "type": "string",
            "description": "Script URL that emitted the entry"
          },
          "line": {
            "type": "integer"
          },
          "column": {
            "type": "integer"
          },
          "stack": {
            "type": "string",
            "description": "Stack trace for errors"
          }
        },
        "required": ["seq", "ts", "type", "level", "text"]
      },
      "RunTelemetryNetworkEntry": {
        "type": "object",
        "properties": {
          "seq": {
            "type": "integer",
            "description": "Monotonic sequence number across console and network entries"
          },
          "ts": {
            "type": "string",
            "description": "ISO timestamp of the request"
          },
          "requestId": {
            "type": "string",
            "description": "Browser request identifier"
          },
          "url": {
            "type": "string",
            "description": "Request URL (credential query params redacted)"
          },
          "method": {
            "type": "string",
            "description": "HTTP method"
          },
          "resourceType": {
            "type": "string",
            "description": "Browser resource type (document, fetch, xhr, ...)"
          },
          "status": {
            "type": "integer",
            "description": "HTTP response status"
          },
          "statusText": {
            "type": "string"
          },
          "mimeType": {
            "type": "string"
          },
          "durationMs": {
            "type": "number",
            "description": "Request duration in milliseconds"
          },
          "requestHeaders": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Allowlisted request headers"
          },
          "responseHeaders": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Allowlisted response headers"
          },
          "requestBody": {
            "type": "string",
            "description": "JSON request body preview with secrets redacted (fetch/XHR only, truncated)"
          },
          "responseBody": {
            "type": "string",
            "description": "JSON response body preview with secrets redacted (fetch/XHR only, truncated)"
          },
          "failure": {
            "type": "object",
            "properties": {
              "errorText": {
                "type": "string"
              },
              "canceled": {
                "type": "boolean"
              }
            },
            "description": "Present when the request failed before receiving a response"
          }
        },
        "required": ["seq", "ts", "requestId", "url"]
      },
      "BatchStatusResponse": {
        "type": "object",
        "properties": {
          "batchId": {
            "type": "string",
            "format": "uuid",
            "description": "Batch ID"
          },
          "status": {
            "type": "string",
            "enum": ["queued", "running", "completed", "failed", "cancelled"],
            "description": "Aggregate batch status: running while any run is in flight, failed when any finished run failed, completed when all finished runs passed, cancelled when every run was cancelled"
          },
          "counts": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer",
                "minimum": 0
              },
              "queued": {
                "type": "integer",
                "minimum": 0
              },
              "running": {
                "type": "integer",
                "minimum": 0
              },
              "completed": {
                "type": "integer",
                "minimum": 0
              },
              "failed": {
                "type": "integer",
                "minimum": 0
              },
              "cancelled": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": ["total", "queued", "running", "completed", "failed", "cancelled"],
            "description": "Run counts by status"
          },
          "runs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BatchStatusRun"
            },
            "description": "Child runs ordered by creation time"
          }
        },
        "required": ["batchId", "status", "counts", "runs"]
      },
      "BatchStatusRun": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Run ID"
          },
          "testId": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "Saved test the run executed"
          },
          "status": {
            "type": "string",
            "enum": ["queued", "running", "completed", "failed", "cancelled"],
            "description": "Run status"
          },
          "result": {
            "type": ["string", "null"],
            "enum": ["PASS", "FAILED", "BLOCKED", null],
            "description": "Test verdict when the run finished with an output. BLOCKED means an environment or setup problem prevented a product verdict"
          },
          "errorCode": {
            "type": ["string", "null"],
            "description": "Run error code when execution failed"
          },
          "durationMs": {
            "type": ["integer", "null"],
            "description": "Execution time in milliseconds"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the run was created"
          },
          "startedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "When execution started"
          },
          "completedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "When execution finished"
          }
        },
        "required": [
          "id",
          "testId",
          "status",
          "result",
          "errorCode",
          "durationMs",
          "createdAt",
          "startedAt",
          "completedAt"
        ]
      }
    },
    "parameters": {}
  },
  "paths": {
    "/v1/me": {
      "get": {
        "summary": "Get the current user",
        "description": "The authenticated user and the workspaces the credential can act on. An API key lists only its own workspace. Works before a workspace is chosen, so `teamId` is null for a user-scoped token that names none while the user belongs to several.",
        "tags": ["Account"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Workspace id or slug to act on, for user-scoped tokens."
            },
            "required": false,
            "description": "Workspace id or slug to act on, for user-scoped tokens.",
            "name": "x-testerarmy-team",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "The current user and their workspaces",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "email": {
                          "type": "string"
                        },
                        "name": {
                          "type": ["string", "null"]
                        }
                      },
                      "required": ["id", "email", "name"]
                    },
                    "teamId": {
                      "type": ["string", "null"],
                      "format": "uuid"
                    },
                    "teams": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "name": {
                            "type": "string"
                          },
                          "slug": {
                            "type": ["string", "null"]
                          },
                          "role": {
                            "type": "string"
                          }
                        },
                        "required": ["id", "name", "slug", "role"]
                      }
                    }
                  },
                  "required": ["user", "teamId", "teams"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects": {
      "get": {
        "summary": "List projects",
        "description": "List projects available to the authenticated API key's team.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of projects",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projects": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "shortId": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "url": {
                            "type": ["string", "null"],
                            "format": "uri"
                          },
                          "projectType": {
                            "type": "string",
                            "enum": ["web", "mobile"]
                          },
                          "environments": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string",
                                  "format": "uuid"
                                },
                                "name": {
                                  "type": "string"
                                },
                                "slug": {
                                  "type": "string"
                                },
                                "kind": {
                                  "type": "string",
                                  "enum": ["production", "pr_preview", "static"]
                                },
                                "url": {
                                  "type": ["string", "null"]
                                }
                              },
                              "required": ["id", "name", "slug", "kind", "url"]
                            }
                          }
                        },
                        "required": ["id", "shortId", "name", "url", "projectType"]
                      }
                    }
                  },
                  "required": ["projects"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a project",
        "description": "Create a project for the authenticated API key's team.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "url": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500,
                    "description": "Required for web projects; optional for mobile projects."
                  },
                  "projectType": {
                    "type": "string",
                    "enum": ["web", "mobile"]
                  },
                  "description": {
                    "type": ["string", "null"],
                    "maxLength": 2000
                  }
                },
                "required": ["name"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Project created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "$ref": "#/components/schemas/ProjectDetail"
                    }
                  },
                  "required": ["project"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "403": {
            "description": "Project limit exceeded for the current plan",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    },
                    "currentCount": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "limit": {
                      "type": "integer",
                      "minimum": 0
                    }
                  },
                  "required": ["error", "message", "currentCount", "limit"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}": {
      "get": {
        "summary": "Get a project",
        "description": "Get a single project by ID or shortId.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Project details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectDetail"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update a project",
        "description": "Update project name, URL, description, or settings.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID"
            },
            "required": true,
            "description": "Project ID",
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "browserRegion": {
                    "type": ["string", "null"],
                    "enum": ["us", "us-dynamic", "eu", "pl", null],
                    "description": "Default exit region for web runs. null uses the default, us (static IPs). us-dynamic exits from a US IP that usually changes between runs. Web projects only."
                  },
                  "prTestingEnabled": {
                    "type": "boolean",
                    "description": "Test PR deployments automatically."
                  },
                  "prTestingInstructions": {
                    "type": ["string", "null"],
                    "maxLength": 2000,
                    "description": "Free-form instructions for the PR exploration agent."
                  },
                  "agentInstructions": {
                    "type": ["string", "null"],
                    "maxLength": 4000,
                    "description": "Free-form instructions injected into the QA agent's system prompt on every run of this project."
                  },
                  "prTestingDebounceMinutes": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 60,
                    "description": "Quiet period before a PR deployment is tested. 0 disables debouncing."
                  },
                  "prTestingBlockMerge": {
                    "type": "boolean",
                    "description": "Conclude the GitHub check run as failed when tests fail, so a required TesterArmy check blocks the merge. Off by default."
                  },
                  "includeExampleMobileApp": {
                    "type": "boolean",
                    "description": "Offer the example app as a run target. Mobile projects only."
                  },
                  "autoDeleteOldestMobileApp": {
                    "type": "boolean",
                    "description": "Delete the oldest unused app builds when an upload exceeds the storage quota. Mobile projects only."
                  },
                  "accessibilityAuditEnabled": {
                    "type": "boolean",
                    "description": "Scan visited pages with axe-core during web runs and report critical accessibility violations as non-blocking warnings. On by default. Web projects only."
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "url": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "description": {
                    "type": ["string", "null"],
                    "maxLength": 2000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Project updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "$ref": "#/components/schemas/ProjectDetail"
                    }
                  },
                  "required": ["project"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a project",
        "description": "Delete a project. Cascades to groups, tests, runs, and associated artifacts.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID"
            },
            "required": true,
            "description": "Project ID",
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Project deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean",
                      "enum": [true]
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "required": ["deleted", "id"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/pull-request-runs": {
      "post": {
        "summary": "Trigger a pull request exploration run",
        "description": "Trigger the PR exploration agent from CI using PR metadata. Callers do not send changed files; TesterArmy enriches with changed files and GitHub reporting only when the project has a supported GitHub connection.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DynamicPrRunRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Dynamic PR run queued successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": ["queued", "skipped"],
                      "description": "\"skipped\" means the PR skip judge decided the changes cannot affect this platform; a cancelled audit run records the decision and no test executes."
                    },
                    "runId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "projectId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "platform": {
                      "type": "string",
                      "enum": ["web", "ios", "android"]
                    },
                    "skipReason": {
                      "type": "string",
                      "description": "Present only when status is \"skipped\"."
                    },
                    "metadata": {
                      "type": "object",
                      "properties": {
                        "github": {
                          "type": "object",
                          "properties": {
                            "configured": {
                              "type": "boolean"
                            },
                            "checkRunCreated": {
                              "type": "boolean"
                            },
                            "commentTargetResolved": {
                              "type": "boolean"
                            },
                            "status": {
                              "type": "string",
                              "enum": ["not_configured", "check_create_failed", "pr_not_found"]
                            }
                          },
                          "required": ["configured", "checkRunCreated", "commentTargetResolved"]
                        },
                        "mobile": {
                          "type": "object",
                          "properties": {
                            "source": {
                              "type": "string"
                            },
                            "buildId": {
                              "type": "string"
                            }
                          },
                          "required": ["source"]
                        }
                      }
                    }
                  },
                  "required": ["status", "runId", "projectId", "platform"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "413": {
            "description": "Request body too large",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/discovery-runs": {
      "post": {
        "summary": "Trigger a discovery run",
        "description": "Queue a free-roam discovery run: the QA agent gets only a goal, decides what to test itself, and reports every bug it finds. Supports web, iOS, and Android; mobile platforms explore the uploaded app. FAILED means bugs were found.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DiscoveryRunRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Discovery run queued successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiscoveryRunResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "413": {
            "description": "Request body too large",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/environments": {
      "get": {
        "summary": "List project environments",
        "description": "List all run environments for a project, including built-in Production and PR Preview plus static environments.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "List of project environments",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "environments": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProjectEnvironment"
                      }
                    }
                  },
                  "required": ["environments"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a project environment",
        "description": "Create a static project environment with a stable HTTPS URL. Built-in Production and PR Preview environments are managed by TesterArmy.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "url": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  }
                },
                "required": ["name", "url"],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Project environment created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "environment": {
                      "$ref": "#/components/schemas/ProjectEnvironment"
                    }
                  },
                  "required": ["environment"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "409": {
            "description": "Environment name conflicts with an existing environment",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/environments/{environmentId}": {
      "delete": {
        "summary": "Delete a project environment",
        "description": "Delete a static project environment. Built-in Production and PR Preview environments are not deletable.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Static environment ID"
            },
            "required": true,
            "description": "Static environment ID",
            "name": "environmentId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Project environment deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean",
                      "enum": [true]
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "required": ["deleted", "id"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Project or environment not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/credentials": {
      "get": {
        "summary": "List project credentials",
        "description": "List credentials for a project. Passwords are not returned.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "List of credentials",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "credentials": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CredentialSummary"
                      }
                    }
                  },
                  "required": ["credentials"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a project credential",
        "description": "Create a login or inbox credential for a project. Passwords are not returned.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": ["login"]
                      },
                      "authMethod": {
                        "type": "string",
                        "enum": ["password", "google", "github"]
                      },
                      "label": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 50
                      },
                      "description": {
                        "type": "string",
                        "maxLength": 500,
                        "description": "When to use this account: its type, enabled features/plans, and the environments it exists in. The agent reads this when choosing between credentials."
                      },
                      "username": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 255
                      },
                      "password": {
                        "type": "string",
                        "minLength": 1
                      },
                      "totpSecret": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 512,
                        "description": "Authenticator (TOTP/MFA) secret: the base32 setup key or otpauth:// URI from the account's MFA enrollment. The agent generates one-time codes from it during runs. Never returned; responses expose only hasTotpSecret."
                      }
                    },
                    "required": ["kind", "label", "username", "password"],
                    "additionalProperties": false
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": ["login"]
                      },
                      "authMethod": {
                        "type": "string",
                        "enum": ["custom"]
                      },
                      "label": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 50
                      },
                      "description": {
                        "type": "string",
                        "maxLength": 500,
                        "description": "When to use this account: its type, enabled features/plans, and the environments it exists in. The agent reads this when choosing between credentials."
                      },
                      "authInstructions": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 4000
                      }
                    },
                    "required": ["kind", "authMethod", "label", "authInstructions"],
                    "additionalProperties": false
                  },
                  {
                    "type": "object",
                    "properties": {
                      "kind": {
                        "type": "string",
                        "enum": ["inbox"]
                      },
                      "label": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 50
                      },
                      "description": {
                        "type": "string",
                        "maxLength": 500,
                        "description": "When to use this account: its type, enabled features/plans, and the environments it exists in. The agent reads this when choosing between credentials."
                      }
                    },
                    "required": ["kind", "label"],
                    "additionalProperties": false
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Credential created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "credential": {
                      "$ref": "#/components/schemas/CredentialSummary"
                    }
                  },
                  "required": ["credential"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/memories": {
      "get": {
        "summary": "List project memories",
        "description": "List manual project memories used as context for dashboard tests and agents.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "List of project memories",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "memories": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProjectMemory"
                      }
                    },
                    "count": {
                      "type": "integer"
                    },
                    "maxMemories": {
                      "type": "integer"
                    }
                  },
                  "required": ["memories", "count", "maxMemories"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a project memory",
        "description": "Create a manual project memory that agents can use as project context.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "category": {
                    "type": "string",
                    "enum": ["site_structure", "test_insights", "user_preferences"]
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "content": {
                    "type": "string",
                    "minLength": 1
                  },
                  "importance": {
                    "type": "string",
                    "enum": ["high", "medium", "low"]
                  }
                },
                "required": ["category", "title", "content", "importance"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Project memory created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "memory": {
                      "$ref": "#/components/schemas/ProjectMemory"
                    },
                    "pruned": {
                      "type": "integer"
                    }
                  },
                  "required": ["memory", "pruned"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "409": {
            "description": "Memory limit reached and no lower-priority memories can be pruned",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/issues": {
      "get": {
        "summary": "List project issues",
        "description": "List a project's tracked issues: bugs and warnings surfaced by QA runs, deduplicated across runs with occurrence counts and triage status. Open issues sort first, then by most recently seen.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["open", "resolved", "false_positive"],
              "description": "Filter to one triage status."
            },
            "required": false,
            "description": "Filter to one triage status.",
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["production", "staging", "preview", "custom"],
              "description": "Filter to issues seen on one deployment environment."
            },
            "required": false,
            "description": "Filter to issues seen on one deployment environment.",
            "name": "environment",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^(?:[1-9]|[1-9][0-9]|100)$",
              "description": "Maximum issues to return (1-100, default 50)."
            },
            "required": false,
            "description": "Maximum issues to return (1-100, default 50).",
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of project issues",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "issues": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProjectIssue"
                      }
                    },
                    "count": {
                      "type": "integer"
                    },
                    "openCount": {
                      "type": "integer",
                      "description": "Total open issues in the project."
                    }
                  },
                  "required": ["issues", "count", "openCount"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/issues/{issueId}": {
      "get": {
        "summary": "Get a project issue",
        "description": "Get one tracked issue with its full details and recent run occurrences: which runs surfaced it and when.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Issue ID"
            },
            "required": true,
            "description": "Issue ID",
            "name": "issueId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Issue detail with recent occurrences",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "issue": {
                      "$ref": "#/components/schemas/ProjectIssue"
                    },
                    "occurrences": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProjectIssueOccurrence"
                      }
                    }
                  },
                  "required": ["issue", "occurrences"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Project or issue not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/memories/{memoryId}": {
      "delete": {
        "summary": "Delete a project memory",
        "description": "Delete a manual project memory used as agent context.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Memory ID"
            },
            "required": true,
            "description": "Memory ID",
            "name": "memoryId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Project memory deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean"
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "required": ["deleted", "id"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Project or memory not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/files": {
      "get": {
        "summary": "List project files",
        "description": "List uploaded files for a project.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID"
            },
            "required": true,
            "description": "Project ID",
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "List of files",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "files": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProjectFileSummary"
                      }
                    }
                  },
                  "required": ["files"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Initiate a project file upload",
        "description": "Validate a project file and create a presigned direct-upload URL. Mobile projects only accept photos and videos (.png, .jpg, .jpeg, .mp4, .mov); runs preload them into the device photo library.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filename": {
                    "type": "string",
                    "minLength": 1
                  },
                  "fileSize": {
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 52428800
                  },
                  "mediaType": {
                    "type": "string"
                  }
                },
                "required": ["filename", "fileSize"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Presigned project-file upload details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "uploadUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "storageKey": {
                      "type": "string"
                    },
                    "mimeType": {
                      "type": "string"
                    },
                    "filename": {
                      "type": "string"
                    },
                    "fileSize": {
                      "type": "integer"
                    },
                    "mediaType": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "uploadUrl",
                    "storageKey",
                    "mimeType",
                    "filename",
                    "fileSize",
                    "mediaType"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Confirm a project file upload",
        "description": "Verify uploaded bytes and register the file on the project.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID or shortId"
            },
            "required": true,
            "description": "Project ID or shortId",
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "storageKey": {
                    "type": "string",
                    "minLength": 1
                  },
                  "fileSize": {
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 52428800
                  },
                  "description": {
                    "type": ["string", "null"]
                  }
                },
                "required": ["storageKey", "fileSize"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Project file uploaded successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "files": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProjectFileSummary"
                      }
                    }
                  },
                  "required": ["files"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/mobile": {
      "get": {
        "summary": "List project mobile apps",
        "description": "List uploaded mobile apps for a mobile project.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Project ID"
            },
            "required": true,
            "description": "Project ID",
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "List of project mobile apps",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "apps": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "platform": {
                            "type": "string",
                            "enum": ["ios", "android"]
                          },
                          "filename": {
                            "type": "string"
                          },
                          "bundleId": {
                            "type": ["string", "null"]
                          },
                          "appVersion": {
                            "type": ["string", "null"]
                          },
                          "buildVersion": {
                            "type": ["string", "null"]
                          },
                          "fileSize": {
                            "type": "number"
                          },
                          "source": {
                            "type": "string",
                            "enum": ["manual_upload", "group_webhook_artifact", "api_upload"]
                          },
                          "expiresAt": {
                            "type": ["string", "null"],
                            "format": "date-time"
                          },
                          "removeAfter": {
                            "type": ["integer", "null"]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "platform",
                          "filename",
                          "bundleId",
                          "appVersion",
                          "buildVersion",
                          "fileSize",
                          "source",
                          "expiresAt",
                          "removeAfter",
                          "createdAt"
                        ]
                      }
                    }
                  },
                  "required": ["apps"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Upload a project mobile app",
        "description": "Upload a mobile app binary to a mobile project. Optionally set removeAfter to delete temporary uploads after a delay.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Project ID"
            },
            "required": true,
            "description": "Project ID",
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  },
                  "removeAfter": {
                    "type": "string",
                    "description": "Optional expiration in seconds for temporary uploads, from 60 to 604800. Temporary uploads have a 20 GB storage cap per project."
                  }
                },
                "required": ["file"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Mobile app uploaded successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "app": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "platform": {
                          "type": "string",
                          "enum": ["ios", "android"]
                        },
                        "filename": {
                          "type": "string"
                        },
                        "bundleId": {
                          "type": ["string", "null"]
                        },
                        "appVersion": {
                          "type": ["string", "null"]
                        },
                        "buildVersion": {
                          "type": ["string", "null"]
                        },
                        "fileSize": {
                          "type": "number"
                        },
                        "source": {
                          "type": "string",
                          "enum": ["manual_upload", "group_webhook_artifact", "api_upload"]
                        },
                        "expiresAt": {
                          "type": ["string", "null"],
                          "format": "date-time"
                        },
                        "removeAfter": {
                          "type": ["integer", "null"]
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time"
                        }
                      },
                      "required": [
                        "id",
                        "platform",
                        "filename",
                        "bundleId",
                        "appVersion",
                        "buildVersion",
                        "fileSize",
                        "source",
                        "expiresAt",
                        "removeAfter",
                        "createdAt"
                      ]
                    }
                  },
                  "required": ["app"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/mobile/{appId}": {
      "delete": {
        "summary": "Delete a project mobile app",
        "description": "Delete a previously uploaded mobile app from a mobile project.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Project ID"
            },
            "required": true,
            "description": "Project ID",
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Mobile app ID"
            },
            "required": true,
            "description": "Mobile app ID",
            "name": "appId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Mobile app deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean",
                      "enum": [true]
                    }
                  },
                  "required": ["deleted"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Project or mobile app not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/mobile/upload": {
      "post": {
        "summary": "Initiate a project mobile app upload",
        "description": "Create a presigned temporary upload for a mobile app binary.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Project ID"
            },
            "required": true,
            "description": "Project ID",
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filename": {
                    "type": "string",
                    "minLength": 1
                  },
                  "fileSize": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  },
                  "removeAfter": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 604800
                  }
                },
                "required": ["filename", "fileSize"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Presigned upload details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "uploadUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "storageKey": {
                      "type": "string"
                    },
                    "filename": {
                      "type": "string"
                    },
                    "fileSize": {
                      "type": "integer"
                    },
                    "removeAfter": {
                      "type": ["integer", "null"]
                    }
                  },
                  "required": ["uploadUrl", "storageKey", "filename", "fileSize", "removeAfter"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/projects/{projectId}/mobile/upload/confirm": {
      "post": {
        "summary": "Confirm a project mobile app upload",
        "description": "Validate a completed temporary upload and promote it into project storage.",
        "tags": ["Projects"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Project ID"
            },
            "required": true,
            "description": "Project ID",
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "storageKey": {
                    "type": "string",
                    "minLength": 1
                  },
                  "filename": {
                    "type": "string",
                    "minLength": 1
                  },
                  "fileSize": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  },
                  "removeAfter": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 604800
                  }
                },
                "required": ["storageKey", "filename", "fileSize"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Mobile app uploaded successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "app": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "platform": {
                          "type": "string",
                          "enum": ["ios", "android"]
                        },
                        "filename": {
                          "type": "string"
                        },
                        "bundleId": {
                          "type": ["string", "null"]
                        },
                        "appVersion": {
                          "type": ["string", "null"]
                        },
                        "buildVersion": {
                          "type": ["string", "null"]
                        },
                        "fileSize": {
                          "type": "number"
                        },
                        "source": {
                          "type": "string",
                          "enum": ["manual_upload", "group_webhook_artifact", "api_upload"]
                        },
                        "expiresAt": {
                          "type": ["string", "null"],
                          "format": "date-time"
                        },
                        "removeAfter": {
                          "type": ["integer", "null"]
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time"
                        }
                      },
                      "required": [
                        "id",
                        "platform",
                        "filename",
                        "bundleId",
                        "appVersion",
                        "buildVersion",
                        "fileSize",
                        "source",
                        "expiresAt",
                        "removeAfter",
                        "createdAt"
                      ]
                    }
                  },
                  "required": ["app"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/tests": {
      "get": {
        "summary": "List tests",
        "description": "List tests for a project, optionally scoped to a test group. Use `cursor` for pagination; the response includes `nextCursor` when more pages exist.",
        "tags": ["Tests"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID"
            },
            "required": true,
            "description": "Project ID",
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Optional test group ID"
            },
            "required": false,
            "description": "Optional test group ID",
            "name": "groupId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^(?:[1-9]|[1-9][0-9]|100)$",
              "description": "Max results per page (default 50, max 100)"
            },
            "required": false,
            "description": "Max results per page (default 50, max 100)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Cursor for pagination"
            },
            "required": false,
            "description": "Cursor for pagination",
            "name": "cursor",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of tests",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projectUrl": {
                      "type": ["string", "null"],
                      "format": "uri"
                    },
                    "projectName": {
                      "type": "string"
                    },
                    "tests": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TestDefinition"
                      }
                    },
                    "nextCursor": {
                      "type": ["string", "null"]
                    }
                  },
                  "required": ["projectUrl", "projectName", "tests", "nextCursor"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a test",
        "description": "Create a structured test definition for a project.",
        "tags": ["Tests"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "description": {
                    "type": "string"
                  },
                  "steps": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/TestStep"
                    },
                    "minItems": 1,
                    "maxItems": 30
                  },
                  "projectId": {
                    "type": "string"
                  },
                  "groupId": {
                    "type": ["string", "null"],
                    "format": "uuid"
                  },
                  "platform": {
                    "type": "string",
                    "enum": ["web", "mobile"]
                  },
                  "settings": {
                    "$ref": "#/components/schemas/TestSettings"
                  },
                  "enabled": {
                    "type": "boolean"
                  }
                },
                "required": ["title", "steps", "projectId"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Test created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "test": {
                      "$ref": "#/components/schemas/TestDefinition"
                    }
                  },
                  "required": ["test"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/tests/{testId}": {
      "get": {
        "summary": "Get a test",
        "description": "Get a single structured test definition, including the groups it belongs to.",
        "tags": ["Tests"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test ID"
            },
            "required": true,
            "description": "Test ID",
            "name": "testId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Test details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestDetail"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update a test",
        "description": "Update a structured test definition. `settings` is merged field by field; every other field replaces its stored value.",
        "tags": ["Tests"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test ID"
            },
            "required": true,
            "description": "Test ID",
            "name": "testId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "description": {
                    "type": "string"
                  },
                  "steps": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/TestStep"
                    },
                    "minItems": 1,
                    "maxItems": 30
                  },
                  "settings": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/TestSettings"
                      },
                      {
                        "description": "Settings patch; omitted fields keep their stored value."
                      }
                    ]
                  },
                  "enabled": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Test updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "test": {
                      "$ref": "#/components/schemas/TestDefinition"
                    }
                  },
                  "required": ["test"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a test",
        "description": "Delete a structured test definition.",
        "tags": ["Tests"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test ID"
            },
            "required": true,
            "description": "Test ID",
            "name": "testId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Test deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean",
                      "enum": [true]
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "required": ["deleted", "id"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/tests/{testId}/runs": {
      "post": {
        "summary": "Trigger a test run",
        "description": "Trigger a saved dashboard test remotely using API-key authentication. Returns the queued run ID.",
        "tags": ["Tests"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test ID"
            },
            "required": true,
            "description": "Test ID",
            "name": "testId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": ["fast", "deep"],
                    "description": "Deprecated and ignored. Deep mode was removed; every run uses the same mode."
                  },
                  "platform": {
                    "type": "string",
                    "enum": ["web", "ios", "android"],
                    "description": "Run platform for the test. Mobile tests default to ios when omitted, so Android runs must set platform: android - including when the mobile app is selected by appId."
                  },
                  "deviceModel": {
                    "type": "string",
                    "enum": ["iphone", "ipad"],
                    "description": "Mobile device variant within the run platform (iOS: iphone | ipad). Omit for the platform default phone-sized device; explicitly requesting the default (e.g. iphone) is equivalent to omitting it."
                  },
                  "appId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "projectEnvironmentId": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Test run queued successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": ["queued"]
                    },
                    "runId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "testId": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "required": ["status", "runId", "testId"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/groups": {
      "get": {
        "summary": "List test groups",
        "description": "List test groups for a project. The default All Tests group is always returned and new tests are added to it at creation time.",
        "tags": ["Groups"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Project ID"
            },
            "required": true,
            "description": "Project ID",
            "name": "projectId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of test groups",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "groups": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "name": {
                            "type": "string"
                          },
                          "isDefault": {
                            "type": "boolean"
                          },
                          "testCount": {
                            "type": "integer"
                          },
                          "runMode": {
                            "type": "string",
                            "enum": ["concurrent", "sequential"]
                          },
                          "maxConcurrentRuns": {
                            "type": ["integer", "null"],
                            "minimum": 1,
                            "description": "Concurrent groups only: max tests executing at once per group run. Capped at your team's concurrent-run limit; null follows the plan limit."
                          },
                          "prepTestId": {
                            "type": ["string", "null"],
                            "format": "uuid"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "isDefault",
                          "testCount",
                          "runMode",
                          "maxConcurrentRuns",
                          "prepTestId"
                        ]
                      }
                    }
                  },
                  "required": ["groups"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a test group",
        "description": "Create a test group in a project. Capped at 100 groups per project.",
        "tags": ["Groups"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "projectId": {
                    "type": "string",
                    "description": "Project ID"
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "runMode": {
                    "type": "string",
                    "enum": ["concurrent", "sequential"]
                  },
                  "maxConcurrentRuns": {
                    "type": ["integer", "null"],
                    "minimum": 1,
                    "description": "Concurrent groups only: max tests executing at once per group run. Capped at your team's concurrent-run limit; null follows the plan limit."
                  },
                  "prepTestId": {
                    "type": ["string", "null"],
                    "format": "uuid",
                    "description": "Web test that runs first and saves its browser session. Any web test in the project qualifies; it does not have to be a member of this group."
                  }
                },
                "required": ["projectId", "name"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Group created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "group": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        },
                        "isDefault": {
                          "type": "boolean"
                        },
                        "runMode": {
                          "type": "string",
                          "enum": ["concurrent", "sequential"]
                        },
                        "maxConcurrentRuns": {
                          "type": ["integer", "null"],
                          "minimum": 1,
                          "description": "Concurrent groups only: max tests executing at once per group run. Capped at your team's concurrent-run limit; null follows the plan limit."
                        },
                        "prepTestId": {
                          "type": ["string", "null"],
                          "format": "uuid"
                        },
                        "projectId": {
                          "type": "string",
                          "format": "uuid"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "isDefault",
                        "runMode",
                        "maxConcurrentRuns",
                        "prepTestId",
                        "projectId"
                      ]
                    }
                  },
                  "required": ["group"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/groups/{groupId}": {
      "get": {
        "summary": "Get a test group",
        "description": "Get a single test group by ID.",
        "tags": ["Groups"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test group ID"
            },
            "required": true,
            "description": "Test group ID",
            "name": "groupId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Group details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroupDetail"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update a test group",
        "description": "Update name, runMode, maxConcurrentRuns, or prepTestId on a test group.",
        "tags": ["Groups"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test group ID"
            },
            "required": true,
            "description": "Test group ID",
            "name": "groupId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "runMode": {
                    "type": "string",
                    "enum": ["concurrent", "sequential"]
                  },
                  "maxConcurrentRuns": {
                    "type": ["integer", "null"],
                    "minimum": 1,
                    "description": "Pass null to follow the plan limit again."
                  },
                  "prepTestId": {
                    "type": ["string", "null"],
                    "format": "uuid",
                    "description": "Web test that runs first and saves its browser session. Any web test in the project qualifies; it does not have to be a member of this group. Pass null to clear."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Group updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "group": {
                      "$ref": "#/components/schemas/GroupDetail"
                    }
                  },
                  "required": ["group"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a test group",
        "description": "Delete a non-default test group. The default group cannot be deleted.",
        "tags": ["Groups"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test group ID"
            },
            "required": true,
            "description": "Test group ID",
            "name": "groupId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Group deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean",
                      "enum": [true]
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "required": ["deleted", "id"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/groups/{groupId}/tests": {
      "post": {
        "summary": "Add a test to a group",
        "description": "Add an existing test to a test group. Returns 201 when a new membership row was created, or 200 with `added: false` when the test was already a member (idempotent).",
        "tags": ["Groups"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test group ID"
            },
            "required": true,
            "description": "Test group ID",
            "name": "groupId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "testId": {
                    "type": "string",
                    "format": "uuid"
                  }
                },
                "required": ["testId"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Test was already a member; no change",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "groupId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "testId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "added": {
                      "type": "boolean",
                      "enum": [false]
                    }
                  },
                  "required": ["groupId", "testId", "added"]
                }
              }
            }
          },
          "201": {
            "description": "Test added to group",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "groupId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "testId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "added": {
                      "type": "boolean",
                      "enum": [true]
                    }
                  },
                  "required": ["groupId", "testId", "added"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/groups/{groupId}/tests/{testId}": {
      "delete": {
        "summary": "Remove a test from a group",
        "description": "Remove a test from a test group. The group's prepTestId is left alone, because a preparation test does not have to be a member of the group it prepares. `removed` is `true` when a membership row was deleted, `false` when the test was not a member (idempotent).",
        "tags": ["Groups"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test group ID"
            },
            "required": true,
            "description": "Test group ID",
            "name": "groupId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test ID"
            },
            "required": true,
            "description": "Test ID",
            "name": "testId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Idempotent removal result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "groupId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "testId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "removed": {
                      "type": "boolean"
                    }
                  },
                  "required": ["groupId", "testId", "removed"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/groups/{groupId}/runs": {
      "post": {
        "summary": "Trigger a test group run",
        "description": "Trigger all runnable tests in a group using API-key authentication. Returns the batch ID plus `queuedRunIds` (runs accepted onto the worker) and `cancelledRunIds` (runs the server immediately cancelled, e.g. duplicates or quota cancellations). `status` is `queued` when at least one run is queued and `cancelled` when every run was rejected.",
        "tags": ["Groups"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test group ID"
            },
            "required": true,
            "description": "Test group ID",
            "name": "groupId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "platform": {
                    "type": "string",
                    "enum": ["web", "ios", "android"],
                    "description": "Run platform for the batch. Mobile tests default to ios when omitted, so Android runs must set platform: android - including when the mobile app is selected by appId or bundleId."
                  },
                  "deviceModel": {
                    "type": "string",
                    "enum": ["iphone", "ipad"],
                    "description": "Mobile device variant within the run platform (iOS: iphone | ipad). Omit for the platform default phone-sized device; explicitly requesting the default (e.g. iphone) is equivalent to omitting it."
                  },
                  "projectEnvironmentId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "targetUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "environment": {
                    "type": "string",
                    "enum": ["production", "staging", "preview", "custom"]
                  },
                  "mobile": {
                    "type": "object",
                    "properties": {
                      "appId": {
                        "type": "string",
                        "format": "uuid"
                      },
                      "bundleId": {
                        "type": "string",
                        "minLength": 1
                      },
                      "artifactUrl": {
                        "type": "string",
                        "format": "uri"
                      },
                      "artifactFilename": {
                        "type": "string",
                        "minLength": 1
                      },
                      "buildId": {
                        "type": "string",
                        "minLength": 1
                      }
                    },
                    "additionalProperties": false
                  },
                  "commitSha": {
                    "type": "string",
                    "minLength": 1
                  },
                  "prNumber": {
                    "type": "integer",
                    "exclusiveMinimum": 0
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Group run queued successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": ["queued", "cancelled"]
                    },
                    "groupId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "batchId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "runIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      }
                    },
                    "queuedRunIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      }
                    },
                    "cancelledRunIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      }
                    },
                    "count": {
                      "type": "integer"
                    },
                    "metadata": {
                      "type": "object",
                      "properties": {
                        "github": {
                          "type": "object",
                          "properties": {
                            "configured": {
                              "type": "boolean"
                            },
                            "checkRunCreated": {
                              "type": "boolean"
                            },
                            "commentTargetResolved": {
                              "type": "boolean"
                            },
                            "status": {
                              "type": "string",
                              "enum": ["not_configured", "check_create_failed", "pr_not_found"]
                            }
                          },
                          "required": ["configured", "checkRunCreated", "commentTargetResolved"]
                        }
                      },
                      "required": ["github"]
                    }
                  },
                  "required": [
                    "status",
                    "groupId",
                    "batchId",
                    "runIds",
                    "queuedRunIds",
                    "cancelledRunIds",
                    "count"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Group not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/groups/{groupId}/schedule": {
      "get": {
        "summary": "Get a group's schedule",
        "description": "Get the recurring schedule of a test group. A group holds at most one schedule; `schedule` is `null` when the group only runs manually.",
        "tags": ["Groups"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test group ID"
            },
            "required": true,
            "description": "Test group ID",
            "name": "groupId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The group's schedule, or null",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "schedule": {
                      "anyOf": [
                        {
                          "$ref": "#/components/schemas/GroupSchedule"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": ["schedule"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Create or replace a group's schedule",
        "description": "Create the group's recurring schedule, or replace the existing one in place. Every time the schedule fires, a run of each enabled test in the group is queued. The scheduler entry is updated before the stored schedule, so a rejected cron leaves the current schedule running. Returns 201 when the group had no schedule and 200 when one was replaced. Web projects only: a mobile project's group returns 400.",
        "tags": ["Groups"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test group ID"
            },
            "required": true,
            "description": "Test group ID",
            "name": "groupId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GroupScheduleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing schedule replaced",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "schedule": {
                      "$ref": "#/components/schemas/GroupSchedule"
                    }
                  },
                  "required": ["schedule"]
                }
              }
            }
          },
          "201": {
            "description": "Schedule created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "schedule": {
                      "$ref": "#/components/schemas/GroupSchedule"
                    }
                  },
                  "required": ["schedule"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "503": {
            "description": "The scheduler did not answer or failed server-side; the current schedule is unchanged and the same payload can be retried",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a group's schedule",
        "description": "Remove the group's recurring schedule so it only runs manually. Idempotent: `deleted` is `false` when the group had no schedule.",
        "tags": ["Groups"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test group ID"
            },
            "required": true,
            "description": "Test group ID",
            "name": "groupId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Idempotent deletion result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "groupId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "deleted": {
                      "type": "boolean"
                    }
                  },
                  "required": ["groupId", "deleted"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Resource does not exist or is not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook/{webhookId}/{secret}": {
      "post": {
        "summary": "Trigger a project webhook",
        "description": "Receive a deployment webhook and trigger PR testing when configured.",
        "tags": ["Webhooks"],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Webhook ID"
            },
            "required": true,
            "description": "Webhook ID",
            "name": "webhookId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Webhook secret"
            },
            "required": true,
            "description": "Webhook secret",
            "name": "secret",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook accepted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "received": {
                      "type": "boolean"
                    },
                    "ignored": {
                      "type": "boolean"
                    },
                    "reason": {
                      "type": "string"
                    },
                    "runId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "batchId": {
                      "type": "string",
                      "format": "uuid",
                      "deprecated": true,
                      "description": "First created batch only. Use batchIds, which covers every PR test group."
                    },
                    "batchIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      },
                      "description": "One batch per selected PR test group started by this delivery."
                    }
                  },
                  "required": ["received"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/groups/webhook/{webhookId}/{secret}": {
      "post": {
        "summary": "Trigger a group webhook",
        "description": "Trigger all runnable tests in a group from a signed webhook URL.",
        "tags": ["Webhooks"],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Webhook ID"
            },
            "required": true,
            "description": "Webhook ID",
            "name": "webhookId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Webhook secret"
            },
            "required": true,
            "description": "Webhook secret",
            "name": "secret",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "platform": {
                    "type": "string",
                    "enum": ["web", "ios", "android"],
                    "description": "Run platform for the batch. Mobile tests default to ios when omitted, so Android runs must set platform: android - including when the mobile app is selected by appId or bundleId."
                  },
                  "deviceModel": {
                    "type": "string",
                    "enum": ["iphone", "ipad"],
                    "description": "Mobile device variant within the run platform (iOS: iphone | ipad). Omit for the platform default phone-sized device; explicitly requesting the default (e.g. iphone) is equivalent to omitting it."
                  },
                  "projectEnvironmentId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "targetUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "environment": {
                    "type": "string",
                    "enum": ["production", "staging", "preview", "custom"]
                  },
                  "mobile": {
                    "type": "object",
                    "properties": {
                      "appId": {
                        "type": "string",
                        "format": "uuid"
                      },
                      "bundleId": {
                        "type": "string",
                        "minLength": 1
                      },
                      "artifactUrl": {
                        "type": "string",
                        "format": "uri"
                      },
                      "artifactFilename": {
                        "type": "string",
                        "minLength": 1
                      },
                      "buildId": {
                        "type": "string",
                        "minLength": 1
                      }
                    },
                    "additionalProperties": false
                  },
                  "commitSha": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Webhook accepted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "received": {
                      "type": "boolean"
                    },
                    "ignored": {
                      "type": "boolean"
                    },
                    "reason": {
                      "type": "string"
                    },
                    "runId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "batchId": {
                      "type": "string",
                      "format": "uuid",
                      "deprecated": true,
                      "description": "First created batch only. Use batchIds, which covers every PR test group."
                    },
                    "batchIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      },
                      "description": "One batch per selected PR test group started by this delivery."
                    }
                  },
                  "required": ["received"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs": {
      "get": {
        "summary": "List test runs",
        "description": "List test runs for the authenticated team with optional project/status filtering and cursor pagination.",
        "tags": ["Test Runs"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^(?:[1-9]|[1-9][0-9]|100)$",
              "description": "Max results per page (default 20, max 100)"
            },
            "required": false,
            "description": "Max results per page (default 20, max 100)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["queued", "running", "completed", "failed", "cancelled"],
              "description": "Filter by status"
            },
            "required": false,
            "description": "Filter by status",
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Filter by project ID"
            },
            "required": false,
            "description": "Filter by project ID",
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Filter by test ID"
            },
            "required": false,
            "description": "Filter by test ID",
            "name": "testId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Filter by group-run batch ID"
            },
            "required": false,
            "description": "Filter by group-run batch ID",
            "name": "batchId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Cursor for pagination"
            },
            "required": false,
            "description": "Cursor for pagination",
            "name": "cursor",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of runs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/{id}": {
      "get": {
        "summary": "Get test run status",
        "description": "Retrieve the current status and result of a test run. Poll this endpoint to check for completion.",
        "tags": ["Test Runs"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test run ID"
            },
            "required": true,
            "description": "Test run ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Run details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Run not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/{id}/messages": {
      "get": {
        "summary": "Get run agent transcript",
        "description": "Retrieve the full agent transcript for a run: assistant reasoning, tool calls, and tool outputs in execution order. Use this to understand exactly what the agent did and why a step failed. Credential-bearing tool parts are redacted.",
        "tags": ["Test Runs"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test run ID"
            },
            "required": true,
            "description": "Test run ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Agent transcript",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunMessagesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Run not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/{id}/telemetry": {
      "get": {
        "summary": "Get run console and network logs",
        "description": "Retrieve console logs and network requests captured during a run. Use this to debug failures: console errors, failed requests, and 4xx/5xx responses with redacted header and JSON body previews. Web runs capture browser console and network activity; mobile runs of an uploaded app capture the app's logs (Android logcat, iOS stdout/stderr) as console entries with no network entries. Telemetry becomes available after the run finishes; runs with nothing captured return 404.",
        "tags": ["Test Runs"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test run ID"
            },
            "required": true,
            "description": "Test run ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Console and network telemetry",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunTelemetryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Run not found or no telemetry captured for this run",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/{id}/recording": {
      "get": {
        "summary": "Get run screen recording",
        "description": "Stream the screen recording (MP4) captured during a run. Supports HTTP Range requests for seeking and partial downloads. Recordings become available after the run finishes; cancelled runs and runs without a recording return 404.",
        "tags": ["Test Runs"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test run ID"
            },
            "required": true,
            "description": "Test run ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Screen recording video stream",
            "content": {
              "video/mp4": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "206": {
            "description": "Partial video content for a Range request",
            "content": {
              "video/mp4": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Run not found or no recording available for this run",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "416": {
            "description": "Requested range not satisfiable"
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/{id}/recording/download-url": {
      "get": {
        "summary": "Get a run recording download URL",
        "description": "Get a short-lived signed URL that downloads the run's screen recording (MP4), plus its file name and size. Use this instead of the streaming endpoint when the client should hand the link off rather than hold the bytes. Recordings become available after the run finishes; cancelled runs and runs without a recording return 404.",
        "tags": ["Test Runs"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test run ID"
            },
            "required": true,
            "description": "Test run ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Signed recording download URL",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "runId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "fileName": {
                      "type": "string"
                    },
                    "mediaType": {
                      "type": "string"
                    },
                    "sizeBytes": {
                      "type": ["number", "null"],
                      "description": "Recording size in bytes, when R2 reports it"
                    },
                    "downloadUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "expiresIn": {
                      "type": "number",
                      "description": "Lifetime of the URL in seconds"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  },
                  "required": [
                    "runId",
                    "fileName",
                    "mediaType",
                    "sizeBytes",
                    "downloadUrl",
                    "expiresIn",
                    "expiresAt"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Run not found or no recording available for this run",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/{id}/cancel": {
      "post": {
        "summary": "Cancel a queued or running run",
        "description": "Cancel a queued or running test run.",
        "tags": ["Test Runs"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test run ID"
            },
            "required": true,
            "description": "Test run ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Run cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "enum": ["cancelled"]
                    }
                  },
                  "required": ["id", "status"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "409": {
            "description": "Conflict - Run is already terminal or cannot be cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/batches/{batchId}": {
      "get": {
        "summary": "Get batch status",
        "description": "Retrieve the aggregate status of a group-run batch with per-run verdicts. Poll this endpoint to track batch completion, then fetch individual runs (or `GET /v1/runs?batchId=...`) for details.",
        "tags": ["Test Runs"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Batch ID"
            },
            "required": true,
            "description": "Batch ID",
            "name": "batchId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Batch status summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchStatusResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Batch not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/batches/{batchId}/junit": {
      "get": {
        "summary": "Get batch JUnit XML report",
        "description": "Download the batch as a JUnit XML report for CI test reporters and test management tools such as TestRail (`trcli parse_junit -f report.xml`). Preparation runs are omitted. Returns 409 until every run has finished unless `allowIncomplete=true` is set.",
        "tags": ["Test Runs"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Batch ID"
            },
            "required": true,
            "description": "Batch ID",
            "name": "batchId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["true", "false"],
              "description": "Export a batch with in-flight runs; unfinished runs render as skipped"
            },
            "required": false,
            "description": "Export a batch with in-flight runs; unfinished runs render as skipped",
            "name": "allowIncomplete",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "JUnit XML report (served as an attachment)",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string",
                  "description": "JUnit XML document. One `testsuite` per group-run batch (named after the group), one `testcase` per test. Passing runs have no child element; a FAILED verdict is a `<failure>`; BLOCKED verdicts, runs that crashed before a verdict, and runs that finished without one are `<error>` (type `BLOCKED`, the run error code, or `MISSING_VERDICT`); cancelled, planner-skipped, and unfinished runs are `<skipped>`. Each testcase carries `testerarmy_*` properties plus TestRail `testrail_result_comment` and `testrail_result_step` properties, and a `test_id` property when the test title contains `[C123]`-style case ids, so `trcli parse_junit` imports it directly."
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Batch not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "409": {
            "description": "Conflict - Some runs are still queued or running; pass `allowIncomplete=true` to export as skipped",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/{id}/junit": {
      "get": {
        "summary": "Get run JUnit XML report",
        "description": "Download a single run as a one-case JUnit XML report, in the same shape as the batch report. Returns 409 until the run has finished unless `allowIncomplete=true` is set, and 422 for a group's preparation run, which is not a test case.",
        "tags": ["Test Runs"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Test run ID"
            },
            "required": true,
            "description": "Test run ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["true", "false"],
              "description": "Export an in-flight run; it renders as skipped"
            },
            "required": false,
            "description": "Export an in-flight run; it renders as skipped",
            "name": "allowIncomplete",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "JUnit XML report (served as an attachment)",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string",
                  "description": "JUnit XML document. One `testsuite` per group-run batch (named after the group), one `testcase` per test. Passing runs have no child element; a FAILED verdict is a `<failure>`; BLOCKED verdicts, runs that crashed before a verdict, and runs that finished without one are `<error>` (type `BLOCKED`, the run error code, or `MISSING_VERDICT`); cancelled, planner-skipped, and unfinished runs are `<skipped>`. Each testcase carries `testerarmy_*` properties plus TestRail `testrail_result_comment` and `testrail_result_step` properties, and a `test_id` property when the test title contains `[C123]`-style case ids, so `trcli parse_junit` imports it directly."
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Run not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "409": {
            "description": "Conflict - The run is still queued or running; pass `allowIncomplete=true` to export as skipped",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable - The run is a preparation run and is not exported as a test case",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/batches/{batchId}/cancel": {
      "post": {
        "summary": "Cancel a queued or running batch",
        "description": "Cancel all queued or running runs in a prior group-run batch. Finished runs are left unchanged, making the endpoint idempotent when the batch has already completed.",
        "tags": ["Test Runs"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Batch ID"
            },
            "required": true,
            "description": "Batch ID",
            "name": "batchId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Batch cancellation summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "batchId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "cancelled": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "alreadyFinished": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "cancelledRunIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      }
                    },
                    "alreadyFinishedRunIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      }
                    }
                  },
                  "required": [
                    "batchId",
                    "cancelled",
                    "alreadyFinished",
                    "cancelledRunIds",
                    "alreadyFinishedRunIds"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Batch not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "409": {
            "description": "Conflict - Some runs could not be cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    },
                    "batchId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "cancelled": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "alreadyFinished": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "cancelledRunIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      }
                    },
                    "alreadyFinishedRunIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      }
                    },
                    "failedRunIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      }
                    }
                  },
                  "required": [
                    "error",
                    "message",
                    "batchId",
                    "cancelled",
                    "alreadyFinished",
                    "cancelledRunIds",
                    "alreadyFinishedRunIds",
                    "failedRunIds"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/batches/{batchId}/rerun": {
      "post": {
        "summary": "Re-run a batch",
        "description": "Create a new group-run batch from the runnable tests in a prior batch. Deleted, disabled, or malformed tests are skipped and returned as `skippedTestIds`.",
        "tags": ["Test Runs"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Source batch ID"
            },
            "required": true,
            "description": "Source batch ID",
            "name": "batchId",
            "in": "path"
          }
        ],
        "responses": {
          "202": {
            "description": "Batch re-run queued successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": ["queued", "cancelled"]
                    },
                    "groupId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "batchId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "sourceBatchId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "runIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      }
                    },
                    "queuedRunIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      }
                    },
                    "cancelledRunIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      }
                    },
                    "skippedTestIds": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      }
                    },
                    "count": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "status",
                    "groupId",
                    "batchId",
                    "sourceBatchId",
                    "runIds",
                    "queuedRunIds",
                    "cancelledRunIds",
                    "skippedTestIds",
                    "count"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "404": {
            "description": "Batch not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "409": {
            "description": "Conflict - Batch cannot be re-run",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    },
    "/v1/feedback": {
      "post": {
        "summary": "Submit product feedback",
        "description": "Report a problem with TesterArmy itself (not the app under test): a broken or confusing tool, misleading docs, or a missing capability. Intended for coding agents driving TesterArmy through the CLI or API; the MCP server exposes the same report as `submit_feedback`. Delivered to the TesterArmy team.",
        "tags": ["Feedback"],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["bug", "docs", "feature", "other"],
                    "default": "other",
                    "description": "bug: a tool or command broke or returned wrong results. docs: docs or guides were wrong or confusing. feature: a capability you needed is missing. other: anything else."
                  },
                  "message": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000,
                    "description": "One or two sentences summarizing the problem."
                  },
                  "task": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000,
                    "description": "What you were trying to accomplish."
                  },
                  "expected": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000,
                    "description": "What you expected to happen."
                  },
                  "actual": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000,
                    "description": "What actually happened, including error messages."
                  },
                  "approach": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000,
                    "description": "What you tried, including workarounds."
                  },
                  "tool": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "The MCP tool or CLI command involved, e.g. run_test or `ta tests run`."
                  },
                  "projectId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100,
                    "description": "Related project ID, if any."
                  },
                  "runId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100,
                    "description": "Related run ID, if any."
                  },
                  "agent": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "The coding agent and model reporting, e.g. Claude Code / claude-sonnet-5."
                  }
                },
                "required": ["message"],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Feedback submitted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "submitted": {
                      "type": "boolean",
                      "enum": [true]
                    }
                  },
                  "required": ["submitted"]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid input parameters",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Usage limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          },
          "504": {
            "description": "Gateway Timeout - Test execution exceeded time limit",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Error code or type"
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable error message"
                    }
                  },
                  "required": ["error", "message"]
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {}
}
