{"openapi":"3.1.0","info":{"title":"Tiora Versioned Workspace API","version":"1.0.0","description":"Public HTTP API for hosted connectors (ChatGPT, Claude, Cursor, Codex, Muse, Grok and MCP-compatible hosts). Tokens are bound to one Workspace with coarse read/write scopes. Workspace Role still applies."},"servers":[{"url":"/api/v1"}],"paths":{"/workspaces/{workspaceId}/search":{"get":{"operationId":"searchWorkspace","summary":"Search artifacts by key or title","security":[{"connectorBearer":["read"]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"}},{"name":"q","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Shallow search results"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}}}},"/workspaces/{workspaceId}/projects":{"get":{"operationId":"listProjects","summary":"List Projects","security":[{"connectorBearer":["read"]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Project list"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}}}},"/workspaces/{workspaceId}/projects/{projectId}":{"get":{"operationId":"getProject","summary":"Get one Project","security":[{"connectorBearer":["read"]}]}},"/workspaces/{workspaceId}/members":{"get":{"operationId":"listMembers","summary":"List assignable Workspace members","security":[{"connectorBearer":["read"]}],"description":"Read-only directory of non-Viewer members for Defect Assignee selection. Membership mutations stay web-only.","responses":{"200":{"description":"Assignable Workspace memberships","content":{"application/json":{"schema":{"type":"object","required":["members"],"properties":{"members":{"type":"array","items":{"type":"object","required":["id","userId","name","email","role"],"properties":{"id":{"type":"string","description":"Workspace membership id accepted as assigneeId."},"userId":{"type":"string"},"name":{"type":"string","nullable":true},"email":{"type":"string"},"role":{"type":"string"}}}}}}}}}}}},"/workspaces/{workspaceId}/projects/{projectId}/folders":{"get":{"operationId":"listFolders","summary":"List Folders"},"post":{"operationId":"createFolder","summary":"Create Folder"}},"/workspaces/{workspaceId}/projects/{projectId}/folders/{folderId}":{"patch":{"operationId":"updateFolder","summary":"Rename and/or move a Folder"},"delete":{"operationId":"deleteFolder","summary":"Delete an empty Folder","responses":{"204":{"description":"Folder deleted"}}}},"/workspaces/{workspaceId}/projects/{projectId}/labels":{"get":{"operationId":"listLabels","summary":"List Labels"},"post":{"operationId":"createLabel","summary":"Create Label"}},"/workspaces/{workspaceId}/projects/{projectId}/environments":{"get":{"operationId":"listEnvironments","summary":"List Environments"},"post":{"operationId":"createEnvironment","summary":"Create Environment"}},"/workspaces/{workspaceId}/projects/{projectId}/build-versions":{"get":{"operationId":"listBuildVersions","summary":"List Build versions"},"post":{"operationId":"createBuildVersion","summary":"Create Build version","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBuildVersionRequest"}}}}}},"/workspaces/{workspaceId}/projects/{projectId}/test-cases":{"get":{"operationId":"listTestCases","summary":"List Tests","security":[{"connectorBearer":["read"]}],"responses":{"200":{"description":"Test Case summaries","content":{"application/json":{"schema":{"type":"object","required":["testCases"],"properties":{"testCases":{"type":"array","items":{"$ref":"#/components/schemas/TestCaseSummary"}}}}}}}}},"post":{"operationId":"createTestCase","summary":"Create Test","security":[{"connectorBearer":["write"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestCaseRequest"}}}},"responses":{"201":{"description":"Created Test","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedTestCase"}}}}}}},"/workspaces/{workspaceId}/projects/{projectId}/test-cases/{testCaseId}":{"get":{"operationId":"getTestCase","summary":"Get one Test Case","security":[{"connectorBearer":["read"]}],"responses":{"200":{"description":"Full Test Case","content":{"application/json":{"schema":{"type":"object","required":["testCase"],"properties":{"testCase":{"$ref":"#/components/schemas/TestCase"}}}}}}}},"patch":{"operationId":"updateTestCase","summary":"Revise Test Working Copy, Folder, Labels or lifecycle","security":[{"connectorBearer":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTestCaseRequest"}}}},"responses":{"200":{"description":"Updated Test","content":{"application/json":{"schema":{"type":"object","required":["testCase"],"properties":{"testCase":{"$ref":"#/components/schemas/UpdatedTestCase"}}}}}},"409":{"description":"Working Copy version conflict"}}}},"/workspaces/{workspaceId}/projects/{projectId}/run-recipes":{"get":{"operationId":"listRunRecipes","summary":"List Run Recipes","security":[{"connectorBearer":["read"]}]},"post":{"operationId":"createRunRecipe","summary":"Create a Run Recipe","security":[{"connectorBearer":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRunRecipeRequest"}}}}}},"/workspaces/{workspaceId}/projects/{projectId}/run-recipes/{runRecipeId}":{"patch":{"operationId":"updateRunRecipe","summary":"Update a Run Recipe","security":[{"connectorBearer":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRunRecipeRequest"}}}}},"delete":{"operationId":"deleteRunRecipe","summary":"Delete a Run Recipe","security":[{"connectorBearer":["write"]}],"responses":{"204":{"description":"Run Recipe deleted"}}}},"/workspaces/{workspaceId}/projects/{projectId}/test-runs":{"get":{"operationId":"listTestRuns","summary":"List Test Runs"},"post":{"operationId":"createTestRun","summary":"Create Test Run","description":"Create from Ready Test Case ids, or from a Run Recipe via recipeKey (PREFIX-S…) or recipeSlug. Optional externalId dedupes CI retries. forceNew ignores a prior externalId match.","security":[{"connectorBearer":["write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestRunRequest"}}}}}},"/workspaces/{workspaceId}/projects/{projectId}/test-runs/retest":{"post":{"operationId":"createRetest","summary":"Create a Retest Run"}},"/workspaces/{workspaceId}/projects/{projectId}/test-runs/{testRunId}":{"get":{"operationId":"getTestRun","summary":"Get Test Run with executions","description":"Includes outcome counts, progress and gateFailed for CI polling against the Run’s gateFailurePolicy.","security":[{"connectorBearer":["read"]}],"responses":{"200":{"description":"Test Run with gate rollup","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTestRunResponse"}}}}}},"patch":{"operationId":"patchTestRun","summary":"Patch Test Run name, environment, build version or assignee","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchTestRunRequest"}}}}}},"/workspaces/{workspaceId}/projects/{projectId}/test-runs/{testRunId}/cancel":{"post":{"operationId":"cancelTestRun","summary":"Cancel a Test Run"}},"/workspaces/{workspaceId}/projects/{projectId}/test-runs/{testRunId}/executions":{"post":{"operationId":"addRunExecutions","summary":"Add Tests to a Test Run"}},"/workspaces/{workspaceId}/projects/{projectId}/test-runs/{testRunId}/executions/{executionId}":{"delete":{"operationId":"removeRunExecution","summary":"Remove a Test Execution from a Run"}},"/workspaces/{workspaceId}/projects/{projectId}/test-runs/{testRunId}/executions/order":{"put":{"operationId":"reorderRunExecutions","summary":"Reorder unexecuted Tests in a Run"}},"/workspaces/{workspaceId}/projects/{projectId}/test-runs/{testRunId}/executions/claim-next":{"post":{"operationId":"claimNextExecution","summary":"Claim the next unexecuted Test Execution","description":"Automation Actors receive a short stealable lease. Humans claim without a lease and clear any automation lease.","security":[{"connectorBearer":["write"]}],"responses":{"200":{"description":"Claimed execution"},"404":{"description":"No claimable execution"}}}},"/workspaces/{workspaceId}/projects/{projectId}/executions/{executionId}/claim":{"post":{"operationId":"claimExecution","summary":"Claim Test Execution as Executor"}},"/workspaces/{workspaceId}/projects/{projectId}/executions/{executionId}/release":{"post":{"operationId":"releaseExecution","summary":"Release a claimed Test Execution"}},"/workspaces/{workspaceId}/projects/{projectId}/executions/{executionId}/reassign":{"post":{"operationId":"reassignExecution","summary":"Reassign a Test Execution to another Executor","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReassignExecutionRequest"}}}}}},"/workspaces/{workspaceId}/projects/{projectId}/executions/{executionId}/progress":{"post":{"operationId":"saveExecutionProgress","summary":"Save in-progress step outcomes"}},"/workspaces/{workspaceId}/projects/{projectId}/executions/{executionId}/outcome":{"post":{"operationId":"submitExecutionOutcome","summary":"Record final Execution Outcome"}},"/workspaces/{workspaceId}/projects/{projectId}/defects":{"get":{"operationId":"listDefects","summary":"List Defects"},"post":{"operationId":"createDefect","summary":"Create Defect"}},"/workspaces/{workspaceId}/projects/{projectId}/defects/{defectId}":{"get":{"operationId":"getDefect","summary":"Get one Defect with reproduction fields, labels, execution links, screenshots and comments"},"patch":{"operationId":"updateDefect","summary":"Update Defect fields and/or status"}},"/workspaces/{workspaceId}/projects/{projectId}/defects/{defectId}/comments":{"post":{"operationId":"commentOnDefect","summary":"Add a Defect comment"}},"/workspaces/{workspaceId}/projects/{projectId}/defects/{defectId}/execution-links":{"post":{"operationId":"linkDefectExecution","summary":"Link a Defect to a Test Execution","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkDefectExecutionRequest"}}}}}},"/workspaces/{workspaceId}/projects/{projectId}/failure-screenshots":{"post":{"operationId":"createFailureScreenshotUpload","summary":"Create short-lived Failure Screenshot upload URL"}},"/workspaces/{workspaceId}/projects/{projectId}/failure-screenshots/{screenshotId}/finalize":{"post":{"operationId":"finalizeFailureScreenshot","summary":"Finalize uploaded Failure Screenshot"}},"/workspaces/{workspaceId}/projects/{projectId}/failure-screenshots/{screenshotId}/preview":{"get":{"operationId":"getFailureScreenshotPreview","summary":"Get a short-lived Failure Screenshot preview path"}},"/workspaces/{workspaceId}/statuses":{"get":{"operationId":"listStatuses","summary":"List Workspace Statuses"}}},"components":{"securitySchemes":{"connectorBearer":{"type":"http","scheme":"bearer","bearerFormat":"Tiora connector access token"}},"schemas":{"StructuredStep":{"type":"object","required":["id","order","instruction"],"properties":{"id":{"type":"string","minLength":1,"maxLength":100},"order":{"type":"integer","minimum":0,"description":"Must equal the step’s index in the steps array."},"instruction":{"type":"string"},"testData":{"type":"string","default":""},"expectedResult":{"type":"string","default":""}}},"TestCaseContent":{"type":"object","required":["format","steps"],"properties":{"format":{"type":"string","enum":["STRUCTURED"]},"steps":{"type":"array","items":{"$ref":"#/components/schemas/StructuredStep"}}}},"CreateTestCaseRequest":{"type":"object","required":["title","content"],"properties":{"title":{"type":"string","minLength":1,"maxLength":200},"objective":{"type":"string","nullable":true,"maxLength":50000,"description":"Case Objective. The app shows this as Objective in English and Cíl in Czech. Steps belong in content. Defects use a separate description field."},"preconditions":{"type":"string","nullable":true,"maxLength":50000},"testData":{"type":"string","nullable":true,"maxLength":50000},"content":{"$ref":"#/components/schemas/TestCaseContent"},"folderId":{"type":"string"},"position":{"type":"integer","minimum":0},"lifecycle":{"type":"string","maxLength":64},"priority":{"type":"string","nullable":true,"enum":["URGENT","HIGH","MEDIUM","LOW"]},"assigneeId":{"type":"string","nullable":true},"labelIds":{"type":"array","maxItems":100,"items":{"type":"string"}}}},"UpdateTestCaseRequest":{"type":"object","description":"At least one field required. Revising Working Copy fields requires both expectedVersion and content.","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"objective":{"type":"string","nullable":true,"maxLength":50000,"description":"Case Objective. The app shows this as Objective in English and Cíl in Czech. Steps belong in content. Defects use a separate description field."},"preconditions":{"type":"string","nullable":true,"maxLength":50000},"testData":{"type":"string","nullable":true,"maxLength":50000},"content":{"$ref":"#/components/schemas/TestCaseContent"},"expectedVersion":{"type":"integer","minimum":1,"description":"Optimistic concurrency token from workingCopyVersion."},"lifecycle":{"type":"string","maxLength":64},"folderId":{"type":"string"},"position":{"type":"integer","minimum":0},"labelIds":{"type":"array","maxItems":100,"items":{"type":"string"}}}},"TestCaseSummary":{"type":"object","required":["id","key","title","lifecycle","folderId"],"properties":{"id":{"type":"string"},"key":{"type":"string","description":"Artifact Key"},"title":{"type":"string"},"lifecycle":{"type":"string"},"folderId":{"type":"string"}}},"CreatedTestCase":{"type":"object","required":["testCase"],"properties":{"testCase":{"type":"object","required":["id","key","title","lifecycle","workingCopyVersion"],"properties":{"id":{"type":"string"},"key":{"type":"string"},"title":{"type":"string"},"objective":{"type":"string","nullable":true},"lifecycle":{"type":"string"},"workingCopyVersion":{"type":"integer"},"content":{"$ref":"#/components/schemas/TestCaseContent"},"folder":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string"}}}}}}},"UpdatedTestCase":{"type":"object","required":["id","key","title","lifecycle","workingCopyVersion"],"properties":{"id":{"type":"string"},"key":{"type":"string"},"title":{"type":"string"},"lifecycle":{"type":"string"},"workingCopyVersion":{"type":"integer"}}},"CreateTestRunRequest":{"type":"object","description":"Either (name + environmentId + testCaseIds) or (recipeKey / recipeSlug). Recipe path expands Ready Cases from the Recipe selection.","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"environmentId":{"type":"string","minLength":1},"testCaseIds":{"type":"array","items":{"type":"string","minLength":1}},"recipeKey":{"type":"string","minLength":1,"description":"Run Recipe Artifact Key (PREFIX-S…)."},"recipeSlug":{"type":"string","minLength":1,"description":"Optional stable slug for the Run Recipe."},"buildVersion":{"type":"string","nullable":true,"maxLength":200,"description":"Build version name. Automatically added to the Project catalog when missing."},"assigneeId":{"type":"string","nullable":true,"description":"Workspace membership id for unexecuted assignees."},"externalId":{"type":"string","minLength":1,"maxLength":200,"description":"CI correlation id. Matching open Runs are returned instead of creating a duplicate unless forceNew is true."},"forceNew":{"type":"boolean","description":"Ignore externalId dedupe and create a new Run."},"gateFailurePolicy":{"type":"string","enum":["FAILED_ONLY","FAILED_OR_BLOCKED","ANY_NON_PASSED"]},"autoFileDefects":{"type":"boolean"}}},"GetTestRunResponse":{"type":"object","required":["testRun"],"properties":{"testRun":{"type":"object","required":["id","key","name","status","counts","gateFailed","progress","executions"],"properties":{"id":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"buildVersion":{"type":"string","nullable":true},"externalId":{"type":"string","nullable":true},"gateFailurePolicy":{"type":"string","enum":["FAILED_ONLY","FAILED_OR_BLOCKED","ANY_NON_PASSED"]},"autoFileDefects":{"type":"boolean"},"counts":{"type":"object","required":["passed","failed","blocked","skipped","unexecuted"],"properties":{"passed":{"type":"integer"},"failed":{"type":"integer"},"blocked":{"type":"integer"},"skipped":{"type":"integer"},"unexecuted":{"type":"integer"}}},"gateFailed":{"type":"boolean","description":"True when counts violate gateFailurePolicy (use for CI exit)."},"progress":{"type":"object","required":["total","completed"],"properties":{"total":{"type":"integer"},"completed":{"type":"integer"}}},"executions":{"type":"array","items":{"type":"object"}}}}}},"CreateRunRecipeRequest":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":200},"slug":{"type":"string","nullable":true,"maxLength":64},"environmentId":{"type":"string","nullable":true},"defaultBuildVersion":{"type":"string","nullable":true,"maxLength":200},"selectedFolderIds":{"type":"array","items":{"type":"string"}},"requiredLabelIds":{"type":"array","items":{"type":"string"}},"addedTestCaseIds":{"type":"array","items":{"type":"string"}},"removedTestCaseIds":{"type":"array","items":{"type":"string"}},"gateFailurePolicy":{"type":"string","enum":["FAILED_ONLY","FAILED_OR_BLOCKED","ANY_NON_PASSED"]},"autoFileDefects":{"type":"boolean"},"automationOnly":{"type":"boolean"}}},"UpdateRunRecipeRequest":{"type":"object","description":"At least one field required.","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"slug":{"type":"string","nullable":true,"maxLength":64},"environmentId":{"type":"string","nullable":true},"defaultBuildVersion":{"type":"string","nullable":true,"maxLength":200},"selectedFolderIds":{"type":"array","items":{"type":"string"}},"requiredLabelIds":{"type":"array","items":{"type":"string"}},"addedTestCaseIds":{"type":"array","items":{"type":"string"}},"removedTestCaseIds":{"type":"array","items":{"type":"string"}},"gateFailurePolicy":{"type":"string","enum":["FAILED_ONLY","FAILED_OR_BLOCKED","ANY_NON_PASSED"]},"autoFileDefects":{"type":"boolean"},"automationOnly":{"type":"boolean"}}},"PatchTestRunRequest":{"type":"object","description":"At least one field required.","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"environmentId":{"type":"string","minLength":1},"buildVersion":{"type":"string","nullable":true,"maxLength":200,"description":"Build version name from the Project catalog."},"assigneeId":{"type":"string","nullable":true,"description":"Workspace membership id for unexecuted assignees."}}},"ReassignExecutionRequest":{"type":"object","required":["executorMembershipId"],"properties":{"executorMembershipId":{"type":"string","nullable":true,"description":"Target Workspace membership id, or null to clear assignee."}}},"LinkDefectExecutionRequest":{"type":"object","required":["executionId"],"properties":{"executionId":{"type":"string","minLength":1},"stepId":{"type":"string","nullable":true,"minLength":1}}},"CreateBuildVersionRequest":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000,"nullable":true}}},"TestCase":{"type":"object","description":"Full Test Case Working Copy as returned by GET for agents.","required":["id","key","title","lifecycle","workingCopyVersion","content"],"properties":{"id":{"type":"string"},"key":{"type":"string","description":"Artifact Key"},"title":{"type":"string"},"lifecycle":{"type":"string"},"workingCopyVersion":{"type":"integer"},"folderId":{"type":"string","nullable":true},"folder":{"type":"object","nullable":true,"additionalProperties":true},"objective":{"type":"string","nullable":true},"preconditions":{"type":"string","nullable":true},"testData":{"type":"string","nullable":true},"content":{"$ref":"#/components/schemas/TestCaseContent"},"labels":{"type":"array","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"color":{"type":"string","nullable":true}}}}}}}}}