{"openapi":"3.0.3","info":{"title":"GoOmni AI","description":"AI-powered project management, quality assurance, and knowledge platform.\n\n**Base URL:** `https://agent.goomni.ai` &nbsp;|&nbsp; **Auth:** `Authorization: Bearer <jwt>`\n","version":"1.0.0","contact":{"name":"GoOmni API Support","url":"https://goomni.ai"},"license":{"name":"Proprietary","url":"https://goomni.ai/terms"}},"servers":[{"url":"https://agent.goomni.ai","description":"Production"},{"url":"http://localhost:3000","description":"Local Development"}],"tags":[{"name":"Public Test Case Generator","description":"**No authentication.** Powers the public-facing Test Case Generator at\n`/public/test-case-generator`. Agentic, multi-turn generation backed by a\nClaude tool-use loop with KB grounding (Rex Black, ISTQB) and file-to-\nrequirements extraction. Rate-limited per email.\n\nStreams real-time progress via WebSocket, POST returns an `executionId`,\nthen `wss://<api>/ws` with `{action: \"subscribe\", executionId}` delivers\n`status` / `result` / `execution_complete` events.\n"},{"name":"Public Test Sessions","description":"Persistent generation sessions. Tracks the requirements input, conversation\nturns, generated test cases, and lets the UI autosave inline edits via PATCH.\n"},{"name":"Public Hosted Execution","description":"Dispatches a hosted browser run for a subset of test cases against a\ntarget URL. Each prose test step is interpreted by Claude into typed\nbrowser actions (puppeteer-core + @sparticuz/chromium on AWS Lambda),\nverified, and captured as PNG evidence in S3. Returns `executionId`\nimmediately, the frontend subscribes via WebSocket for step-level\nprogress and pulls signed-URL evidence when the run completes.\n\n**Free-tier limit:** 5 executions per hour per email.\n"},{"name":"Public Test Case Export","description":"Render generated test cases into 6 deliverable formats:\nJira Xray CSV, TestRail CSV, Azure DevOps CSV, generic CSV,\nGherkin .feature, and structured JSON.\n"}],"security":[{"bearerAuth":[]}],"components":{"parameters":{"organizationId":{"name":"organizationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Organization ID (top-level tenant identifier)"},"projectId":{"name":"projectId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Project ID (scoped workspace within an organization)"},"kbId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Knowledge Base ID"}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT token from NextAuth/Cognito authentication"}},"schemas":{"AnalyticsWebsite":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"domain":{"type":"string","nullable":true},"organizationId":{"type":"string","format":"uuid"},"teamId":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"}}},"CollectRequest":{"type":"object","required":["type","payload"],"properties":{"type":{"type":"string","enum":["event","identify"],"description":"`event` records a pageview or custom event. `identify` attaches\nsession properties via the session_data pipeline.\n"},"payload":{"type":"object","required":["website"],"properties":{"website":{"type":"string","format":"uuid","description":"Website ID from the analytics console (tracker site key)."},"url":{"type":"string"},"title":{"type":"string"},"referrer":{"type":"string"},"hostname":{"type":"string"},"language":{"type":"string"},"screen":{"type":"string"},"name":{"type":"string","description":"Custom event name (omit for pageviews)."},"specialEventName":{"type":"string"},"tag":{"type":"string","nullable":true},"data":{"type":"object","additionalProperties":true,"description":"Custom event properties."},"session":{"type":"object","additionalProperties":true}}}}},"RecordRequest":{"type":"object","required":["type","payload"],"properties":{"type":{"type":"string","enum":["record"]},"payload":{"type":"object","required":["website","events"],"properties":{"website":{"type":"string","format":"uuid"},"events":{"type":"array","minItems":1,"maxItems":200,"items":{"type":"object","description":"rrweb recording chunk events."}},"timestamp":{"type":"integer","format":"int64"}}}}},"Heatmap":{"type":"object","properties":{"heatmapId":{"type":"string","format":"uuid"},"websiteId":{"type":"string","format":"uuid"},"urlPath":{"type":"string"},"device":{"type":"string","enum":["desktop","mobile","tablet"]},"status":{"type":"string","enum":["pending","building","ready","failed"]},"windowStart":{"type":"string","format":"date-time"},"windowEnd":{"type":"string","format":"date-time"}}},"ReplaySessionSummary":{"type":"object","properties":{"replaySessionId":{"type":"string"},"websiteId":{"type":"string","format":"uuid"},"sessionId":{"type":"string"},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time"},"durationMs":{"type":"integer"},"eventCount":{"type":"integer"},"errorCount":{"type":"integer"},"rageClickCount":{"type":"integer"},"deadClickCount":{"type":"integer"},"device":{"type":"string"},"browser":{"type":"string"},"country":{"type":"string"},"landingUrl":{"type":"string"},"exitUrl":{"type":"string"},"status":{"type":"string","enum":["recording","finalized","failed",""]},"qualityScore":{"type":"number"},"chunkCount":{"type":"integer"},"playable":{"type":"boolean"}}},"Experiment":{"type":"object","properties":{"experimentId":{"type":"string","format":"uuid"},"websiteId":{"type":"string","format":"uuid"},"name":{"type":"string"},"status":{"type":"string","enum":["draft","running","paused","completed","archived"]},"hypothesis":{"type":"string"},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"weight":{"type":"number"},"isControl":{"type":"boolean"}}}}}},"Error":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}},"Organization":{"type":"object","properties":{"organizationId":{"type":"string","format":"uuid","description":"Unique organization identifier"},"name":{"type":"string","example":"Acme Corp"},"slug":{"type":"string","example":"acme-corp","description":"URL-friendly identifier"},"tier":{"type":"string","enum":["startup","growth","enterprise"]},"billingEmail":{"type":"string","format":"email"},"settings":{"type":"object","properties":{"chatModel":{"type":"string"},"chatTemperature":{"type":"number"},"maxMembers":{"type":"integer"},"maxProjects":{"type":"integer"},"maxStorage":{"type":"integer"},"allowPublicKBs":{"type":"boolean"},"customBranding":{"type":"boolean"}}},"googleDriveLinked":{"type":"boolean"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"Project":{"type":"object","properties":{"projectId":{"type":"string","format":"uuid","description":"Unique project identifier"},"organizationId":{"type":"string","format":"uuid","description":"Parent organization"},"name":{"type":"string","example":"Q1 2026 Government RFP"},"description":{"type":"string"},"templateId":{"type":"string"},"templateType":{"type":"string","enum":["rfp","migration","qa","blank"]},"knowledgeBaseIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Linked knowledge bases providing context for this project"},"agentConfigs":{"type":"array","items":{"type":"object","properties":{"agentId":{"type":"string"},"agentType":{"type":"string"},"enabled":{"type":"boolean"},"order":{"type":"integer"},"config":{"type":"object"}}}},"status":{"type":"string","enum":["active","archived","deleted"]},"stats":{"type":"object","properties":{"fileCount":{"type":"integer"},"agentRunCount":{"type":"integer"},"lastActivityAt":{"type":"string","format":"date-time"}}},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"KnowledgeBase":{"type":"object","properties":{"kbId":{"type":"string","format":"uuid","description":"Unique knowledge base identifier"},"organizationId":{"type":"string","format":"uuid","description":"Parent organization"},"name":{"type":"string","example":"Company Training Materials"},"description":{"type":"string"},"type":{"type":"string","enum":["drive_folders","manual_files","integration","website"],"description":"How content is ingested"},"isPublic":{"type":"boolean","description":"Whether KB is publicly searchable"},"publicSlug":{"type":"string"},"fileCount":{"type":"integer"},"totalSizeBytes":{"type":"integer"},"embeddingModel":{"type":"string"},"status":{"type":"string","enum":["active","indexing","error","archived"]},"masterContext":{"type":"string","description":"AI-generated summary of all KB content"},"createdBy":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"KnowledgeBaseCreate":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"Company Policies"},"description":{"type":"string","example":"Internal company policies and procedures"},"isPublic":{"type":"boolean","default":false}}},"FileUpload":{"type":"object","properties":{"fileId":{"type":"string","format":"uuid"},"fileName":{"type":"string"},"fileType":{"type":"string"},"fileSize":{"type":"integer"},"status":{"type":"string","enum":["uploaded","processing","indexed","error"]},"createdAt":{"type":"string","format":"date-time"}}},"SearchRequest":{"type":"object","required":["question"],"properties":{"question":{"type":"string","description":"The search question to ask the knowledge base","example":"What is our refund policy?"},"conversationHistory":{"type":"array","items":{"type":"object"},"description":"Previous conversation messages for context"},"enableWebSearch":{"type":"boolean","default":false},"stream":{"type":"boolean","default":false},"limit":{"type":"integer","minimum":1,"maximum":200,"default":10,"description":"Maximum number of source chunks to return. In non-streaming mode this\nis also the page size unless `perPage` is provided. Capped at 200 per\nrequest; use `page` to retrieve additional results.\n"},"page":{"type":"integer","minimum":1,"default":1,"description":"1-indexed page number for paginating through source results.\nNon-streaming mode only. The total crawl depth (page × perPage) is\ncapped at 1000 sources per query.\n"},"perPage":{"type":"integer","minimum":1,"maximum":200,"description":"Page size for pagination. Defaults to `limit` if not provided.\nNon-streaming mode only.\n"}}},"SearchPagination":{"type":"object","properties":{"page":{"type":"integer","description":"Current 1-indexed page"},"perPage":{"type":"integer","description":"Page size used for this response"},"total":{"type":"integer","description":"Total source chunks retrieved across all pages for this query\n(bounded by the 1000-source crawl cap).\n"},"hasMore":{"type":"boolean","description":"True if additional pages may exist"}}},"SearchResponse":{"type":"object","properties":{"answer":{"type":"string","description":"LLM-generated answer (always reflects the top source set, even when you page through results)"},"sources":{"type":"array","items":{"type":"object"}},"entities":{"type":"array","items":{"type":"object"}},"relationships":{"type":"array","items":{"type":"object"}},"question":{"type":"string"},"kbName":{"type":"string"},"pagination":{"$ref":"#/components/schemas/SearchPagination"}}},"SearchResult":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"chunkId":{"type":"string"},"content":{"type":"string"},"score":{"type":"number","format":"float"},"metadata":{"type":"object","properties":{"fileName":{"type":"string"},"fileId":{"type":"string"},"pageNumber":{"type":"integer"}}}}}},"totalResults":{"type":"integer"}}},"Integration":{"type":"object","properties":{"integrationId":{"type":"string"},"type":{"type":"string","enum":["twilio","hubspot","google-drive"]},"status":{"type":"string","enum":["active","inactive","error"]},"config":{"type":"object"}}},"PublicTestStep":{"type":"object","required":["stepNumber","action","expectedResult"],"properties":{"stepNumber":{"type":"integer"},"action":{"type":"string","description":"Prose instruction (e.g. \"Click the Sign Up button\")"},"expectedResult":{"type":"string","description":"Verification target (e.g. \"User is redirected to /verify-email\")"},"testData":{"type":"string"}}},"PublicTestCase":{"type":"object","required":["id","title"],"properties":{"id":{"type":"string","example":"TC-001"},"title":{"type":"string"},"description":{"type":"string"},"objective":{"type":"string"},"testBasis":{"type":"string","description":"Source requirement (e.g. user story ID)"},"testCondition":{"type":"string"},"designTechnique":{"type":"string","example":"equivalence-partitioning"},"testLevel":{"type":"string","enum":["unit","integration","system","acceptance"],"default":"system"},"testType":{"type":"string","enum":["functional","regression","integration","e2e","accessibility","security","performance","boundary","negative","smoke"],"default":"functional"},"preconditions":{"type":"array","items":{"type":"string"}},"steps":{"type":"array","items":{"$ref":"#/components/schemas/PublicTestStep"}},"expectedResult":{"type":"string"},"postconditions":{"type":"array","items":{"type":"string"}},"priority":{"type":"string","enum":["critical","high","medium","low"],"default":"medium"},"riskLevel":{"type":"string"},"category":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"requirementRef":{"type":"string"},"gherkin":{"type":"string"},"estimatedDuration":{"type":"string"}}},"PublicConversationTurn":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"testCaseCount":{"type":"integer"}}},"PublicSessionDetail":{"type":"object","properties":{"sessionId":{"type":"string"},"title":{"type":"string"},"status":{"type":"string"},"requirements":{"type":"string"},"scope":{"type":"string"},"format":{"type":"string"},"maxTestCases":{"type":"integer"},"uploadedFileName":{"type":"string"},"conversation":{"type":"array","items":{"$ref":"#/components/schemas/PublicConversationTurn"}},"testCases":{"type":"array","items":{"$ref":"#/components/schemas/PublicTestCase"}},"summary":{"type":"object"},"events":{"type":"array","items":{"type":"object"}},"totalTestCases":{"type":"integer"},"totalIterations":{"type":"integer"},"totalToolCalls":{"type":"integer"},"turnCount":{"type":"integer"},"latestExecutionId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"PublicStepResult":{"type":"object","properties":{"stepNumber":{"type":"integer"},"action":{"type":"string"},"status":{"type":"string","enum":["passed","failed","error","skipped"]},"durationMs":{"type":"integer"},"screenshotKey":{"type":"string","description":"S3 key of the post-step screenshot (use the parent case's screenshotUrls for signed URL)"},"error":{"type":"string"},"interpretedAction":{"type":"object","description":"The typed browser action Claude derived from the prose step.\nShape varies by action, examples below:\n","example":{"type":"click","selector":"button:has-text('Sign Up')"}}}},"TestCase":{"type":"object","properties":{"id":{"type":"string","example":"TC-001"},"title":{"type":"string","example":"Verify login with valid credentials"},"description":{"type":"string"},"preconditions":{"type":"array","items":{"type":"string"}},"steps":{"type":"array","items":{"type":"object","properties":{"stepNumber":{"type":"integer"},"action":{"type":"string"},"expectedResult":{"type":"string"},"testData":{"type":"string"}}}},"expectedResult":{"type":"string"},"priority":{"type":"string","enum":["critical","high","medium","low"]},"type":{"type":"string","enum":["functional","regression","integration","e2e","accessibility","security","performance","boundary","negative","smoke"]},"category":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"requirementRef":{"type":"string","description":"Source requirement ID for traceability"},"gherkin":{"type":"string","description":"Given/When/Then syntax (when format is gherkin)"},"estimatedDuration":{"type":"string","example":"5min"}}},"Requirement":{"type":"object","properties":{"id":{"type":"string","example":"REQ-001"},"statement":{"type":"string","example":"The system shall authenticate users via username and password"},"category":{"type":"string","enum":["functional","security","performance","accessibility","usability","reliability"]},"subcategory":{"type":"string"},"priority":{"type":"string","enum":["critical","high","medium","low"]},"testability":{"type":"string","enum":["high","medium","low"]},"testabilityNotes":{"type":"string"},"suggestedTestType":{"type":"string"},"acceptanceCriteria":{"type":"array","items":{"type":"string"}},"ambiguities":{"type":"array","items":{"type":"string"}},"dependencies":{"type":"array","items":{"type":"string"}},"source":{"type":"string"}}},"RfpAnalysisRequest":{"type":"object","required":["projectId"],"properties":{"projectId":{"type":"string","description":"Project containing RFP files"},"kbIds":{"type":"array","items":{"type":"string"},"description":"Knowledge base IDs for company context"}}},"RfpSection":{"type":"object","properties":{"sectionId":{"type":"string"},"title":{"type":"string"},"content":{"type":"string"},"order":{"type":"integer"},"status":{"type":"string","enum":["draft","generated","reviewed","final"]}}},"AgentChainRequest":{"type":"object","required":["projectId","organizationId"],"properties":{"projectId":{"type":"string"},"organizationId":{"type":"string"},"agents":{"type":"array","items":{"type":"string","enum":["analysis","assessment","research","win-themes","writer","qa"]},"description":"Agents to run (defaults to full chain)"},"companyKbIds":{"type":"array","items":{"type":"string"},"description":"Company knowledge base IDs for context"}}},"OpportunityScanRequest":{"type":"object","required":["filterId"],"properties":{"filterId":{"type":"string","description":"Search filter ID defining scan criteria"},"organizationId":{"type":"string"},"projectId":{"type":"string"}}},"Opportunity":{"type":"object","properties":{"opportunityId":{"type":"string"},"title":{"type":"string"},"agency":{"type":"string"},"postedDate":{"type":"string","format":"date"},"dueDate":{"type":"string","format":"date"},"estimatedValue":{"type":"number"},"naicsCode":{"type":"string"},"setAside":{"type":"string"},"sourceUrl":{"type":"string"},"qualificationScore":{"type":"number","format":"float"},"status":{"type":"string","enum":["new","qualified","reviewed","applied","won","lost"]}}},"NormalizedTicket":{"type":"object","properties":{"externalId":{"type":"string","description":"Platform-specific ID (e.g. PROJ-42 for Jira, gid for Asana)"},"platform":{"type":"string","enum":["asana","jira","linear","azure_devops"]},"url":{"type":"string","format":"uri"},"title":{"type":"string"},"description":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string","enum":["critical","high","medium","low"]},"type":{"type":"string"},"assignee":{"type":"string"},"labels":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"parentId":{"type":"string"},"subtaskIds":{"type":"array","items":{"type":"string"}},"storyPoints":{"type":"integer"},"customFields":{"type":"object"}}},"GeneratedTicket":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["feature","bug","task","spike"]},"priority":{"type":"string","enum":["critical","high","medium","low"]},"acceptanceCriteria":{"type":"array","items":{"type":"string"}},"storyPoints":{"type":"integer"},"labels":{"type":"array","items":{"type":"string"}},"relatedTicketIds":{"type":"array","items":{"type":"string"}}}},"TicketSyncResult":{"type":"object","properties":{"integrationId":{"type":"string"},"platform":{"type":"string"},"totalFetched":{"type":"integer"},"newTickets":{"type":"integer"},"updatedTickets":{"type":"integer"},"errors":{"type":"array","items":{"type":"string"}},"syncedAt":{"type":"string","format":"date-time"}}},"VoiceCall":{"type":"object","properties":{"callId":{"type":"string"},"kbId":{"type":"string"},"direction":{"type":"string","enum":["inbound","outbound"]},"fromNumber":{"type":"string"},"toNumber":{"type":"string"},"status":{"type":"string","enum":["initiated","ringing","in-progress","completed","failed"]},"duration":{"type":"integer","description":"Call duration in seconds"},"transcript":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"OutboundCallRequest":{"type":"object","required":["kbId","phoneNumber"],"properties":{"kbId":{"type":"string","format":"uuid","description":"Knowledge base ID (determines which voice agent handles the call)"},"phoneNumber":{"type":"string","description":"Phone number to call (E.164 format)","example":"+12125551234"},"metadata":{"type":"object","properties":{"contactName":{"type":"string"},"campaignId":{"type":"string"}}}}},"VoiceTool":{"type":"object","properties":{"toolId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["lead-collection","search-faq","hubspot-meeting-booking","hubspot-meeting-availability","retrieve-kb-info","custom"]},"description":{"type":"string"},"config":{"type":"object"},"kbIds":{"type":"array","items":{"type":"string"}}}},"Campaign":{"type":"object","properties":{"campaignId":{"type":"string"},"name":{"type":"string"},"kbId":{"type":"string"},"status":{"type":"string","enum":["draft","active","paused","completed"]},"totalContacts":{"type":"integer"},"contactsCalled":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"}}}}},"paths":{"/api/public/test-cases/extract-from-file":{"post":{"operationId":"publicTestCaseExtractFromFile","summary":"Extract requirements text from an uploaded file","description":"Accepts a file upload (PDF, DOCX, DOC, XLSX, XLS, CSV, TXT, MD) and\nreturns the extracted plain text suitable for pasting into the test\ncase generator. Limit: 10 MB per file, 30 uploads per hour per IP.\n","tags":["Public Test Case Generator"],"security":[],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"PDF, DOCX, DOC, XLSX, XLS, CSV, TXT, or MD file (≤10 MB)"}},"required":["file"]}}}},"responses":{"200":{"description":"Text extracted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","description":"Extracted plain text from the file"},"fileName":{"type":"string"},"fileType":{"type":"string","enum":["pdf","docx","doc","xlsx","xls","csv","txt","md"]},"charCount":{"type":"integer"}}},"examples":{"pdf":{"summary":"PDF extraction","value":{"text":"1. Login Page\nAs a user, I want to log in with my email and password...","fileName":"requirements.pdf","fileType":"pdf","charCount":2415}}}}}},"400":{"description":"Invalid file (missing, wrong type, empty, or oversize)"},"429":{"description":"Rate limit exceeded (30 uploads/hour/IP)"}}}},"/api/public/test-cases/generate":{"post":{"operationId":"publicTestCaseGenerate","summary":"Generate test cases from requirements","description":"Generates ISTQB-aligned test cases enriched with the Rex Black training\nknowledge base. Two modes:\n\n* **`stream: false` (default)**, synchronous; returns the test cases in\n  the response body. Capped by CloudFront's 120-second timeout.\n* **`stream: true`**, dispatches to a background Lambda worker and\n  returns an `executionId` immediately. Subscribe via WebSocket to\n  receive `status`, `tool_call`, and `result` events.\n\nSupports five `mode` values: `agentic` (multi-turn Claude tool-use,\ndefault), `generate` (single-shot), `extract-requirements` (parse a\nrequirements doc into testable items), `gap-analysis`, and `fill-gaps`.\n\nRate limit: 20 generations per hour per IP.\n","tags":["Public Test Case Generator"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["requirements"],"properties":{"requirements":{"type":"string","minLength":20,"description":"User stories, acceptance criteria, or product description"},"mode":{"type":"string","enum":["agentic","generate","extract-requirements","gap-analysis","fill-gaps"],"default":"agentic"},"scope":{"type":"string","enum":["full","requirements","user-stories","api","accessibility","security","performance"],"default":"full"},"testTypes":{"type":"array","items":{"type":"string","enum":["functional","regression","integration","e2e","accessibility","security","performance","boundary","negative","smoke"]}},"priority":{"type":"string","enum":["all","critical","high","medium","low"],"default":"all"},"format":{"type":"string","enum":["standard","gherkin","bdd"],"default":"standard"},"maxTestCases":{"type":"integer","minimum":1,"maximum":500,"default":100},"context":{"type":"string","description":"Additional context (constraints, tech stack, etc.)"},"stream":{"type":"boolean","default":false,"description":"When true, dispatch to background worker and return executionId"},"existingTestCases":{"type":"array","description":"For mode=gap-analysis / fill-gaps","items":{"type":"object"}},"gaps":{"type":"array","description":"For mode=fill-gaps","items":{"type":"object"}},"uploadedContent":{"type":"string"},"uploadedFileName":{"type":"string"},"userKbIds":{"type":"array","items":{"type":"string"}},"codeContent":{"type":"string"},"codeLanguage":{"type":"string"},"sessionId":{"type":"string","description":"Reuse an existing session; otherwise a new session is created"},"userEmail":{"type":"string","format":"email"}}},"examples":{"agenticStream":{"summary":"Agentic mode with WebSocket streaming","value":{"requirements":"User can sign up with email + password, must verify email before logging in.","mode":"agentic","stream":true,"maxTestCases":30,"userEmail":"qa-lead@acme.com"}},"syncGenerate":{"summary":"Synchronous single-shot generation","value":{"requirements":"Checkout flow: cart → address → payment → confirmation","mode":"generate","scope":"full","maxTestCases":20}}}}}},"responses":{"200":{"description":"Result depends on `stream`. `stream: true` returns an executionId\nfor WebSocket subscription. `stream: false` returns the test cases\ninline.\n","content":{"application/json":{"schema":{"oneOf":[{"type":"object","description":"Streaming response, subscribe to WebSocket","properties":{"executionId":{"type":"string"},"sessionId":{"type":"string"},"message":{"type":"string"}}},{"type":"object","description":"Synchronous response, test cases inline","properties":{"success":{"type":"boolean"},"testCases":{"type":"array","items":{"$ref":"#/components/schemas/PublicTestCase"}},"summary":{"type":"object","properties":{"total":{"type":"integer"},"byPriority":{"type":"object"},"byType":{"type":"object"}}},"sessionId":{"type":"string"}}}]}}}},"400":{"description":"Validation failed (e.g. requirements <20 chars)"},"429":{"description":"Rate limit exceeded (20 generations/hour/IP)"},"500":{"description":"Generation failed"}}}},"/api/public/test-cases/export":{"post":{"operationId":"publicTestCaseExport","summary":"Export test cases to Jira/TestRail/Azure/CSV/Gherkin/JSON","description":"Renders an array of test cases into one of six deliverable formats and\nreturns it as a downloadable file. Use the `Content-Disposition` header\nto obtain the filename. Rate limit: 50 exports per hour per IP.\n","tags":["Public Test Case Export"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["testCases","format"],"properties":{"testCases":{"type":"array","items":{"$ref":"#/components/schemas/PublicTestCase"}},"format":{"type":"string","enum":["csv","gherkin","json","jira-xray","testrail","azure-devops"]},"projectName":{"type":"string","default":"GoOmni-Generated-Tests"}}}}}},"responses":{"200":{"description":"Export file (binary)","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}},"headers":{"Content-Disposition":{"schema":{"type":"string","example":"attachment; filename=\"test-cases.csv\""}}}},"400":{"description":"Invalid format or test cases"},"429":{"description":"Rate limit exceeded (50 exports/hour/IP)"}}}},"/api/public/test-cases/sessions":{"get":{"operationId":"publicListSessions","summary":"List generation sessions for an email","description":"Returns up to 20 most recent sessions for a given email address.","tags":["Public Test Sessions"],"security":[],"parameters":[{"name":"email","in":"query","required":true,"schema":{"type":"string","format":"email"}}],"responses":{"200":{"description":"Sessions list","content":{"application/json":{"schema":{"type":"object","properties":{"sessions":{"type":"array","items":{"type":"object","properties":{"sessionId":{"type":"string"},"title":{"type":"string"},"status":{"type":"string"},"totalTestCases":{"type":"integer"},"turnCount":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}}}}}}},"400":{"description":"Missing email parameter"}}},"post":{"operationId":"publicCreateSession","summary":"Create a generation session","description":"Pre-creates an empty session you can later attach generations and edits to.","tags":["Public Test Sessions"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","requirements"],"properties":{"title":{"type":"string","minLength":1,"maxLength":200},"requirements":{"type":"string","minLength":20},"userEmail":{"type":"string","format":"email"},"scope":{"type":"string"},"format":{"type":"string"},"maxTestCases":{"type":"integer"},"uploadedFileName":{"type":"string"}}}}}},"responses":{"200":{"description":"Session created","content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string"},"title":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"string"}}}}}}}}},"/api/public/test-cases/sessions/{sessionId}":{"get":{"operationId":"publicGetSession","summary":"Get full session (requirements, conversation, test cases, events)","tags":["Public Test Sessions"],"security":[],"responses":{"200":{"description":"Session detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicSessionDetail"}}}},"404":{"description":"Session not found"}}},"post":{"operationId":"publicRefineSession","summary":"Refine the session with a follow-up message (multi-turn)","description":"Adds a user turn to the conversation and dispatches a refinement run.\nReturns an `executionId`, subscribe via WebSocket for streaming events.\n","tags":["Public Test Sessions"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","minLength":5,"description":"Follow-up instruction (e.g. \"Add 5 more negative cases for password reset\")"},"scope":{"type":"string"},"format":{"type":"string"},"maxTestCases":{"type":"integer"}}}}}},"responses":{"200":{"description":"Refinement dispatched","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"executionId":{"type":"string"},"sessionId":{"type":"string"},"message":{"type":"string"}}}}}},"400":{"description":"Validation failed"},"404":{"description":"Session not found"}}},"patch":{"operationId":"publicPatchSessionTestCases","summary":"Replace the session's test cases (manual edits)","description":"Persists inline edits made in the UI (title, description, steps, priority,\ntags). The full test cases array is replaced atomically, call this from\na debounced autosave loop.\n","tags":["Public Test Sessions"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["testCases"],"properties":{"testCases":{"type":"array","maxItems":500,"items":{"$ref":"#/components/schemas/PublicTestCase"}}}}}}},"responses":{"200":{"description":"Test cases replaced","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"sessionId":{"type":"string"},"testCaseCount":{"type":"integer"},"updatedAt":{"type":"string"}}}}}},"404":{"description":"Session not found"}}}},"/api/public/test-cases/execute":{"post":{"operationId":"publicExecuteTestCases","summary":"Dispatch a hosted browser run for selected test cases","description":"Spins up Headless Chromium in AWS Lambda, navigates to your `config.url`,\nand runs each selected test case. Each prose step is interpreted by Claude\ninto typed browser actions (`goto`, `click`, `fill`, `wait_for_selector`,\n`assert_text`, etc.), executed, and verified. Each step is captured as a\nPNG screenshot and uploaded to S3.\n\nReturns immediately with an `executionId`. Subscribe via WebSocket\n(`{action:\"subscribe\", executionId}`) to receive `execution_start`,\n`case_start`, `step_start`, `step_complete`, `case_complete`, and\n`execution_complete` events. When the run completes, fetch\n`GET /api/public/test-cases/executions/{executionId}` for signed evidence URLs.\n\n**Free-tier limit:** 5 executions per hour per email.\n**Per-case timeout:** 240s. **Per-step timeout:** 30s.\n","tags":["Public Hosted Execution"],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sessionId","testCaseIds","config"],"properties":{"sessionId":{"type":"string"},"testCaseIds":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string"},"description":"IDs of cases (within the session) to execute"},"testType":{"type":"string","enum":["web","rest_api","soap_api","graphql","a11y","perf"],"default":"web","description":"Currently only `web` is implemented. The other test types are\nreserved by the Executor abstraction and return 501 until their\nexecutors ship.\n"},"config":{"type":"object","description":"Polymorphic, depends on `testType`. For `web` see properties below.","properties":{"url":{"type":"string","format":"uri"},"browser":{"type":"string","enum":["chromium","firefox","webkit"],"default":"chromium"},"viewport":{"type":"object","properties":{"width":{"type":"integer"},"height":{"type":"integer"}}}},"required":["url"]},"parallel":{"type":"boolean","default":false,"description":"Reserved, currently sequential"},"userEmail":{"type":"string","format":"email","description":"Used for free-tier rate limiting (5/hour/email)"}}},"examples":{"singleCase":{"summary":"Run one case against a target URL","value":{"sessionId":"tcg-1730000000000-abc123","testCaseIds":["TC-001"],"testType":"web","config":{"url":"https://app.example.com","browser":"chromium"},"userEmail":"qa-lead@acme.com"}},"bulkRun":{"summary":"Run a smoke suite","value":{"sessionId":"tcg-1730000000000-abc123","testCaseIds":["TC-001","TC-002","TC-003","TC-007"],"testType":"web","config":{"url":"https://staging.example.com","browser":"chromium","viewport":{"width":1440,"height":900}},"userEmail":"qa-lead@acme.com"}}}}}},"responses":{"200":{"description":"Execution dispatched","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"executionId":{"type":"string"},"sessionId":{"type":"string"},"testType":{"type":"string"},"totalCases":{"type":"integer"},"missingTestCases":{"type":"array","items":{"type":"string"},"description":"IDs that weren't found in the session"},"message":{"type":"string"}}},"example":{"success":true,"executionId":"f15c68f0-b7ed-4767-b58e-c6f3de97ee18","sessionId":"tcg-1730000000000-abc123","testType":"web","totalCases":1,"message":"Execution dispatched. Subscribe to executionId via WebSocket for real-time updates."}}}},"400":{"description":"Validation failed (no matching test cases, bad config, etc.)"},"404":{"description":"Session not found"},"429":{"description":"Free-tier rate limit exceeded (5 executions/hour/email)"},"501":{"description":"Executor for the requested testType is not yet available"},"502":{"description":"Worker dispatch failed"}}}},"/api/public/test-cases/executions/{executionId}":{"get":{"operationId":"publicGetExecution","summary":"Get execution detail with signed evidence URLs","description":"Returns the execution metadata, per-test-case results, and pre-signed S3\nURLs (1-hour TTL) for video, screenshots, console logs, network HAR, and\nmanifest/timeline JSON.\n","tags":["Public Hosted Execution"],"security":[],"responses":{"200":{"description":"Execution detail","content":{"application/json":{"schema":{"type":"object","properties":{"execution":{"type":"object","properties":{"executionId":{"type":"string"},"sessionId":{"type":"string"},"testType":{"type":"string","enum":["web","rest_api","soap_api","graphql","a11y","perf"]},"status":{"type":"string","enum":["queued","running","passed","failed","partial","error","cancelled"]},"totalCases":{"type":"integer"},"passedCount":{"type":"integer"},"failedCount":{"type":"integer"},"skippedCount":{"type":"integer"},"errorCount":{"type":"integer"},"browser":{"type":"string"},"baseUrl":{"type":"string"},"targetConfig":{"type":"object"},"manifestUrl":{"type":"string","description":"Signed URL to manifest.json (1h TTL)"},"timelineUrl":{"type":"string","description":"Signed URL to timeline.json (1h TTL)"},"queuedAt":{"type":"string","format":"date-time"},"startedAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time"},"durationMs":{"type":"integer"},"errorMessage":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"cases":{"type":"array","items":{"type":"object","properties":{"testCaseId":{"type":"string"},"status":{"type":"string","enum":["passed","failed","skipped","error"]},"durationMs":{"type":"integer"},"stepResults":{"type":"array","items":{"$ref":"#/components/schemas/PublicStepResult"}},"assertionsTotal":{"type":"integer"},"assertionsPassed":{"type":"integer"},"assertionsFailed":{"type":"integer"},"errorMessage":{"type":"string"},"failedStep":{"type":"integer"},"videoUrl":{"type":"string","description":"Signed URL (1h TTL), null if video capture is off"},"consoleLogUrl":{"type":"string"},"networkHarUrl":{"type":"string"},"screenshotUrls":{"type":"array","items":{"type":"string"},"description":"Per-step PNG signed URLs (1h TTL)"},"startedAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time"}}}}}}}}},"404":{"description":"Execution not found"}}}},"/api/public/test-cases/sessions/{sessionId}/executions":{"get":{"operationId":"publicListSessionExecutions","summary":"List past hosted execution runs for a session","description":"Returns lightweight metadata for each prior run (status, counts, browser,\nbaseUrl, durationMs). Used by the execution-history panel on the public\npage. For the full result of a specific run, call\n`GET /api/public/test-cases/executions/{executionId}`.\n","tags":["Public Hosted Execution"],"security":[],"responses":{"200":{"description":"Execution history","content":{"application/json":{"schema":{"type":"object","properties":{"executions":{"type":"array","items":{"type":"object","properties":{"executionId":{"type":"string"},"testType":{"type":"string"},"status":{"type":"string"},"totalCases":{"type":"integer"},"passedCount":{"type":"integer"},"failedCount":{"type":"integer"},"skippedCount":{"type":"integer"},"errorCount":{"type":"integer"},"durationMs":{"type":"integer"},"parallel":{"type":"boolean"},"browser":{"type":"string"},"baseUrl":{"type":"string"},"queuedAt":{"type":"string","format":"date-time"},"startedAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}}}}}}}}}}}}