{"servers":[{"url":"https://qastudio.dev/api","description":"Production server"},{"url":"http://localhost:3000/api","description":"Development server"}],"openapi":"3.0.0","info":{"title":"QA Studio API","version":"1.0.0","description":"A comprehensive test management and reporting platform API.\n\n## Features\n\n- **Project Management**: Organize testing by projects with unique keys\n- **Test Organization**: Create hierarchical test suites and test cases\n- **Test Execution**: Plan and execute test runs across different environments\n- **Results Tracking**: Record detailed test results with steps, attachments, and metrics\n- **Milestone Planning**: Track testing progress against release milestones\n\n## Authentication\n\nMost endpoints require an API key. Create one under **Settings → API Keys**, then send it with every request using either header:\n\n```\nAuthorization: Bearer <your-api-key>\nX-API-Key: <your-api-key>\n```\n\nRequests made from the QA Studio web app are authenticated with your session cookie automatically.\n\n## Base URL\n\nProduction: `https://qastudio.dev/api`\nDevelopment: `http://localhost:3000/api`\n\t\t"},"tags":[{"name":"Projects","description":"Project management endpoints"},{"name":"Suites","description":"Test suite organization endpoints"},{"name":"Cases","description":"Test case management endpoints"},{"name":"Runs","description":"Test execution endpoints"},{"name":"Results","description":"Test result recording endpoints"},{"name":"Milestones","description":"Milestone tracking endpoints"},{"name":"Environments","description":"Environment configuration endpoints"},{"name":"Attachments","description":"File attachment endpoints"}],"components":{"schemas":{},"parameters":{}},"paths":{"/api/attachments":{"get":{"tags":["Attachments"],"summary":"List attachments","description":"Retrieve a paginated list of attachments with access control, optionally filtered by test case or test result","parameters":[{"schema":{"type":"string","description":"Filter by test case ID"},"required":false,"description":"Filter by test case ID","name":"testCaseId","in":"query"},{"schema":{"type":"string","description":"Filter by test result ID"},"required":false,"description":"Filter by test result ID","name":"testResultId","in":"query"},{"schema":{"type":"number","minimum":1,"default":1,"description":"Page number (default: 1)"},"required":false,"description":"Page number (default: 1)","name":"page","in":"query"},{"schema":{"type":"number","minimum":1,"maximum":100,"default":50,"description":"Results per page (default: 50)"},"required":false,"description":"Results per page (default: 50)","name":"limit","in":"query"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Attachment ID"},"filename":{"type":"string","description":"Storage filename"},"originalName":{"type":"string","description":"Original filename"},"mimeType":{"type":"string","description":"MIME type"},"size":{"type":"number","description":"File size in bytes"},"url":{"type":"string","description":"Public URL to access the file"},"testCaseId":{"type":"string","nullable":true,"description":"Linked test case ID"},"testResultId":{"type":"string","nullable":true,"description":"Linked test result ID"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"testCase":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"title":{"type":"string"}},"required":["id","title"],"description":"Linked test case details"},"testResult":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"testRun":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]}},"required":["id","testRun"],"description":"Linked test result details"}},"required":["id","filename","originalName","mimeType","size","url","testCaseId","testResultId","testCase","testResult"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"},"hasMore":{"type":"boolean"}},"required":["page","limit","total","totalPages","hasMore"]}},"required":["data","pagination"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}},"post":{"tags":["Attachments"],"summary":"Upload attachment","description":"Upload an attachment (screenshot, log, video) and link it to a test case or test result. Accepts base64-encoded data.","requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Attachment filename (max 255 characters)"},"contentType":{"type":"string","description":"MIME type of the file"},"data":{"type":"string","description":"Base64-encoded file data"},"testCaseId":{"type":"string","format":"uuid","description":"Test case ID to link attachment to"},"testResultId":{"type":"string","format":"uuid","description":"Test result ID to link attachment to"},"type":{"type":"string","enum":["screenshot","video","log","trace","other"],"description":"Attachment type (screenshot, video, log, trace, other)"}},"required":["name","contentType","data"]}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Attachment filename (max 255 characters)"},"contentType":{"type":"string","description":"MIME type of the file"},"data":{"type":"string","description":"Base64-encoded file data"},"testCaseId":{"type":"string","format":"uuid","description":"Test case ID to link attachment to"},"testResultId":{"type":"string","format":"uuid","description":"Test result ID to link attachment to"},"type":{"type":"string","enum":["screenshot","video","log","trace","other"],"description":"Attachment type (screenshot, video, log, trace, other)"}},"required":["name","contentType","data"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Attachment filename (max 255 characters)"},"contentType":{"type":"string","description":"MIME type of the file"},"data":{"type":"string","description":"Base64-encoded file data"},"testCaseId":{"type":"string","format":"uuid","description":"Test case ID to link attachment to"},"testResultId":{"type":"string","format":"uuid","description":"Test result ID to link attachment to"},"type":{"type":"string","enum":["screenshot","video","log","trace","other"],"description":"Attachment type (screenshot, video, log, trace, other)"}},"required":["name","contentType","data"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"attachment":{"type":"object","properties":{"id":{"type":"string","description":"Attachment ID"},"filename":{"type":"string","description":"Storage filename"},"url":{"type":"string","description":"Public URL"},"size":{"type":"number","description":"File size in bytes"},"mimeType":{"type":"string","description":"MIME type"}},"required":["id","filename","url","size","mimeType"]}},"required":["attachment"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/api/attachments/{id}":{"get":{"tags":["Attachments"],"summary":"Get attachment details or download","description":"Retrieve attachment metadata or redirect to the attachment file. Use ?metadata=true to get JSON metadata only.","parameters":[{"schema":{"type":"string","description":"Attachment ID"},"required":true,"description":"Attachment ID","name":"id","in":"path"},{"schema":{"type":"string","enum":["true","false"],"description":"If true, returns JSON metadata instead of redirecting to file"},"required":false,"description":"If true, returns JSON metadata instead of redirecting to file","name":"metadata","in":"query"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Attachment ID"},"filename":{"type":"string","description":"Storage filename"},"originalName":{"type":"string","description":"Original filename"},"mimeType":{"type":"string","description":"MIME type"},"size":{"type":"number","description":"File size in bytes"},"url":{"type":"string","description":"Public URL to access the file"},"testCaseId":{"type":"string","nullable":true,"description":"Linked test case ID"},"testResultId":{"type":"string","nullable":true,"description":"Linked test result ID"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"testCase":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"title":{"type":"string"},"project":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"key":{"type":"string"},"createdBy":{"type":"string"},"teamId":{"type":"string","nullable":true},"team":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]}},"required":["id","name","key","createdBy","teamId","team"]}},"required":["id","title","project"],"description":"Associated test case"},"testResult":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"testCase":{"type":"object","properties":{"title":{"type":"string"}},"required":["title"]},"testRun":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"project":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"key":{"type":"string"},"createdBy":{"type":"string"},"teamId":{"type":"string","nullable":true},"team":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]}},"required":["id","name","key","createdBy","teamId","team"]}},"required":["id","name","project"]}},"required":["id","testCase","testRun"],"description":"Associated test result"}},"required":["id","filename","originalName","mimeType","size","url","testCaseId","testResultId","testCase","testResult"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/api/authenticator-tokens":{"get":{"tags":["Authenticator Tokens"],"summary":"List authenticator tokens","description":"Get all authenticator tokens for the authenticated user's team. The secret is never returned for security.","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Token ID"},"name":{"type":"string","description":"Token name"},"description":{"type":"string","nullable":true,"description":"Token description"},"issuer":{"type":"string","nullable":true,"description":"Issuer name"},"accountName":{"type":"string","nullable":true,"description":"Account name"},"algorithm":{"type":"string","description":"TOTP algorithm (SHA1, SHA256, SHA512)"},"digits":{"type":"number","description":"Number of digits in TOTP code"},"period":{"type":"number","description":"TOTP period in seconds"},"createdBy":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true}},"required":["id","email","firstName","lastName"],"description":"User who created the token"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"}},"required":["id","name","description","issuer","accountName","algorithm","digits","period","createdBy"]}}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}},"post":{"tags":["Authenticator Tokens"],"summary":"Create authenticator token","description":"Create a new authenticator token for the team. The secret will be encrypted before storage.","requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Token name"},"description":{"type":"string","description":"Token description"},"secret":{"type":"string","description":"Base32-encoded TOTP secret"},"issuer":{"type":"string","description":"Issuer name"},"accountName":{"type":"string","description":"Account name"},"algorithm":{"type":"string","enum":["SHA1","SHA256","SHA512"],"description":"TOTP algorithm"},"digits":{"type":"integer","minimum":6,"maximum":8,"description":"Number of digits in TOTP code"},"period":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"TOTP period in seconds"},"csrfToken":{"type":"string","description":"CSRF token for session-based auth"}},"required":["name","secret"]}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Token name"},"description":{"type":"string","description":"Token description"},"secret":{"type":"string","description":"Base32-encoded TOTP secret"},"issuer":{"type":"string","description":"Issuer name"},"accountName":{"type":"string","description":"Account name"},"algorithm":{"type":"string","enum":["SHA1","SHA256","SHA512"],"description":"TOTP algorithm"},"digits":{"type":"integer","minimum":6,"maximum":8,"description":"Number of digits in TOTP code"},"period":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"TOTP period in seconds"},"csrfToken":{"type":"string","description":"CSRF token for session-based auth"}},"required":["name","secret"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Token name"},"description":{"type":"string","description":"Token description"},"secret":{"type":"string","description":"Base32-encoded TOTP secret"},"issuer":{"type":"string","description":"Issuer name"},"accountName":{"type":"string","description":"Account name"},"algorithm":{"type":"string","enum":["SHA1","SHA256","SHA512"],"description":"TOTP algorithm"},"digits":{"type":"integer","minimum":6,"maximum":8,"description":"Number of digits in TOTP code"},"period":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"TOTP period in seconds"},"csrfToken":{"type":"string","description":"CSRF token for session-based auth"}},"required":["name","secret"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Token ID"},"name":{"type":"string","description":"Token name"},"description":{"type":"string","nullable":true,"description":"Token description"},"issuer":{"type":"string","nullable":true,"description":"Issuer name"},"accountName":{"type":"string","nullable":true,"description":"Account name"},"algorithm":{"type":"string","description":"TOTP algorithm (SHA1, SHA256, SHA512)"},"digits":{"type":"number","description":"Number of digits in TOTP code"},"period":{"type":"number","description":"TOTP period in seconds"},"createdBy":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true}},"required":["id","email","firstName","lastName"],"description":"User who created the token"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"}},"required":["id","name","description","issuer","accountName","algorithm","digits","period","createdBy"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/api/authenticator-tokens/{id}":{"delete":{"tags":["Authenticator Tokens"],"summary":"Delete authenticator token","description":"Permanently delete an authenticator token.","parameters":[{"schema":{"type":"string","description":"Token ID"},"required":true,"description":"Token ID","name":"id","in":"path"}],"requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"csrfToken":{"type":"string","description":"CSRF token for session-based auth"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"csrfToken":{"type":"string","description":"CSRF token for session-based auth"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"csrfToken":{"type":"string","description":"CSRF token for session-based auth"}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}},"get":{"tags":["Authenticator Tokens"],"summary":"Get authenticator token","description":"Get details for a specific authenticator token. The secret is never returned for security.","parameters":[{"schema":{"type":"string","description":"Token ID"},"required":true,"description":"Token ID","name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Token ID"},"name":{"type":"string","description":"Token name"},"description":{"type":"string","nullable":true,"description":"Token description"},"issuer":{"type":"string","nullable":true,"description":"Issuer name"},"accountName":{"type":"string","nullable":true,"description":"Account name"},"algorithm":{"type":"string","description":"TOTP algorithm (SHA1, SHA256, SHA512)"},"digits":{"type":"number","description":"Number of digits in TOTP code"},"period":{"type":"number","description":"TOTP period in seconds"},"createdBy":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true}},"required":["id","email","firstName","lastName"],"description":"User who created the token"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"}},"required":["id","name","description","issuer","accountName","algorithm","digits","period","createdBy"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}},"patch":{"tags":["Authenticator Tokens"],"summary":"Update authenticator token","description":"Update an authenticator token. All fields are optional.","parameters":[{"schema":{"type":"string","description":"Token ID"},"required":true,"description":"Token ID","name":"id","in":"path"}],"requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Token name"},"description":{"type":"string","description":"Token description"},"secret":{"type":"string","description":"Base32-encoded TOTP secret"},"issuer":{"type":"string","description":"Issuer name"},"accountName":{"type":"string","description":"Account name"},"algorithm":{"type":"string","enum":["SHA1","SHA256","SHA512"],"description":"TOTP algorithm"},"digits":{"type":"integer","minimum":6,"maximum":8,"description":"Number of digits in TOTP code"},"period":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"TOTP period in seconds"},"csrfToken":{"type":"string","description":"CSRF token for session-based auth"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Token name"},"description":{"type":"string","description":"Token description"},"secret":{"type":"string","description":"Base32-encoded TOTP secret"},"issuer":{"type":"string","description":"Issuer name"},"accountName":{"type":"string","description":"Account name"},"algorithm":{"type":"string","enum":["SHA1","SHA256","SHA512"],"description":"TOTP algorithm"},"digits":{"type":"integer","minimum":6,"maximum":8,"description":"Number of digits in TOTP code"},"period":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"TOTP period in seconds"},"csrfToken":{"type":"string","description":"CSRF token for session-based auth"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Token name"},"description":{"type":"string","description":"Token description"},"secret":{"type":"string","description":"Base32-encoded TOTP secret"},"issuer":{"type":"string","description":"Issuer name"},"accountName":{"type":"string","description":"Account name"},"algorithm":{"type":"string","enum":["SHA1","SHA256","SHA512"],"description":"TOTP algorithm"},"digits":{"type":"integer","minimum":6,"maximum":8,"description":"Number of digits in TOTP code"},"period":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"TOTP period in seconds"},"csrfToken":{"type":"string","description":"CSRF token for session-based auth"}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Token ID"},"name":{"type":"string","description":"Token name"},"description":{"type":"string","nullable":true,"description":"Token description"},"issuer":{"type":"string","nullable":true,"description":"Issuer name"},"accountName":{"type":"string","nullable":true,"description":"Account name"},"algorithm":{"type":"string","description":"TOTP algorithm (SHA1, SHA256, SHA512)"},"digits":{"type":"number","description":"Number of digits in TOTP code"},"period":{"type":"number","description":"TOTP period in seconds"},"createdBy":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true}},"required":["id","email","firstName","lastName"],"description":"User who created the token"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"}},"required":["id","name","description","issuer","accountName","algorithm","digits","period","createdBy"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/api/authenticator-tokens/{id}/code":{"get":{"tags":["Authenticator Tokens"],"summary":"Generate TOTP code","description":"Generate the current TOTP code for an authenticator token. The code rotates based on the configured period.","parameters":[{"schema":{"type":"string","description":"Token ID"},"required":true,"description":"Token ID","name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","description":"Current TOTP code"},"timeRemaining":{"type":"number","description":"Seconds until next code"},"period":{"type":"number","description":"TOTP period in seconds"},"digits":{"type":"number","description":"Number of digits in code"},"tokenId":{"type":"string","description":"Token ID"},"tokenName":{"type":"string","description":"Token name"}},"required":["code","timeRemaining","period","digits","tokenId","tokenName"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/api/authenticator-tokens/codes":{"get":{"tags":["Authenticator Tokens"],"summary":"Generate TOTP codes for all team tokens","description":"Generate current TOTP codes for all authenticator tokens belonging to the user's team. Returns a map of token IDs to their TOTP codes. This is more efficient than calling the individual code endpoint for each token.","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object","properties":{"code":{"type":"string","description":"Current TOTP code"},"timeRemaining":{"type":"number","description":"Seconds until next code"},"period":{"type":"number","description":"TOTP period in seconds"},"digits":{"type":"number","description":"Number of digits in code"},"tokenId":{"type":"string","description":"Token ID"},"tokenName":{"type":"string","description":"Token name"}},"required":["code","timeRemaining","period","digits","tokenId","tokenName"]}}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/api/cases/{testCaseId}":{"patch":{"tags":["Cases"],"summary":"Update a test case","description":"Update test case fields including title, steps, priority, and automation status.","parameters":[{"schema":{"type":"string"},"required":true,"name":"testCaseId","in":"path"}],"requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"Test case title"},"description":{"type":"string","nullable":true,"description":"Detailed test case description"},"preconditions":{"type":"string","nullable":true,"description":"Pre-requisites before executing"},"steps":{"anyOf":[{"type":"string","description":"Legacy plain-text test steps"},{"type":"array","items":{"type":"object","properties":{"action":{"type":"string","minLength":1,"description":"Step action/description"},"expectedResult":{"type":"string","description":"Expected result for this step"},"order":{"type":"integer","minimum":0,"description":"Step order (auto-calculated if not provided)"}},"required":["action"]},"minItems":1,"maxItems":100,"description":"Structured test execution steps (max 100 steps)"},{"nullable":true}],"description":"Test execution steps (plain text or structured array)"},"expectedResult":{"type":"string","nullable":true,"description":"Expected test outcome"},"priority":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"],"description":"Test case priority"},"type":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"],"description":"Test type"},"automationStatus":{"type":"string","enum":["AUTOMATED","NOT_AUTOMATED","CANDIDATE"],"description":"Automation status"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"Test case title"},"description":{"type":"string","nullable":true,"description":"Detailed test case description"},"preconditions":{"type":"string","nullable":true,"description":"Pre-requisites before executing"},"steps":{"anyOf":[{"type":"string","description":"Legacy plain-text test steps"},{"type":"array","items":{"type":"object","properties":{"action":{"type":"string","minLength":1,"description":"Step action/description"},"expectedResult":{"type":"string","description":"Expected result for this step"},"order":{"type":"integer","minimum":0,"description":"Step order (auto-calculated if not provided)"}},"required":["action"]},"minItems":1,"maxItems":100,"description":"Structured test execution steps (max 100 steps)"},{"nullable":true}],"description":"Test execution steps (plain text or structured array)"},"expectedResult":{"type":"string","nullable":true,"description":"Expected test outcome"},"priority":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"],"description":"Test case priority"},"type":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"],"description":"Test type"},"automationStatus":{"type":"string","enum":["AUTOMATED","NOT_AUTOMATED","CANDIDATE"],"description":"Automation status"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"description":"Test case title"},"description":{"type":"string","nullable":true,"description":"Detailed test case description"},"preconditions":{"type":"string","nullable":true,"description":"Pre-requisites before executing"},"steps":{"anyOf":[{"type":"string","description":"Legacy plain-text test steps"},{"type":"array","items":{"type":"object","properties":{"action":{"type":"string","minLength":1,"description":"Step action/description"},"expectedResult":{"type":"string","description":"Expected result for this step"},"order":{"type":"integer","minimum":0,"description":"Step order (auto-calculated if not provided)"}},"required":["action"]},"minItems":1,"maxItems":100,"description":"Structured test execution steps (max 100 steps)"},{"nullable":true}],"description":"Test execution steps (plain text or structured array)"},"expectedResult":{"type":"string","nullable":true,"description":"Expected test outcome"},"priority":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"],"description":"Test case priority"},"type":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"],"description":"Test type"},"automationStatus":{"type":"string","enum":["AUTOMATED","NOT_AUTOMATED","CANDIDATE"],"description":"Automation status"}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"preconditions":{"type":"string","nullable":true},"steps":{"nullable":true,"description":"Plain-text string or structured step array"},"expectedResult":{"type":"string","nullable":true},"priority":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"]},"type":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"]},"automationStatus":{"type":"string","enum":["AUTOMATED","NOT_AUTOMATED","CANDIDATE"]},"tags":{"type":"array","items":{"type":"string"}},"projectId":{"type":"string"},"suiteId":{"type":"string","nullable":true},"createdBy":{"type":"string"},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true},"project":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"key":{"type":"string"}},"required":["id","name","key"]},"suite":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"creator":{"type":"object","properties":{"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"email":{"type":"string"},"imageUrl":{"type":"string","nullable":true}},"required":["firstName","lastName","email","imageUrl"]}},"required":["id","title","description","preconditions","expectedResult","priority","type","automationStatus","tags","projectId","suiteId","createdBy","project","suite","creator"]}}}},"400":{"description":"Title is required"},"404":{"description":"Test case not found"},"500":{"description":"Failed to update test case"}}}},"/api/cases/{testCaseId}/results":{"get":{"tags":["Cases"],"summary":"Get results for a test case","description":"Retrieve paginated test results for a specific test case, including execution history, attachments, and steps.","parameters":[{"schema":{"type":"string","description":"Test case ID"},"required":true,"description":"Test case ID","name":"testCaseId","in":"path"},{"schema":{"type":"number","minimum":1,"default":1,"description":"Page number (default: 1)"},"required":false,"description":"Page number (default: 1)","name":"page","in":"query"},{"schema":{"type":"number","minimum":1,"maximum":100,"default":10,"description":"Results per page (default: 10)"},"required":false,"description":"Results per page (default: 10)","name":"limit","in":"query"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Test result ID"},"testCaseId":{"type":"string","description":"Test case ID"},"testRunId":{"type":"string","description":"Test run ID"},"status":{"type":"string","enum":["PASSED","FAILED","BLOCKED","SKIPPED","RETEST","UNTESTED"],"description":"Result status"},"fullTitle":{"type":"string","nullable":true,"description":"Full hierarchical test title"},"duration":{"type":"number","nullable":true,"description":"Test duration in milliseconds"},"errorMessage":{"type":"string","nullable":true,"description":"Error message"},"stackTrace":{"type":"string","nullable":true,"description":"Stack trace"},"executedBy":{"type":"string","description":"User ID who executed the test"},"executedAt":{"type":"string","nullable":true,"description":"ISO 8601 execution timestamp"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"executor":{"type":"object","properties":{"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"email":{"type":"string"}},"required":["firstName","lastName","email"],"description":"User who executed the test"},"testRun":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"description":"Associated test run"},"attachments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"filename":{"type":"string"},"originalName":{"type":"string"},"mimeType":{"type":"string"},"size":{"type":"number"},"url":{"type":"string"},"createdAt":{"type":"string","nullable":true}},"required":["id","filename","originalName","mimeType","size","url"]},"description":"Test attachments"},"steps":{"type":"array","items":{"nullable":true},"description":"Test execution steps (hierarchical)"}},"required":["id","testCaseId","testRunId","status","fullTitle","duration","errorMessage","stackTrace","executedBy","testRun","attachments","steps"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"},"hasMore":{"type":"boolean"}},"required":["page","limit","total","totalPages","hasMore"]}},"required":["data","pagination"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/api/config":{"get":{"tags":["Configuration"],"summary":"Get public deployment configuration","description":"Returns minimal deployment mode information (self-hosted vs SaaS) to help frontends conditionally render billing/pricing UI. This endpoint is public and does not require authentication. Rate limited to 100 requests per minute per IP.","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"selfHosted":{"type":"boolean","description":"Whether this is a self-hosted deployment"},"billing":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether billing/payment features are enabled"}},"required":["enabled"],"description":"Billing configuration"}},"required":["selfHosted","billing"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/api/integrations/twilio":{"delete":{"tags":["Twilio Integration"],"summary":"Remove Twilio configuration","description":"Remove Twilio configuration from the team. Requires OWNER, ADMIN, or MANAGER role.","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Success message"}},"required":["message"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"403":{"description":"Insufficient permissions"},"404":{"description":"Team not found"}}},"get":{"tags":["Twilio Integration"],"summary":"Get Twilio configuration","description":"Get Twilio configuration for the authenticated user's team. Requires Pro or Enterprise plan.","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"twilioEnabled":{"type":"boolean","description":"Whether Twilio integration is enabled"},"twilioPhoneNumber":{"type":"string","nullable":true,"description":"Twilio phone number in E.164 format"},"twilioMessagingUrl":{"type":"string","nullable":true,"description":"Optional Messaging Service SID or webhook URL"},"twilioConfiguredAt":{"type":"string","nullable":true,"description":"When Twilio was last configured"},"twilioConfiguredBy":{"type":"string","nullable":true,"description":"User ID who configured Twilio"},"hasAccountSid":{"type":"boolean","description":"Whether Account SID is configured"},"hasAuthToken":{"type":"boolean","description":"Whether Auth Token is configured"}},"required":["twilioEnabled","twilioPhoneNumber","twilioMessagingUrl","twilioConfiguredBy","hasAccountSid","hasAuthToken"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"403":{"description":"Twilio integration requires Pro or Enterprise plan"},"404":{"description":"Team not found"}}},"post":{"tags":["Twilio Integration"],"summary":"Configure Twilio integration","description":"Configure or update Twilio integration for the team. Requires OWNER, ADMIN, or MANAGER role. Pro/Enterprise plans only.","requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"accountSid":{"type":"string","minLength":1,"pattern":"^AC[a-fA-F0-9]{32}$","description":"Twilio Account SID (starts with AC followed by 32 hex characters)"},"authToken":{"type":"string","minLength":1,"description":"Twilio Auth Token (will be encrypted)"},"phoneNumber":{"type":"string","pattern":"^\\+[1-9]\\d{1,14}$","description":"Phone number in E.164 format (e.g., +15551234567)"},"messagingUrl":{"type":"string","description":"Optional Messaging Service SID or HTTPS webhook URL"}},"required":["accountSid","authToken","phoneNumber"]}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"accountSid":{"type":"string","minLength":1,"pattern":"^AC[a-fA-F0-9]{32}$","description":"Twilio Account SID (starts with AC followed by 32 hex characters)"},"authToken":{"type":"string","minLength":1,"description":"Twilio Auth Token (will be encrypted)"},"phoneNumber":{"type":"string","pattern":"^\\+[1-9]\\d{1,14}$","description":"Phone number in E.164 format (e.g., +15551234567)"},"messagingUrl":{"type":"string","description":"Optional Messaging Service SID or HTTPS webhook URL"}},"required":["accountSid","authToken","phoneNumber"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"accountSid":{"type":"string","minLength":1,"pattern":"^AC[a-fA-F0-9]{32}$","description":"Twilio Account SID (starts with AC followed by 32 hex characters)"},"authToken":{"type":"string","minLength":1,"description":"Twilio Auth Token (will be encrypted)"},"phoneNumber":{"type":"string","pattern":"^\\+[1-9]\\d{1,14}$","description":"Phone number in E.164 format (e.g., +15551234567)"},"messagingUrl":{"type":"string","description":"Optional Messaging Service SID or HTTPS webhook URL"}},"required":["accountSid","authToken","phoneNumber"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"twilioEnabled":{"type":"boolean"},"twilioPhoneNumber":{"type":"string"},"twilioMessagingUrl":{"type":"string","nullable":true},"twilioConfiguredAt":{"type":"string","nullable":true},"twilioConfiguredBy":{"type":"string"}},"required":["message","twilioEnabled","twilioPhoneNumber","twilioMessagingUrl","twilioConfiguredBy"]}}}},"400":{"description":"Invalid request - check required fields and phone number format"},"403":{"description":"Insufficient permissions or plan upgrade required"},"404":{"description":"Team not found"}}}},"/api/integrations/twilio/sms/messages":{"get":{"tags":["Twilio Integration"],"summary":"Get SMS messages","description":"Get recent SMS messages from Twilio. Pro/Enterprise plans only.","parameters":[{"schema":{"type":"number","minimum":1,"maximum":100,"description":"Maximum number of messages to return (max 100)"},"required":false,"description":"Maximum number of messages to return (max 100)","name":"limit","in":"query"},{"schema":{"type":"string","enum":["inbound","outbound"],"description":"Filter by message direction"},"required":false,"description":"Filter by message direction","name":"direction","in":"query"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"messages":{"type":"array","items":{"type":"object","properties":{"sid":{"type":"string"},"from":{"type":"string"},"to":{"type":"string"},"body":{"type":"string"},"status":{"type":"string"},"direction":{"type":"string","enum":["inbound","outbound-api","outbound-call","outbound-reply"]},"dateCreated":{"type":"string"},"dateSent":{"type":"string","nullable":true},"dateUpdated":{"type":"string"},"numMedia":{"type":"number"},"errorCode":{"type":"string","nullable":true},"errorMessage":{"type":"string","nullable":true}},"required":["sid","from","to","body","status","direction","dateCreated","dateSent","dateUpdated","numMedia","errorCode","errorMessage"]}},"total":{"type":"number"},"phoneNumber":{"type":"string"}},"required":["messages","total","phoneNumber"]}}}},"400":{"description":"Twilio is not configured for this team"},"403":{"description":"Twilio integration requires Pro or Enterprise plan"},"404":{"description":"Team not found"},"500":{"description":"Failed to fetch messages from Twilio"}}}},"/api/integrations/twilio/sms/send":{"post":{"tags":["Twilio Integration"],"summary":"Send SMS message","description":"Send an SMS message via Twilio. Pro/Enterprise plans only.","requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","pattern":"^\\+[1-9]\\d{1,14}$","description":"Recipient phone number in E.164 format"},"body":{"type":"string","minLength":1,"maxLength":1600,"description":"SMS message body (max 1600 characters)"}},"required":["to","body"]}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"to":{"type":"string","pattern":"^\\+[1-9]\\d{1,14}$","description":"Recipient phone number in E.164 format"},"body":{"type":"string","minLength":1,"maxLength":1600,"description":"SMS message body (max 1600 characters)"}},"required":["to","body"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"to":{"type":"string","pattern":"^\\+[1-9]\\d{1,14}$","description":"Recipient phone number in E.164 format"},"body":{"type":"string","minLength":1,"maxLength":1600,"description":"SMS message body (max 1600 characters)"}},"required":["to","body"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"messageSid":{"type":"string","description":"Twilio message SID"},"status":{"type":"string","description":"Message status (queued, sent, etc.)"},"to":{"type":"string"},"from":{"type":"string"},"body":{"type":"string"},"dateCreated":{"type":"string"}},"required":["success","messageSid","status","to","from","body","dateCreated"]}}}},"400":{"description":"Invalid request or Twilio not configured"},"403":{"description":"Twilio integration requires Pro or Enterprise plan"},"404":{"description":"Team not found"},"429":{"description":"Rate limit exceeded. Too many SMS messages sent."},"500":{"description":"Failed to send SMS"}}}},"/api/projects":{"get":{"tags":["Projects"],"summary":"List all projects","description":"Returns all projects the authenticated user has access to (projects they created or belong to their team)","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique project identifier"},"name":{"type":"string","description":"Project name"},"description":{"type":"string","nullable":true,"description":"Project description"},"key":{"type":"string","description":"Unique project key (e.g., PROJ)"},"createdBy":{"type":"string","description":"User ID who created the project"},"teamId":{"type":"string","nullable":true,"description":"Team ID if project belongs to a team"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"},"_count":{"type":"object","properties":{"testCases":{"type":"number","description":"Number of test cases in the project"},"testRuns":{"type":"number","description":"Number of test runs in the project"},"testSuites":{"type":"number","description":"Number of test suites in the project"}},"required":["testCases","testRuns","testSuites"],"description":"Aggregate counts for project resources"}},"required":["id","name","description","key","createdBy","teamId","_count"]}}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}},"post":{"tags":["Projects"],"summary":"Create a new project","description":"Creates a new project. The project key must be unique and will be automatically converted to uppercase.","requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":"string"},"key":{"type":"string","minLength":3,"maxLength":10,"pattern":"^[A-Z0-9]+$"}},"required":["name","key"]}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":"string"},"key":{"type":"string","minLength":3,"maxLength":10,"pattern":"^[A-Z0-9]+$"}},"required":["name","key"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":"string"},"key":{"type":"string","minLength":3,"maxLength":10,"pattern":"^[A-Z0-9]+$"}},"required":["name","key"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"key":{"type":"string"},"createdBy":{"type":"string"},"teamId":{"type":"string","nullable":true},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true}},"required":["id","name","description","key","createdBy","teamId"]}}}},"400":{"description":"Name and key are required"},"409":{"description":"Project key already exists"},"500":{"description":"Failed to create project"}}}},"/api/projects/{projectId}/cases":{"get":{"tags":["Projects"],"summary":"List test cases for a project","description":"Retrieve paginated test cases for a specific project with optional filtering by suite, priority, type, automation status, and tags.","parameters":[{"schema":{"type":"string","description":"Project ID"},"required":true,"description":"Project ID","name":"projectId","in":"path"},{"schema":{"type":"number","minimum":1,"default":1,"description":"Page number (default: 1)"},"required":false,"description":"Page number (default: 1)","name":"page","in":"query"},{"schema":{"type":"number","minimum":1,"maximum":100,"default":50,"description":"Results per page (default: 50)"},"required":false,"description":"Results per page (default: 50)","name":"limit","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Search in test case title and description"},"required":false,"description":"Search in test case title and description","name":"search","in":"query"},{"schema":{"type":"string","description":"Filter by test suite ID"},"required":false,"description":"Filter by test suite ID","name":"suiteId","in":"query"},{"schema":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"],"description":"Filter by priority"},"required":false,"description":"Filter by priority","name":"priority","in":"query"},{"schema":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"],"description":"Filter by test type"},"required":false,"description":"Filter by test type","name":"type","in":"query"},{"schema":{"type":"string","enum":["AUTOMATED","NOT_AUTOMATED","CANDIDATE"],"description":"Filter by automation status"},"required":false,"description":"Filter by automation status","name":"automationStatus","in":"query"},{"schema":{"type":"string","description":"Filter by tags (comma-separated)"},"required":false,"description":"Filter by tags (comma-separated)","name":"tags","in":"query"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Test case ID"},"title":{"type":"string","description":"Test case title"},"description":{"type":"string","nullable":true,"description":"Test case description"},"preconditions":{"type":"string","nullable":true,"description":"Setup requirements"},"steps":{"nullable":true,"description":"Array of test steps"},"expectedResult":{"type":"string","nullable":true,"description":"Expected test result"},"priority":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"],"description":"Test case priority"},"type":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"],"description":"Test case type"},"automationStatus":{"type":"string","enum":["AUTOMATED","NOT_AUTOMATED","CANDIDATE"],"description":"Automation status"},"tags":{"type":"array","items":{"type":"string"},"description":"Test case tags"},"projectId":{"type":"string","description":"Project ID"},"suiteId":{"type":"string","nullable":true,"description":"Test suite ID"},"createdBy":{"type":"string","description":"User ID who created the test case"},"order":{"type":"number","description":"Display order"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"},"suite":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"description":"Associated test suite"},"_count":{"type":"object","properties":{"results":{"type":"number"},"attachments":{"type":"number"}},"required":["results","attachments"],"description":"Count of related records"}},"required":["id","title","description","preconditions","expectedResult","priority","type","automationStatus","tags","projectId","suiteId","createdBy","order","suite","_count"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"},"hasMore":{"type":"boolean"}},"required":["page","limit","total","totalPages","hasMore"]}},"required":["data","pagination"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}},"post":{"tags":["Cases"],"summary":"Create a test case","description":"Create a new test case with steps, expected results, and metadata. Optionally assign to a test suite.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500,"description":"Test case title"},"description":{"type":"string","maxLength":5000,"description":"Detailed test case description"},"preconditions":{"type":"string","description":"Pre-requisites before executing the test"},"steps":{"type":"array","items":{"type":"object","properties":{"action":{"type":"string","minLength":1,"description":"Step action/description"},"expectedResult":{"type":"string","description":"Expected result for this step"},"order":{"type":"integer","minimum":0,"description":"Step order (auto-calculated if not provided)"}},"required":["action"]},"minItems":1,"maxItems":100,"description":"Test execution steps (max 100 steps)"},"expectedResult":{"type":"string","description":"Overall expected test outcome"},"priority":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"],"description":"Test case priority"},"type":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"],"description":"Test type"},"automationStatus":{"type":"string","enum":["AUTOMATED","NOT_AUTOMATED","CANDIDATE"],"description":"Automation status"},"tags":{"type":"array","items":{"type":"string","maxLength":50,"pattern":"^[a-zA-Z0-9-_]+$"},"maxItems":10,"description":"Tags for categorization (max 10 tags, 50 chars each, alphanumeric only)"},"suiteId":{"type":"string","nullable":true,"description":"Parent test suite ID"}},"required":["title"]}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500,"description":"Test case title"},"description":{"type":"string","maxLength":5000,"description":"Detailed test case description"},"preconditions":{"type":"string","description":"Pre-requisites before executing the test"},"steps":{"type":"array","items":{"type":"object","properties":{"action":{"type":"string","minLength":1,"description":"Step action/description"},"expectedResult":{"type":"string","description":"Expected result for this step"},"order":{"type":"integer","minimum":0,"description":"Step order (auto-calculated if not provided)"}},"required":["action"]},"minItems":1,"maxItems":100,"description":"Test execution steps (max 100 steps)"},"expectedResult":{"type":"string","description":"Overall expected test outcome"},"priority":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"],"description":"Test case priority"},"type":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"],"description":"Test type"},"automationStatus":{"type":"string","enum":["AUTOMATED","NOT_AUTOMATED","CANDIDATE"],"description":"Automation status"},"tags":{"type":"array","items":{"type":"string","maxLength":50,"pattern":"^[a-zA-Z0-9-_]+$"},"maxItems":10,"description":"Tags for categorization (max 10 tags, 50 chars each, alphanumeric only)"},"suiteId":{"type":"string","nullable":true,"description":"Parent test suite ID"}},"required":["title"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500,"description":"Test case title"},"description":{"type":"string","maxLength":5000,"description":"Detailed test case description"},"preconditions":{"type":"string","description":"Pre-requisites before executing the test"},"steps":{"type":"array","items":{"type":"object","properties":{"action":{"type":"string","minLength":1,"description":"Step action/description"},"expectedResult":{"type":"string","description":"Expected result for this step"},"order":{"type":"integer","minimum":0,"description":"Step order (auto-calculated if not provided)"}},"required":["action"]},"minItems":1,"maxItems":100,"description":"Test execution steps (max 100 steps)"},"expectedResult":{"type":"string","description":"Overall expected test outcome"},"priority":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"],"description":"Test case priority"},"type":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"],"description":"Test type"},"automationStatus":{"type":"string","enum":["AUTOMATED","NOT_AUTOMATED","CANDIDATE"],"description":"Automation status"},"tags":{"type":"array","items":{"type":"string","maxLength":50,"pattern":"^[a-zA-Z0-9-_]+$"},"maxItems":10,"description":"Tags for categorization (max 10 tags, 50 chars each, alphanumeric only)"},"suiteId":{"type":"string","nullable":true,"description":"Parent test suite ID"}},"required":["title"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"testCase":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"preconditions":{"type":"string","nullable":true},"steps":{"type":"array","nullable":true,"items":{"type":"object","properties":{"action":{"type":"string"},"expectedResult":{"type":"string"},"order":{"type":"number"}},"required":["action"]}},"expectedResult":{"type":"string","nullable":true},"priority":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"]},"type":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"]},"automationStatus":{"type":"string","enum":["AUTOMATED","NOT_AUTOMATED","CANDIDATE"]},"tags":{"type":"array","items":{"type":"string"}},"projectId":{"type":"string"},"suiteId":{"type":"string","nullable":true},"createdBy":{"type":"string"},"order":{"type":"number"},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true},"creator":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true}},"required":["id","email","firstName","lastName"]}},"required":["id","title","description","preconditions","steps","expectedResult","priority","type","automationStatus","tags","projectId","suiteId","createdBy","order","creator"]}},"required":["testCase"]}}}},"400":{"description":"Invalid test suite or suite does not belong to project"},"401":{"description":"Authentication required"},"403":{"description":"You do not have permission to create test cases in this project"},"404":{"description":"Project not found"}}}},"/api/projects/{projectId}/cases/{id}":{"delete":{"tags":["Cases"],"summary":"Delete test case","description":"Delete a test case and all associated test results, attachments, and step results.","parameters":[{"schema":{"type":"string","description":"Project ID"},"required":true,"description":"Project ID","name":"projectId","in":"path"},{"schema":{"type":"string","description":"Test case ID"},"required":true,"description":"Test case ID","name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"Operation success status"},"message":{"type":"string","description":"Success message"}},"required":["success","message"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"403":{"description":"Access denied"},"404":{"description":"Test case or project not found"}}},"get":{"tags":["Projects"],"summary":"Get test case details","description":"Retrieve detailed information for a specific test case including recent results, attachments, and associated metadata.","parameters":[{"schema":{"type":"string","description":"Project ID"},"required":true,"description":"Project ID","name":"projectId","in":"path"},{"schema":{"type":"string","description":"Test case ID"},"required":true,"description":"Test case ID","name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Test case ID"},"title":{"type":"string","description":"Test case title"},"description":{"type":"string","nullable":true,"description":"Test case description"},"preconditions":{"type":"string","nullable":true,"description":"Setup requirements"},"steps":{"nullable":true,"description":"Array of test steps"},"expectedResult":{"type":"string","nullable":true,"description":"Expected test result"},"priority":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"],"description":"Test case priority"},"type":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"],"description":"Test case type"},"automationStatus":{"type":"string","enum":["AUTOMATED","NOT_AUTOMATED","CANDIDATE"],"description":"Automation status"},"tags":{"type":"array","items":{"type":"string"},"description":"Test case tags"},"projectId":{"type":"string","description":"Project ID"},"suiteId":{"type":"string","nullable":true,"description":"Test suite ID"},"createdBy":{"type":"string","description":"User ID who created the test case"},"order":{"type":"number","description":"Display order"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"},"suite":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"description":"Associated test suite"},"attachments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"filename":{"type":"string"},"originalName":{"type":"string"},"mimeType":{"type":"string"},"size":{"type":"number"},"url":{"type":"string"},"createdAt":{"type":"string","nullable":true}},"required":["id","filename","originalName","mimeType","size","url"]},"description":"Test case attachments"},"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["PASSED","FAILED","BLOCKED","SKIPPED","RETEST","UNTESTED"]},"executedAt":{"type":"string","nullable":true},"testRun":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"environment":{"type":"object","nullable":true,"properties":{"name":{"type":"string"}},"required":["name"]}},"required":["id","name","environment"]}},"required":["id","status","testRun"]},"description":"Recent test results (last 10)"},"_count":{"type":"object","properties":{"results":{"type":"number"},"attachments":{"type":"number"}},"required":["results","attachments"],"description":"Count of related records"}},"required":["id","title","description","preconditions","expectedResult","priority","type","automationStatus","tags","projectId","suiteId","createdBy","order","suite","attachments","results","_count"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/api/projects/{projectId}/environments":{"get":{"tags":["Environments"],"summary":"List environments","description":"Returns all testing environments for a project (Production, Staging, QA, etc.)","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"projectId":{"type":"string"},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true},"_count":{"type":"object","properties":{"testRuns":{"type":"number"}},"required":["testRuns"]}},"required":["id","name","description","projectId","_count"]}}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}},"post":{"tags":["Environments"],"summary":"Create an environment","description":"Create a new testing environment for organizing test runs by deployment target.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Environment name (e.g., Production, Staging, QA)"},"description":{"type":"string","description":"Optional environment description"}},"required":["name"]}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Environment name (e.g., Production, Staging, QA)"},"description":{"type":"string","description":"Optional environment description"}},"required":["name"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Environment name (e.g., Production, Staging, QA)"},"description":{"type":"string","description":"Optional environment description"}},"required":["name"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"projectId":{"type":"string"},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true}},"required":["id","name","description","projectId"]}}}},"400":{"description":"Name is required"},"404":{"description":"Project not found"},"409":{"description":"Environment name already exists in this project"},"500":{"description":"Failed to create environment"}}}},"/api/projects/{projectId}/environments/{id}":{"delete":{"tags":["Environments"],"summary":"Delete an environment","description":"Permanently delete a testing environment.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"404":{"description":"Environment not found"},"500":{"description":"Failed to delete environment"}}},"get":{"tags":["Environments"],"summary":"Get an environment","description":"Returns a single environment by ID with test run count.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"projectId":{"type":"string"},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true},"_count":{"type":"object","properties":{"testRuns":{"type":"number"}},"required":["testRuns"]}},"required":["id","name","description","projectId","_count"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"404":{"description":"Environment not found"},"500":{"description":"Failed to fetch environment"}}},"patch":{"tags":["Environments"],"summary":"Update an environment","description":"Update environment name or description.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Environment name"},"description":{"type":"string","description":"Environment description"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Environment name"},"description":{"type":"string","description":"Environment description"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Environment name"},"description":{"type":"string","description":"Environment description"}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"projectId":{"type":"string"},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true}},"required":["id","name","description","projectId"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"404":{"description":"Environment not found"},"409":{"description":"Environment name already exists in this project"},"500":{"description":"Failed to update environment"}}}},"/api/projects/{projectId}/milestones":{"get":{"tags":["Milestones"],"summary":"List milestones","description":"Returns all milestones for a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"dueDate":{"type":"string","nullable":true},"status":{"type":"string","enum":["ACTIVE","COMPLETED","ARCHIVED"]},"projectId":{"type":"string"},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true},"_count":{"type":"object","properties":{"testRuns":{"type":"number"}},"required":["testRuns"]}},"required":["id","name","description","status","projectId","_count"]}}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}},"post":{"tags":["Milestones"],"summary":"Create a milestone","description":"Create a new milestone for tracking release goals and test progress","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Milestone name"},"description":{"type":"string","description":"Optional description"},"dueDate":{"type":"string","description":"Due date (ISO format)"},"status":{"type":"string","enum":["ACTIVE","COMPLETED","ARCHIVED"],"description":"Milestone status"}},"required":["name"]}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Milestone name"},"description":{"type":"string","description":"Optional description"},"dueDate":{"type":"string","description":"Due date (ISO format)"},"status":{"type":"string","enum":["ACTIVE","COMPLETED","ARCHIVED"],"description":"Milestone status"}},"required":["name"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Milestone name"},"description":{"type":"string","description":"Optional description"},"dueDate":{"type":"string","description":"Due date (ISO format)"},"status":{"type":"string","enum":["ACTIVE","COMPLETED","ARCHIVED"],"description":"Milestone status"}},"required":["name"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"dueDate":{"type":"string","nullable":true},"status":{"type":"string","enum":["ACTIVE","COMPLETED","ARCHIVED"]},"projectId":{"type":"string"},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true}},"required":["id","name","description","status","projectId"]}}}},"400":{"description":"Name is required"},"404":{"description":"Project not found"},"500":{"description":"Failed to create milestone"}}}},"/api/projects/{projectId}/milestones/{id}":{"delete":{"tags":["Milestones"],"summary":"Delete milestone","description":"Delete an existing milestone from the project.","parameters":[{"schema":{"type":"string","description":"Project ID"},"required":true,"description":"Project ID","name":"projectId","in":"path"},{"schema":{"type":"string","description":"Milestone ID"},"required":true,"description":"Milestone ID","name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"Whether the deletion was successful"}},"required":["success"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}},"get":{"tags":["Milestones"],"summary":"Get milestone details","description":"Retrieve detailed information for a specific milestone including recent test runs and statistics.","parameters":[{"schema":{"type":"string","description":"Project ID"},"required":true,"description":"Project ID","name":"projectId","in":"path"},{"schema":{"type":"string","description":"Milestone ID"},"required":true,"description":"Milestone ID","name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Milestone ID"},"name":{"type":"string","description":"Milestone name"},"description":{"type":"string","nullable":true,"description":"Milestone description"},"dueDate":{"type":"string","nullable":true,"description":"ISO 8601 due date"},"status":{"type":"string","enum":["ACTIVE","COMPLETED","ARCHIVED"],"description":"Milestone status"},"projectId":{"type":"string","description":"Project ID"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"},"testRuns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["PLANNED","IN_PROGRESS","COMPLETED","ABORTED"]},"createdAt":{"type":"string","nullable":true}},"required":["id","name","status"]},"description":"Recent test runs (last 10)"},"_count":{"type":"object","properties":{"testRuns":{"type":"number"}},"required":["testRuns"],"description":"Count of associated test runs"}},"required":["id","name","description","status","projectId","testRuns","_count"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}},"patch":{"tags":["Milestones"],"summary":"Update milestone","description":"Update an existing milestone with new information.","parameters":[{"schema":{"type":"string","description":"Project ID"},"required":true,"description":"Project ID","name":"projectId","in":"path"},{"schema":{"type":"string","description":"Milestone ID"},"required":true,"description":"Milestone ID","name":"id","in":"path"}],"requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Milestone name"},"description":{"type":"string","nullable":true,"description":"Milestone description"},"dueDate":{"type":"string","nullable":true,"description":"ISO 8601 due date"},"status":{"type":"string","enum":["ACTIVE","COMPLETED","ARCHIVED"],"description":"Milestone status"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Milestone name"},"description":{"type":"string","nullable":true,"description":"Milestone description"},"dueDate":{"type":"string","nullable":true,"description":"ISO 8601 due date"},"status":{"type":"string","enum":["ACTIVE","COMPLETED","ARCHIVED"],"description":"Milestone status"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Milestone name"},"description":{"type":"string","nullable":true,"description":"Milestone description"},"dueDate":{"type":"string","nullable":true,"description":"ISO 8601 due date"},"status":{"type":"string","enum":["ACTIVE","COMPLETED","ARCHIVED"],"description":"Milestone status"}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Milestone ID"},"name":{"type":"string","description":"Milestone name"},"description":{"type":"string","nullable":true,"description":"Milestone description"},"dueDate":{"type":"string","nullable":true,"description":"ISO 8601 due date"},"status":{"type":"string","enum":["ACTIVE","COMPLETED","ARCHIVED"],"description":"Milestone status"},"projectId":{"type":"string","description":"Project ID"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"}},"required":["id","name","description","status","projectId"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/api/projects/{projectId}/runs":{"get":{"tags":["Projects"],"summary":"List test runs for a project","description":"Retrieve paginated test runs for a specific project with optional filtering by milestone, environment, and status.","parameters":[{"schema":{"type":"string","description":"Project ID"},"required":true,"description":"Project ID","name":"projectId","in":"path"},{"schema":{"type":"number","minimum":1,"default":1,"description":"Page number (default: 1)"},"required":false,"description":"Page number (default: 1)","name":"page","in":"query"},{"schema":{"type":"number","minimum":1,"maximum":100,"default":20,"description":"Results per page (default: 20)"},"required":false,"description":"Results per page (default: 20)","name":"limit","in":"query"},{"schema":{"type":"string","description":"Filter by milestone ID"},"required":false,"description":"Filter by milestone ID","name":"milestoneId","in":"query"},{"schema":{"type":"string","description":"Filter by environment ID"},"required":false,"description":"Filter by environment ID","name":"environmentId","in":"query"},{"schema":{"type":"string","enum":["PLANNED","IN_PROGRESS","COMPLETED","ABORTED"],"description":"Filter by status"},"required":false,"description":"Filter by status","name":"status","in":"query"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Test run ID"},"name":{"type":"string","description":"Test run name"},"description":{"type":"string","nullable":true,"description":"Test run description"},"projectId":{"type":"string","description":"Project ID"},"milestoneId":{"type":"string","nullable":true,"description":"Milestone ID"},"environmentId":{"type":"string","nullable":true,"description":"Environment ID"},"status":{"type":"string","enum":["PLANNED","IN_PROGRESS","COMPLETED","ABORTED"],"description":"Test run status"},"createdBy":{"type":"string","description":"User ID who created the run"},"startedAt":{"type":"string","nullable":true,"description":"ISO 8601 start timestamp"},"completedAt":{"type":"string","nullable":true,"description":"ISO 8601 completion timestamp"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"},"milestone":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"description":"Associated milestone"},"environment":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"description":"Associated environment"},"_count":{"type":"object","properties":{"results":{"type":"number"}},"required":["results"],"description":"Count of test results"}},"required":["id","name","description","projectId","milestoneId","environmentId","status","createdBy","milestone","environment","_count"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"},"hasMore":{"type":"boolean"}},"required":["page","limit","total","totalPages","hasMore"]}},"required":["data","pagination"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/api/projects/{projectId}/runs/{id}":{"delete":{"tags":["Projects"],"summary":"Delete test run","description":"Delete a test run and all associated test results, attachments, and step results.","parameters":[{"schema":{"type":"string","description":"Project ID"},"required":true,"description":"Project ID","name":"projectId","in":"path"},{"schema":{"type":"string","description":"Test run ID"},"required":true,"description":"Test run ID","name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"Operation success status"},"message":{"type":"string","description":"Success message"}},"required":["success","message"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"403":{"description":"Access denied"},"404":{"description":"Test run or project not found"}}},"get":{"tags":["Projects"],"summary":"Get test run details","description":"Retrieve detailed information for a specific test run including results, statistics, and associated metadata.","parameters":[{"schema":{"type":"string","description":"Project ID"},"required":true,"description":"Project ID","name":"projectId","in":"path"},{"schema":{"type":"string","description":"Test run ID"},"required":true,"description":"Test run ID","name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Test run ID"},"name":{"type":"string","description":"Test run name"},"description":{"type":"string","nullable":true,"description":"Test run description"},"projectId":{"type":"string","description":"Project ID"},"milestoneId":{"type":"string","nullable":true,"description":"Milestone ID"},"environmentId":{"type":"string","nullable":true,"description":"Environment ID"},"status":{"type":"string","enum":["PLANNED","IN_PROGRESS","COMPLETED","ABORTED"],"description":"Test run status"},"createdBy":{"type":"string","description":"User ID who created the run"},"startedAt":{"type":"string","nullable":true,"description":"ISO 8601 start timestamp"},"completedAt":{"type":"string","nullable":true,"description":"ISO 8601 completion timestamp"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"},"milestone":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"description":"Associated milestone"},"environment":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"description":"Associated environment"},"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Test result ID"},"testCaseId":{"type":"string","description":"Test case ID"},"status":{"type":"string","enum":["PASSED","FAILED","BLOCKED","SKIPPED","RETEST","UNTESTED"],"description":"Result status"},"executedAt":{"type":"string","nullable":true,"description":"ISO 8601 execution timestamp"},"testCase":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"priority":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"]},"type":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"]}},"required":["id","title","priority","type"],"description":"Associated test case"},"_count":{"type":"object","properties":{"attachments":{"type":"number"},"steps":{"type":"number"}},"required":["attachments","steps"],"description":"Count of related records"}},"required":["id","testCaseId","status","testCase","_count"]},"description":"Test results for this run"},"stats":{"type":"object","properties":{"total":{"type":"number","description":"Total number of test results"},"passed":{"type":"number","description":"Number of passed tests"},"failed":{"type":"number","description":"Number of failed tests"},"blocked":{"type":"number","description":"Number of blocked tests"},"skipped":{"type":"number","description":"Number of skipped tests"},"retest":{"type":"number","description":"Number of tests marked for retest"},"untested":{"type":"number","description":"Number of untested tests"}},"required":["total","passed","failed","blocked","skipped","retest","untested"],"description":"Statistics for test results"},"_count":{"type":"object","properties":{"results":{"type":"number"}},"required":["results"],"description":"Count of test results"}},"required":["id","name","description","projectId","milestoneId","environmentId","status","createdBy","milestone","environment","results","stats","_count"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}},"patch":{"tags":["Projects"],"summary":"Update test run","description":"Update test run details including name, description, status, milestone, and environment.","parameters":[{"schema":{"type":"string","description":"Project ID"},"required":true,"description":"Project ID","name":"projectId","in":"path"},{"schema":{"type":"string","description":"Test run ID"},"required":true,"description":"Test run ID","name":"id","in":"path"}],"requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Test run name"},"description":{"type":"string","nullable":true,"maxLength":2000,"description":"Test run description"},"status":{"type":"string","enum":["PLANNED","IN_PROGRESS","COMPLETED","ABORTED"],"description":"Test run status"},"milestoneId":{"type":"string","nullable":true,"description":"Milestone ID (null to unlink)"},"environmentId":{"type":"string","nullable":true,"description":"Environment ID (null to unlink)"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Test run name"},"description":{"type":"string","nullable":true,"maxLength":2000,"description":"Test run description"},"status":{"type":"string","enum":["PLANNED","IN_PROGRESS","COMPLETED","ABORTED"],"description":"Test run status"},"milestoneId":{"type":"string","nullable":true,"description":"Milestone ID (null to unlink)"},"environmentId":{"type":"string","nullable":true,"description":"Environment ID (null to unlink)"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Test run name"},"description":{"type":"string","nullable":true,"maxLength":2000,"description":"Test run description"},"status":{"type":"string","enum":["PLANNED","IN_PROGRESS","COMPLETED","ABORTED"],"description":"Test run status"},"milestoneId":{"type":"string","nullable":true,"description":"Milestone ID (null to unlink)"},"environmentId":{"type":"string","nullable":true,"description":"Environment ID (null to unlink)"}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Test run ID"},"name":{"type":"string","description":"Test run name"},"description":{"type":"string","nullable":true,"description":"Test run description"},"projectId":{"type":"string","description":"Project ID"},"milestoneId":{"type":"string","nullable":true,"description":"Milestone ID"},"environmentId":{"type":"string","nullable":true,"description":"Environment ID"},"status":{"type":"string","enum":["PLANNED","IN_PROGRESS","COMPLETED","ABORTED"],"description":"Test run status"},"createdBy":{"type":"string","description":"User ID who created the run"},"startedAt":{"type":"string","nullable":true,"description":"ISO 8601 start timestamp"},"completedAt":{"type":"string","nullable":true,"description":"ISO 8601 completion timestamp"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"}},"required":["id","name","description","projectId","milestoneId","environmentId","status","createdBy"]}}}},"400":{"description":"Invalid request"},"403":{"description":"Access denied"},"404":{"description":"Test run or project not found"}}}},"/api/projects/{projectId}/suites":{"get":{"tags":["Suites"],"summary":"List test suites","description":"Returns all test suites for a project. Supports hierarchical organization with optional parent filtering.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"},{"schema":{"type":"string","description":"Filter by parent suite ID (use \"null\" for root level)"},"required":false,"description":"Filter by parent suite ID (use \"null\" for root level)","name":"parentId","in":"query"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"parentId":{"type":"string","nullable":true},"projectId":{"type":"string"},"order":{"type":"number"},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true},"_count":{"type":"object","properties":{"testCases":{"type":"number"},"children":{"type":"number"}},"required":["testCases","children"]},"children":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"_count":{"type":"object","properties":{"testCases":{"type":"number"}},"required":["testCases"]}},"required":["id","name","_count"]}}},"required":["id","name","description","parentId","projectId","order","_count","children"]}}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}},"post":{"tags":["Suites"],"summary":"Create a test suite","description":"Create a new test suite for organizing test cases. Supports hierarchical nesting via parentId. Requires authentication and project access.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Suite name"},"description":{"type":"string","maxLength":1000,"description":"Optional suite description"},"parentId":{"type":"string","nullable":true,"description":"Parent suite ID for nesting"}},"required":["name"]}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Suite name"},"description":{"type":"string","maxLength":1000,"description":"Optional suite description"},"parentId":{"type":"string","nullable":true,"description":"Parent suite ID for nesting"}},"required":["name"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Suite name"},"description":{"type":"string","maxLength":1000,"description":"Optional suite description"},"parentId":{"type":"string","nullable":true,"description":"Parent suite ID for nesting"}},"required":["name"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"parentId":{"type":"string","nullable":true},"projectId":{"type":"string"},"order":{"type":"number"},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true}},"required":["id","name","description","parentId","projectId","order"]}}}},"400":{"description":"Invalid request - check required fields"},"401":{"description":"Authentication required"},"403":{"description":"You do not have access to this project"},"404":{"description":"Project or parent suite not found"},"500":{"description":"Failed to create test suite"}}}},"/api/projects/{projectId}/suites/{id}":{"delete":{"tags":["Suites"],"summary":"Delete a test suite","description":"Permanently delete a test suite and its children.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"404":{"description":"Test suite not found"},"500":{"description":"Failed to delete test suite"}}},"get":{"tags":["Suites"],"summary":"Get a test suite","description":"Returns a single test suite with children, parent, and test cases.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"parentId":{"type":"string","nullable":true},"projectId":{"type":"string"},"order":{"type":"number"},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true},"parent":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"children":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"_count":{"type":"object","properties":{"testCases":{"type":"number"}},"required":["testCases"]}},"required":["id","name","_count"]}},"testCases":{"type":"array","items":{"nullable":true}},"_count":{"type":"object","properties":{"testCases":{"type":"number"},"children":{"type":"number"}},"required":["testCases","children"]}},"required":["id","name","description","parentId","projectId","order","parent","children","testCases","_count"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"404":{"description":"Test suite not found"},"500":{"description":"Failed to fetch test suite"}}},"patch":{"tags":["Suites"],"summary":"Update a test suite","description":"Update test suite name, description, or parent (for moving in hierarchy).","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Suite name"},"description":{"type":"string","description":"Suite description"},"parentId":{"type":"string","nullable":true,"description":"Parent suite ID"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Suite name"},"description":{"type":"string","description":"Suite description"},"parentId":{"type":"string","nullable":true,"description":"Parent suite ID"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Suite name"},"description":{"type":"string","description":"Suite description"},"parentId":{"type":"string","nullable":true,"description":"Parent suite ID"}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"parentId":{"type":"string","nullable":true},"projectId":{"type":"string"},"order":{"type":"number"},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true}},"required":["id","name","description","parentId","projectId","order"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"404":{"description":"Test suite not found"},"500":{"description":"Failed to update test suite"}}}},"/api/projects/{id}":{"delete":{"tags":["Projects"],"summary":"Delete a project","description":"Permanently deletes a project and all related data (test cases, runs, results, etc.)","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"404":{"description":"Project not found"},"500":{"description":"Failed to delete project"}}},"get":{"tags":["Projects"],"summary":"Get a single project","description":"Returns a single project with related counts (milestones, environments, etc.)","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"key":{"type":"string"},"createdBy":{"type":"string"},"teamId":{"type":"string","nullable":true},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true},"_count":{"type":"object","properties":{"testCases":{"type":"number"},"testRuns":{"type":"number"},"testSuites":{"type":"number"},"milestones":{"type":"number"},"environments":{"type":"number"}},"required":["testCases","testRuns","testSuites","milestones","environments"]},"milestones":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["ACTIVE","COMPLETED","ARCHIVED"]},"dueDate":{"type":"string","nullable":true},"createdAt":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true},"projectId":{"type":"string"}},"required":["id","name","status","description","projectId"]}},"environments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]}}},"required":["id","name","description","key","createdBy","teamId","_count","milestones","environments"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"404":{"description":"Project not found"},"500":{"description":"Failed to fetch project"}}},"patch":{"tags":["Projects"],"summary":"Update a project","description":"Updates project details. Only provided fields will be updated.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":"string","nullable":true},"key":{"type":"string","minLength":3,"maxLength":10,"pattern":"^[A-Z0-9]+$"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":"string","nullable":true},"key":{"type":"string","minLength":3,"maxLength":10,"pattern":"^[A-Z0-9]+$"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"description":{"type":"string","nullable":true},"key":{"type":"string","minLength":3,"maxLength":10,"pattern":"^[A-Z0-9]+$"}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"key":{"type":"string"},"createdBy":{"type":"string"},"teamId":{"type":"string","nullable":true},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true}},"required":["id","name","description","key","createdBy","teamId"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"404":{"description":"Project not found"},"409":{"description":"Project key already exists"},"500":{"description":"Failed to update project"}}}},"/api/results":{"post":{"tags":["Results"],"summary":"Submit test results","description":"Submit batch test results from test runners (e.g., Playwright). Automatically creates test cases and suites if they do not exist. Supports attachments (screenshots, logs, videos).","requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"testRunId":{"type":"string","description":"ID of the test run"},"results":{"type":"array","items":{"type":"object","properties":{"testCaseId":{"type":"string","description":"Existing QA Studio test case ID when known"},"title":{"type":"string","description":"Test case title"},"fullTitle":{"type":"string","maxLength":500,"description":"Full hierarchical title (e.g., \"Suite > Test\")"},"status":{"type":"string","enum":["passed","failed","skipped","timedout","interrupted","timedOut"],"description":"Test execution status"},"duration":{"type":"number","description":"Test duration in milliseconds"},"errorMessage":{"type":"string","description":"Error message if test failed"},"error":{"type":"string","description":"Alternative error field"},"stackTrace":{"type":"string","description":"Stack trace for failures"},"errorSnippet":{"type":"string","description":"Error context snippet"},"errorLocation":{"type":"object","properties":{"file":{"type":"string"},"line":{"type":"number"},"column":{"type":"number"}},"required":["file","line"],"description":"Location where error occurred"},"startTime":{"type":"string","description":"ISO 8601 timestamp when test started"},"endTime":{"type":"string","description":"ISO 8601 timestamp when test ended"},"retry":{"type":"number","description":"Retry attempt number (0 for first attempt)"},"projectName":{"type":"string","description":"Project/browser name (e.g., \"chromium\")"},"metadata":{"type":"object","properties":{"tags":{"type":"array","items":{"type":"string"}},"location":{"type":"object","properties":{"file":{"type":"string"},"line":{"type":"number"},"column":{"type":"number"}},"required":["file","line"]}},"description":"Additional test metadata"},"steps":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","description":"Step title"},"category":{"type":"string","enum":["hook","test.step","pw:api","expect","fixture","other"],"description":"Step category"},"status":{"type":"string","enum":["passed","failed","skipped","timedout"],"description":"Step execution status"},"startTime":{"type":"string","description":"ISO 8601 timestamp when step started"},"duration":{"type":"number","description":"Step duration in milliseconds"},"error":{"type":"string","description":"Error message if step failed"},"stackTrace":{"type":"string","description":"Stack trace for failures"},"location":{"type":"object","properties":{"file":{"type":"string"},"line":{"type":"number"},"column":{"type":"number"}},"required":["file","line"],"description":"Source code location"},"steps":{"type":"array","items":{"type":"object"}}},"required":["title"]},"default":[],"description":"Test execution steps"},"consoleOutput":{"type":"object","properties":{"stdout":{"type":"string"},"stderr":{"type":"string"}},"description":"Console output captured during test"},"attachments":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"contentType":{"type":"string"},"body":{"nullable":true},"type":{"type":"string"}},"required":["name","contentType"]},"default":[],"description":"Screenshots, logs, videos, etc."}},"required":["title","status"]},"description":"Array of test results to submit"}},"required":["testRunId","results"]}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"testRunId":{"type":"string","description":"ID of the test run"},"results":{"type":"array","items":{"type":"object","properties":{"testCaseId":{"type":"string","description":"Existing QA Studio test case ID when known"},"title":{"type":"string","description":"Test case title"},"fullTitle":{"type":"string","maxLength":500,"description":"Full hierarchical title (e.g., \"Suite > Test\")"},"status":{"type":"string","enum":["passed","failed","skipped","timedout","interrupted","timedOut"],"description":"Test execution status"},"duration":{"type":"number","description":"Test duration in milliseconds"},"errorMessage":{"type":"string","description":"Error message if test failed"},"error":{"type":"string","description":"Alternative error field"},"stackTrace":{"type":"string","description":"Stack trace for failures"},"errorSnippet":{"type":"string","description":"Error context snippet"},"errorLocation":{"type":"object","properties":{"file":{"type":"string"},"line":{"type":"number"},"column":{"type":"number"}},"required":["file","line"],"description":"Location where error occurred"},"startTime":{"type":"string","description":"ISO 8601 timestamp when test started"},"endTime":{"type":"string","description":"ISO 8601 timestamp when test ended"},"retry":{"type":"number","description":"Retry attempt number (0 for first attempt)"},"projectName":{"type":"string","description":"Project/browser name (e.g., \"chromium\")"},"metadata":{"type":"object","properties":{"tags":{"type":"array","items":{"type":"string"}},"location":{"type":"object","properties":{"file":{"type":"string"},"line":{"type":"number"},"column":{"type":"number"}},"required":["file","line"]}},"description":"Additional test metadata"},"steps":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","description":"Step title"},"category":{"type":"string","enum":["hook","test.step","pw:api","expect","fixture","other"],"description":"Step category"},"status":{"type":"string","enum":["passed","failed","skipped","timedout"],"description":"Step execution status"},"startTime":{"type":"string","description":"ISO 8601 timestamp when step started"},"duration":{"type":"number","description":"Step duration in milliseconds"},"error":{"type":"string","description":"Error message if step failed"},"stackTrace":{"type":"string","description":"Stack trace for failures"},"location":{"type":"object","properties":{"file":{"type":"string"},"line":{"type":"number"},"column":{"type":"number"}},"required":["file","line"],"description":"Source code location"},"steps":{"type":"array","items":{"type":"object"}}},"required":["title"]},"default":[],"description":"Test execution steps"},"consoleOutput":{"type":"object","properties":{"stdout":{"type":"string"},"stderr":{"type":"string"}},"description":"Console output captured during test"},"attachments":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"contentType":{"type":"string"},"body":{"nullable":true},"type":{"type":"string"}},"required":["name","contentType"]},"default":[],"description":"Screenshots, logs, videos, etc."}},"required":["title","status"]},"description":"Array of test results to submit"}},"required":["testRunId","results"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"testRunId":{"type":"string","description":"ID of the test run"},"results":{"type":"array","items":{"type":"object","properties":{"testCaseId":{"type":"string","description":"Existing QA Studio test case ID when known"},"title":{"type":"string","description":"Test case title"},"fullTitle":{"type":"string","maxLength":500,"description":"Full hierarchical title (e.g., \"Suite > Test\")"},"status":{"type":"string","enum":["passed","failed","skipped","timedout","interrupted","timedOut"],"description":"Test execution status"},"duration":{"type":"number","description":"Test duration in milliseconds"},"errorMessage":{"type":"string","description":"Error message if test failed"},"error":{"type":"string","description":"Alternative error field"},"stackTrace":{"type":"string","description":"Stack trace for failures"},"errorSnippet":{"type":"string","description":"Error context snippet"},"errorLocation":{"type":"object","properties":{"file":{"type":"string"},"line":{"type":"number"},"column":{"type":"number"}},"required":["file","line"],"description":"Location where error occurred"},"startTime":{"type":"string","description":"ISO 8601 timestamp when test started"},"endTime":{"type":"string","description":"ISO 8601 timestamp when test ended"},"retry":{"type":"number","description":"Retry attempt number (0 for first attempt)"},"projectName":{"type":"string","description":"Project/browser name (e.g., \"chromium\")"},"metadata":{"type":"object","properties":{"tags":{"type":"array","items":{"type":"string"}},"location":{"type":"object","properties":{"file":{"type":"string"},"line":{"type":"number"},"column":{"type":"number"}},"required":["file","line"]}},"description":"Additional test metadata"},"steps":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string","description":"Step title"},"category":{"type":"string","enum":["hook","test.step","pw:api","expect","fixture","other"],"description":"Step category"},"status":{"type":"string","enum":["passed","failed","skipped","timedout"],"description":"Step execution status"},"startTime":{"type":"string","description":"ISO 8601 timestamp when step started"},"duration":{"type":"number","description":"Step duration in milliseconds"},"error":{"type":"string","description":"Error message if step failed"},"stackTrace":{"type":"string","description":"Stack trace for failures"},"location":{"type":"object","properties":{"file":{"type":"string"},"line":{"type":"number"},"column":{"type":"number"}},"required":["file","line"],"description":"Source code location"},"steps":{"type":"array","items":{"type":"object"}}},"required":["title"]},"default":[],"description":"Test execution steps"},"consoleOutput":{"type":"object","properties":{"stdout":{"type":"string"},"stderr":{"type":"string"}},"description":"Console output captured during test"},"attachments":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"contentType":{"type":"string"},"body":{"nullable":true},"type":{"type":"string"}},"required":["name","contentType"]},"default":[],"description":"Screenshots, logs, videos, etc."}},"required":["title","status"]},"description":"Array of test results to submit"}},"required":["testRunId","results"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"processedCount":{"type":"number","description":"Number of results successfully processed"},"duplicatesSkipped":{"type":"number","description":"Number of duplicate results skipped"},"results":{"type":"array","items":{"type":"object","properties":{"testCaseId":{"type":"string"},"testResultId":{"type":"string"},"title":{"type":"string"},"status":{"type":"string","enum":["PASSED","FAILED","SKIPPED"]},"duration":{"type":"number","nullable":true,"description":"Test duration in milliseconds"},"created":{"type":"boolean","description":"Whether a new test case was created"},"attachmentCount":{"type":"number"}},"required":["testCaseId","testResultId","title","status","duration","created","attachmentCount"]}},"errors":{"type":"array","items":{"type":"object","properties":{"testTitle":{"type":"string"},"error":{"type":"string"}},"required":["testTitle","error"]},"description":"Errors encountered during processing"},"attachmentErrors":{"type":"array","items":{"type":"object","properties":{"testTitle":{"type":"string"},"attachmentName":{"type":"string"},"error":{"type":"string"}},"required":["testTitle","attachmentName","error"]},"description":"Attachment upload errors"}},"required":["processedCount","results"]}}}},"400":{"description":"testRunId and results array are required"},"403":{"description":"You do not have access to this test run"},"404":{"description":"Test run not found"}}}},"/api/runs":{"get":{"tags":["Runs"],"summary":"List test runs","description":"Retrieve a paginated list of test runs with filters and search. Returns test runs the authenticated user has access to (from their projects or team projects).","parameters":[{"schema":{"type":"number","minimum":1,"default":1,"description":"Page number (default: 1)"},"required":false,"description":"Page number (default: 1)","name":"page","in":"query"},{"schema":{"type":"number","minimum":1,"maximum":100,"default":20,"description":"Results per page (default: 20, max: 100)"},"required":false,"description":"Results per page (default: 20, max: 100)","name":"limit","in":"query"},{"schema":{"type":"string","description":"Search in test run name and description"},"required":false,"description":"Search in test run name and description","name":"search","in":"query"},{"schema":{"type":"string","description":"Filter by project ID"},"required":false,"description":"Filter by project ID","name":"projectId","in":"query"},{"schema":{"type":"string","enum":["PLANNED","IN_PROGRESS","COMPLETED","ABORTED"],"description":"Filter by status"},"required":false,"description":"Filter by status","name":"status","in":"query"},{"schema":{"type":"string","description":"Filter by environment ID"},"required":false,"description":"Filter by environment ID","name":"environmentId","in":"query"},{"schema":{"type":"string","description":"Filter by milestone ID"},"required":false,"description":"Filter by milestone ID","name":"milestoneId","in":"query"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"testRuns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Test run ID"},"name":{"type":"string","description":"Test run name"},"description":{"type":"string","nullable":true,"description":"Test run description"},"projectId":{"type":"string","description":"Project ID"},"milestoneId":{"type":"string","nullable":true,"description":"Milestone ID"},"environmentId":{"type":"string","nullable":true,"description":"Environment ID"},"status":{"type":"string","enum":["PLANNED","IN_PROGRESS","COMPLETED","ABORTED"],"description":"Test run status"},"createdBy":{"type":"string","description":"User ID who created the run"},"startedAt":{"type":"string","nullable":true,"description":"ISO 8601 start timestamp"},"completedAt":{"type":"string","nullable":true,"description":"ISO 8601 completion timestamp"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"},"project":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"key":{"type":"string"}},"required":["id","name","key"],"description":"Associated project"},"environment":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"description":"Associated environment"},"milestone":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"description":"Associated milestone"},"creator":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"email":{"type":"string"}},"required":["id","firstName","lastName","email"],"description":"User who created the run"},"stats":{"type":"object","properties":{"total":{"type":"number","description":"Total test results"},"passed":{"type":"number","description":"Passed tests"},"failed":{"type":"number","description":"Failed tests"},"blocked":{"type":"number","description":"Blocked tests"},"skipped":{"type":"number","description":"Skipped tests"},"retest":{"type":"number","description":"Tests requiring retest"},"untested":{"type":"number","description":"Untested cases"}},"required":["total","passed","failed","blocked","skipped","retest","untested"],"description":"Test result statistics"}},"required":["id","name","description","projectId","milestoneId","environmentId","status","createdBy","project","environment","milestone","stats"]}},"pagination":{"type":"object","properties":{"page":{"type":"number","description":"Current page"},"limit":{"type":"number","description":"Results per page"},"total":{"type":"number","description":"Total test runs"},"totalPages":{"type":"number","description":"Total pages"}},"required":["page","limit","total","totalPages"]}},"required":["testRuns","pagination"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}},"post":{"tags":["Runs"],"summary":"Create a run","description":"Create a new test run. Supports both session and API key authentication. If environment name is provided instead of ID, the environment will be created automatically.","requestBody":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project ID"},"name":{"type":"string","minLength":1,"description":"Test run name"},"description":{"type":"string","description":"Optional test run description"},"environmentId":{"type":"string","description":"ID of existing environment"},"environment":{"type":"string","description":"Name of environment (will be created if does not exist)"},"milestoneId":{"type":"string","description":"ID of milestone"}},"required":["projectId","name"]}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project ID"},"name":{"type":"string","minLength":1,"description":"Test run name"},"description":{"type":"string","description":"Optional test run description"},"environmentId":{"type":"string","description":"ID of existing environment"},"environment":{"type":"string","description":"Name of environment (will be created if does not exist)"},"milestoneId":{"type":"string","description":"ID of milestone"}},"required":["projectId","name"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"projectId":{"type":"string","description":"Project ID"},"name":{"type":"string","minLength":1,"description":"Test run name"},"description":{"type":"string","description":"Optional test run description"},"environmentId":{"type":"string","description":"ID of existing environment"},"environment":{"type":"string","description":"Name of environment (will be created if does not exist)"},"milestoneId":{"type":"string","description":"ID of milestone"}},"required":["projectId","name"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"status":{"type":"string","enum":["PLANNED","IN_PROGRESS","COMPLETED","ABORTED"]},"projectId":{"type":"string"},"environmentId":{"type":"string","nullable":true},"milestoneId":{"type":"string","nullable":true},"createdBy":{"type":"string"},"startedAt":{"type":"string","nullable":true},"completedAt":{"type":"string","nullable":true},"createdAt":{"type":"string","nullable":true},"updatedAt":{"type":"string","nullable":true},"project":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"key":{"type":"string"}},"required":["id","name","key"]},"environment":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"milestone":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]}},"required":["id","name","description","status","projectId","environmentId","milestoneId","createdBy","project","environment","milestone"]}}}},"400":{"description":"projectId and name are required"},"403":{"description":"You do not have access to this project"},"404":{"description":"Project not found"}}}},"/api/runs/{runId}/results":{"get":{"tags":["Runs"],"summary":"Get test results for a run","description":"Retrieve paginated test results for a specific test run with search and filtering capabilities. Returns results with nested test case details and suite hierarchy.","parameters":[{"schema":{"type":"string","description":"Test run ID"},"required":true,"description":"Test run ID","name":"runId","in":"path"},{"schema":{"type":"number","minimum":1,"default":1,"description":"Page number (default: 1)"},"required":false,"description":"Page number (default: 1)","name":"page","in":"query"},{"schema":{"type":"number","minimum":1,"maximum":1000,"default":50,"description":"Results per page (default: 50, max: 1000)"},"required":false,"description":"Results per page (default: 50, max: 1000)","name":"limit","in":"query"},{"schema":{"type":"string","description":"Search in test case title"},"required":false,"description":"Search in test case title","name":"search","in":"query"},{"schema":{"type":"string","enum":["PASSED","FAILED","BLOCKED","SKIPPED","RETEST","UNTESTED"],"description":"Filter by result status"},"required":false,"description":"Filter by result status","name":"status","in":"query"},{"schema":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"],"description":"Filter by test case priority"},"required":false,"description":"Filter by test case priority","name":"priority","in":"query"},{"schema":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"],"description":"Filter by test case type"},"required":false,"description":"Filter by test case type","name":"type","in":"query"}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"testResults":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Test result ID"},"testCaseId":{"type":"string","description":"Test case ID"},"testRunId":{"type":"string","description":"Test run ID"},"status":{"type":"string","enum":["PASSED","FAILED","BLOCKED","SKIPPED","RETEST","UNTESTED"],"description":"Result status"},"fullTitle":{"type":"string","nullable":true,"description":"Full hierarchical test title"},"comment":{"type":"string","nullable":true,"description":"Result comment"},"duration":{"type":"number","nullable":true,"description":"Test duration in milliseconds"},"stackTrace":{"type":"string","nullable":true,"description":"Stack trace for failures"},"errorMessage":{"type":"string","nullable":true,"description":"Error message"},"errorSnippet":{"type":"string","nullable":true,"description":"Error code snippet"},"errorLocation":{"nullable":true,"description":"Error location in code"},"retry":{"type":"number","description":"Retry attempt number"},"projectName":{"type":"string","nullable":true,"description":"Project/browser name"},"metadata":{"nullable":true,"description":"Additional metadata"},"consoleOutput":{"nullable":true,"description":"Console output"},"executedBy":{"type":"string","description":"User ID who executed the test"},"executedAt":{"type":"string","nullable":true,"description":"ISO 8601 execution timestamp"},"createdAt":{"type":"string","nullable":true,"description":"ISO 8601 creation timestamp"},"updatedAt":{"type":"string","nullable":true,"description":"ISO 8601 last update timestamp"},"testCase":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"priority":{"type":"string","enum":["CRITICAL","HIGH","MEDIUM","LOW"]},"type":{"type":"string","enum":["FUNCTIONAL","REGRESSION","SMOKE","INTEGRATION","PERFORMANCE","SECURITY","UI","API","UNIT","E2E"]},"automationStatus":{"type":"string","enum":["AUTOMATED","NOT_AUTOMATED","CANDIDATE"]},"suitePath":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"description":"Hierarchical suite path"}},"required":["id","title","description","priority","type","automationStatus","suitePath"],"description":"Associated test case"},"executor":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string","nullable":true},"lastName":{"type":"string","nullable":true},"email":{"type":"string"}},"required":["id","firstName","lastName","email"],"description":"User who executed the test"},"attachments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"filename":{"type":"string"},"originalName":{"type":"string"},"mimeType":{"type":"string"},"url":{"type":"string"},"size":{"type":"number"},"createdAt":{"type":"string","nullable":true}},"required":["id","filename","originalName","mimeType","url","size"]},"description":"Test result attachments"},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"stepNumber":{"type":"number"},"title":{"type":"string"},"category":{"type":"string","nullable":true},"status":{"type":"string","enum":["PASSED","FAILED","BLOCKED","SKIPPED","RETEST","UNTESTED"]},"duration":{"type":"number","nullable":true},"error":{"type":"string","nullable":true},"stackTrace":{"type":"string","nullable":true},"location":{"type":"object","nullable":true,"properties":{"file":{"type":"string"},"line":{"type":"number"},"column":{"type":"number"}},"required":["file","line","column"],"description":"Source code location"}},"required":["id","stepNumber","title","category","status","duration","error","stackTrace","location"]},"description":"Test step results"},"_count":{"type":"object","properties":{"attachments":{"type":"number"},"steps":{"type":"number"}},"required":["attachments","steps"],"description":"Count of related records"}},"required":["id","testCaseId","testRunId","status","fullTitle","comment","duration","stackTrace","errorMessage","errorSnippet","retry","projectName","executedBy","testCase","_count"]}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"}},"required":["page","limit","total","totalPages"]}},"required":["testResults","pagination"]}}}},"400":{"description":"Invalid input (path parameters, query string, or body)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}}}}