{"openapi":"3.1.0","info":{"title":"Can API","description":"Can API — REST surface for KanbanCan integrations.\n\n## Authorization model\n\nBearer tokens are **user-scoped**. A token represents a single Firebase user; it does not encode workspace bindings or roles.\n\nWorkspace access is governed by the live `workspaces/{wsId}/members/{uid}` document. Every request that touches a workspace re-reads the member doc, so:\n\n- Membership is required for any workspace-scoped route. Non-members receive 404 (the API does not leak workspace existence).\n- Some routes require the `admin` role; member-only callers receive 403 on those routes.\n- A demotion or promotion takes effect on the user's **next** API request — no token revocation is needed.\n\nOAuth scopes are **not** used as role substitutes. The single empty scope is reserved for future capability gating.","version":"1.0.0"},"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth 2.0 authorization-code flow with PKCE. Tokens are user-scoped; workspace access is evaluated per request.","flows":{"authorizationCode":{"authorizationUrl":"https://api.can.randomfact.com/oauth/authorize","tokenUrl":"https://api.can.randomfact.com/oauth/token","scopes":{}}}}},"schemas":{}},"paths":{"/v1/workspaces":{"get":{"operationId":"list_workspaces","summary":"List the caller's workspace memberships.","description":"Returns one entry per workspace where the caller has a member doc. Each entry includes the caller's `role` for that workspace.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"ownerId":{"type":"string"},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"role":{"type":"string","enum":["admin","member"]}},"required":["id","slug","name","ownerId","createdAt","role"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}":{"get":{"operationId":"get_workspace","summary":"Get one workspace by slug.","description":"Returns the workspace shape plus the caller's role. Non-members receive 404 — the API does not leak workspace existence.","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"ownerId":{"type":"string"},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"role":{"type":"string","enum":["admin","member"]}},"required":["id","slug","name","ownerId","createdAt","role"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/boards":{"get":{"operationId":"list_boards","summary":"List boards in a workspace.","description":"Cursor-paginated. Ordered by `(createdAt, id)`. The response `nextCursor` is null when the result set is exhausted.","parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false},{"schema":{"type":"string","minLength":1},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Z]{3,5}$"},"name":{"type":"string"},"visibility":{"type":"string","enum":["private","public"]},"ticketCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"nextTicketNumber":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","visibility","ticketCount","nextTicketNumber","createdAt"],"additionalProperties":false}},"nextCursor":{"type":["string","null"]}},"required":["items","nextCursor"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}},"post":{"operationId":"create_board","summary":"Create a board.","description":"Creates a new board with the four default seed columns (To Do, In Progress, Done, Won't Do). Any workspace member may create a private board; only workspace admins may create a public board.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string","pattern":"^[A-Z]{3,5}$"},"name":{"type":"string","minLength":1,"maxLength":200},"visibility":{"type":"string","enum":["private","public"]}},"required":["key","name","visibility"],"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Z]{3,5}$"},"name":{"type":"string"},"visibility":{"type":"string","enum":["private","public"]},"ticketCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"nextTicketNumber":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","visibility","ticketCount","nextTicketNumber","createdAt"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/boards/{key}":{"get":{"operationId":"get_board","summary":"Get one board by key.","description":"Returns the board document keyed by its 3–5 letter `key` (e.g. `LAUN`). 404 if the key does not resolve in the resolved workspace.","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Z]{3,5}$"},"name":{"type":"string"},"visibility":{"type":"string","enum":["private","public"]},"ticketCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"nextTicketNumber":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","visibility","ticketCount","nextTicketNumber","createdAt"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}},"patch":{"operationId":"update_board","summary":"Rename a board.","description":"Updates the board's `name`. Visibility, view settings, and delete are not exposed via this route in v1.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200}},"required":["name"],"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Z]{3,5}$"},"name":{"type":"string"},"visibility":{"type":"string","enum":["private","public"]},"ticketCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"nextTicketNumber":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","visibility","ticketCount","nextTicketNumber","createdAt"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/boards/{key}/columns":{"get":{"operationId":"list_columns","summary":"List columns on a board, in board order.","description":"Ordered by the board's lexorank, left to right — the same order the board shows. Each column carries only what you need to choose one: its `id` (pass to `update_ticket` or `bulk_status_tickets`), its `name`, its `category` (`todo` | `in-progress` | `done` | `wont-do`), and its `wipLimit` when one is set.","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"category":{"type":"string","enum":["todo","in-progress","done","wont-do"]},"wipLimit":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["id","name","category"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/boards/{key}/tags":{"get":{"operationId":"list_tags","summary":"List tags on a board.","description":"Cursor-paginated. Ordered by `(nameLower, id)` ascending. The response `nextCursor` is null when the result set is exhausted.","parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false},{"schema":{"type":"string","minLength":1},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"name":{"type":"string","minLength":1,"maxLength":50},"nameLower":{"type":"string"},"color":{"type":"string","enum":["slate","red","amber","yellow","green","teal","blue","indigo","purple","pink"]},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","boardId","name","nameLower","color","createdAt"],"additionalProperties":false}},"nextCursor":{"type":["string","null"]}},"required":["items","nextCursor"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}},"post":{"operationId":"create_tag","summary":"Create a tag.","description":"Enforces the 50-tags-per-board ceiling and case-insensitive uniqueness on `name`. Tag CRUD does not emit activity-log entries; only the existing ticket-PATCH `tagIds` path does.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":50},"color":{"type":"string","enum":["slate","red","amber","yellow","green","teal","blue","indigo","purple","pink"]}},"required":["name","color"],"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"name":{"type":"string","minLength":1,"maxLength":50},"nameLower":{"type":"string"},"color":{"type":"string","enum":["slate","red","amber","yellow","green","teal","blue","indigo","purple","pink"]},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","boardId","name","nameLower","color","createdAt"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"412":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/boards/{key}/tags/{tagId}":{"get":{"operationId":"get_tag","summary":"Get one tag.","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true},{"schema":{"type":"string","minLength":1},"in":"path","name":"tagId","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"name":{"type":"string","minLength":1,"maxLength":50},"nameLower":{"type":"string"},"color":{"type":"string","enum":["slate","red","amber","yellow","green","teal","blue","indigo","purple","pink"]},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","boardId","name","nameLower","color","createdAt"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}},"patch":{"operationId":"update_tag","summary":"Rename and/or recolor a tag.","description":"At least one of `name` or `color` must be present. `id`, `boardId`, and `createdAt` are immutable.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":50},"color":{"type":"string","enum":["slate","red","amber","yellow","green","teal","blue","indigo","purple","pink"]}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true},{"schema":{"type":"string","minLength":1},"in":"path","name":"tagId","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"name":{"type":"string","minLength":1,"maxLength":50},"nameLower":{"type":"string"},"color":{"type":"string","enum":["slate","red","amber","yellow","green","teal","blue","indigo","purple","pink"]},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","boardId","name","nameLower","color","createdAt"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"412":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}},"delete":{"operationId":"delete_tag","summary":"Delete a tag and remove it from every ticket on the board.","description":"Cascades by walking `tickets where tagIds array-contains :tagId` and rewriting each `tagIds` array. Rejects with 412 if the tag is applied to more than 10000 tickets.","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true},{"schema":{"type":"string","minLength":1},"in":"path","name":"tagId","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]},"affectedTickets":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["deleted","affectedTickets"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"412":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/tickets/{ticketKey}":{"get":{"operationId":"resolve_ticket","summary":"Resolve a ticket by its key, without a workspace slug.","description":"Looks up a ticket from its `LAUN-7`-style key across every workspace the caller is a member of — no slug required. The board key is derived from the ticket key (`LAUN-7` lives on board `LAUN`).\n\n- The response is always `{ matches: [...] }`. Normally `matches` has one entry.\n- If the same board key + ticket key exists in two or more of your workspaces (a rare collision), every match is returned so you can pick the right one by its `slug`.\n- Each match carries the workspace `slug` (use it with the slug-scoped routes to edit, comment, etc.) and the full ticket.\n- 404 when no ticket with that key exists in any workspace you belong to — the API does not reveal tickets in workspaces you are not a member of.","parameters":[{"schema":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"in":"path","name":"ticketKey","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"matches":{"minItems":1,"type":"array","items":{"type":"object","properties":{"slug":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"ticket":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"columnId":{"type":["string","null"]},"title":{"type":"string"},"description":{"type":"string"},"rank":{"type":"string"},"tagIds":{"type":"array","items":{"type":"string"}},"assigneeId":{"type":["string","null"]},"agentAssigneeId":{"anyOf":[{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z][a-z0-9-]*$"},{"type":"null"}]},"attachments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"fileName":{"type":"string","minLength":1},"contentType":{"type":"string","minLength":1},"size":{"type":"integer","minimum":0,"maximum":9007199254740991},"uploadedBy":{"type":"string","minLength":1},"uploadedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","fileName","contentType","size","uploadedBy","uploadedAt"],"additionalProperties":false}},"commentCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"statusChangedAt":{"type":["number","null"]},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdBy":{"type":"string"},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","boardId","columnId","title","description","rank","tagIds","assigneeId","agentAssigneeId","attachments","commentCount","statusChangedAt","createdAt","createdBy","updatedAt"],"additionalProperties":false}},"required":["slug","ticket"],"additionalProperties":false}}},"required":["matches"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/boards/{key}/tickets":{"get":{"operationId":"list_tickets","summary":"List tickets on a board.","description":"Cursor-paginated. Ordered by `(rank, id)`. The response `nextCursor` is null when the result set is exhausted.\n\nNarrow the board with at most one of (more than one is a 400):\n\n- `columnName` — the column as people say it (`Review`), case- and whitespace-insensitive. No `list_columns` call needed first. An unrecognized name is a 400 listing the board's real column names. Names are not unique on a board; a name that matches two columns spans both.\n- `status` — the category a column is classified as: `todo`, `in-progress`, `done`, `wont-do`, or `backlog` (tickets in no column). Spans every column of that category (`Dev` and `Review` may both be `in-progress`), so use it for questions that hold across differently-named boards.\n- `columnId` — an opaque id from `list_columns`, if you already hold one.\n\nOmit all three to list the whole board.\n\nItems are summaries by default: the ticket's identity, column, assignees, tags, comment count and `updatedAt`, plus a `descriptionPreview` of the first 160 characters of the description. Pass `view=full` to get every field of every ticket, descriptions included — that answer is large, and reading one ticket with `get_ticket` is usually what you want instead.","parameters":[{"schema":{"type":"string","enum":["todo","in-progress","done","wont-do","backlog"]},"in":"query","name":"status","required":false},{"schema":{"type":"string","minLength":1,"maxLength":200},"in":"query","name":"columnName","required":false},{"schema":{"type":"string","minLength":1},"in":"query","name":"columnId","required":false},{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false},{"schema":{"type":"string","minLength":1},"in":"query","name":"cursor","required":false},{"schema":{"default":"summary","type":"string","enum":["summary","full"]},"in":"query","name":"view","required":false},{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"columnId":{"type":["string","null"]},"title":{"type":"string"},"description":{"type":"string"},"rank":{"type":"string"},"tagIds":{"type":"array","items":{"type":"string"}},"assigneeId":{"type":["string","null"]},"agentAssigneeId":{"anyOf":[{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z][a-z0-9-]*$"},{"type":"null"}]},"attachments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"fileName":{"type":"string","minLength":1},"contentType":{"type":"string","minLength":1},"size":{"type":"integer","minimum":0,"maximum":9007199254740991},"uploadedBy":{"type":"string","minLength":1},"uploadedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","fileName","contentType","size","uploadedBy","uploadedAt"],"additionalProperties":false}},"commentCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"statusChangedAt":{"type":["number","null"]},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdBy":{"type":"string"},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","boardId","columnId","title","description","rank","tagIds","assigneeId","agentAssigneeId","attachments","commentCount","statusChangedAt","createdAt","createdBy","updatedAt"],"additionalProperties":false}},"nextCursor":{"type":["string","null"]}},"required":["items","nextCursor"],"additionalProperties":false},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"columnId":{"type":["string","null"]},"title":{"type":"string"},"assigneeId":{"type":["string","null"]},"agentAssigneeId":{"anyOf":[{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z][a-z0-9-]*$"},{"type":"null"}]},"tagIds":{"type":"array","items":{"type":"string"}},"commentCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"descriptionPreview":{"type":"string","maxLength":160}},"required":["id","boardId","columnId","title","assigneeId","agentAssigneeId","tagIds","commentCount","updatedAt","descriptionPreview"],"additionalProperties":false}},"nextCursor":{"type":["string","null"]}},"required":["items","nextCursor"],"additionalProperties":false}]}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}},"post":{"operationId":"create_ticket","summary":"Create a ticket on a board.","description":"Appends to the lexorank tail. Emits one activity entry per field that was set on creation; `via` is included on each entry when the request is OAuth-authenticated.\n\nAnswers with a summary of the new ticket — its key, board, column, title, assignees, tags, comment count and `updatedAt`. The description is not echoed back; you just supplied it.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"description":{"type":"string","maxLength":50000},"columnId":{"type":["string","null"]},"assigneeId":{"type":["string","null"]},"agentAssigneeId":{"anyOf":[{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z][a-z0-9-]*$"},{"type":"null"}]},"tagIds":{"maxItems":10,"type":"array","items":{"type":"string","minLength":1}}},"required":["title"]}}}},"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"columnId":{"type":["string","null"]},"title":{"type":"string"},"assigneeId":{"type":["string","null"]},"agentAssigneeId":{"anyOf":[{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z][a-z0-9-]*$"},{"type":"null"}]},"tagIds":{"type":"array","items":{"type":"string"}},"commentCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","boardId","columnId","title","assigneeId","agentAssigneeId","tagIds","commentCount","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"412":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/boards/{key}/tickets/{ticketKey}":{"get":{"operationId":"get_ticket","summary":"Get one ticket by its `LAUN-7`-style key.","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"in":"path","name":"ticketKey","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"columnId":{"type":["string","null"]},"title":{"type":"string"},"description":{"type":"string"},"rank":{"type":"string"},"tagIds":{"type":"array","items":{"type":"string"}},"assigneeId":{"type":["string","null"]},"agentAssigneeId":{"anyOf":[{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z][a-z0-9-]*$"},{"type":"null"}]},"attachments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"fileName":{"type":"string","minLength":1},"contentType":{"type":"string","minLength":1},"size":{"type":"integer","minimum":0,"maximum":9007199254740991},"uploadedBy":{"type":"string","minLength":1},"uploadedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","fileName","contentType","size","uploadedBy","uploadedAt"],"additionalProperties":false}},"commentCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"statusChangedAt":{"type":["number","null"]},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdBy":{"type":"string"},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","boardId","columnId","title","description","rank","tagIds","assigneeId","agentAssigneeId","attachments","commentCount","statusChangedAt","createdAt","createdBy","updatedAt"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}},"patch":{"operationId":"update_ticket","summary":"Update fields on a ticket.","description":"Partial update — pass only the fields you want to change. Emits one activity entry per changed field. `via` is included when OAuth-authenticated.\n\nAnswers with a summary of the ticket as it now stands — key, board, column, title, assignees, tags, comment count and `updatedAt`. That summary is the confirmation; no follow-up read is needed. The description is never echoed: re-read it with `get_ticket` if you need the body.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"description":{"type":"string","maxLength":50000},"columnId":{"type":["string","null"]},"assigneeId":{"type":["string","null"]},"agentAssigneeId":{"anyOf":[{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z][a-z0-9-]*$"},{"type":"null"}]},"tagIds":{"maxItems":10,"type":"array","items":{"type":"string","minLength":1}}}}}}},"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"in":"path","name":"ticketKey","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"columnId":{"type":["string","null"]},"title":{"type":"string"},"assigneeId":{"type":["string","null"]},"agentAssigneeId":{"anyOf":[{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z][a-z0-9-]*$"},{"type":"null"}]},"tagIds":{"type":"array","items":{"type":"string"}},"commentCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","boardId","columnId","title","assigneeId","agentAssigneeId","tagIds","commentCount","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"412":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/boards/{key}/tickets{bulkStatus}":{"post":{"operationId":"bulk_status_tickets","summary":"Move many tickets between columns in one call.","description":"Mirror of the `bulkUpdateTicketStatus` callable. By default appends each moved ticket to the target column's lexorank tail and writes a `columnId` activity entry per ticket whose column actually changed. When the optional `placements` array is supplied (one `{ ticketId, rank }` per id in `ticketIds`), each ticket lands at the supplied rank instead — used by drop-position-aware multi-ticket drag — and also gets a `rank` activity entry per ticket whose rank actually changed.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ticketIds":{"minItems":1,"maxItems":2000,"type":"array","items":{"type":"string"}},"targetColumnId":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"placements":{"type":"array","items":{"type":"object","properties":{"ticketId":{"type":"string","minLength":1},"rank":{"type":"string","minLength":1}},"required":["ticketId","rank"]}}},"required":["ticketIds","targetColumnId"]}}}},"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"updated":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["updated"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"412":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/tickets{assignSelf}":{"post":{"operationId":"assign_self","summary":"Assign a ticket to the calling user.","description":"Sets the ticket's human `assigneeId` to the authenticated caller, resolved server-side from the request's auth context. This lets a client self-assign in a single call, without first calling a 'who am I' endpoint or otherwise learning and tracking its own uid. (The uid is not treated as a secret — a member-listing surface that returns uids is a fine future addition; this action just spares self-assignment that round-trip.)\n\n- Only `slug` + `ticketKey` are required; the board key is derived from the ticket key (`LAUN-7` lives on board `LAUN`).\n- Emits the usual `assigneeId` activity entry (with `via` when OAuth-authenticated).\n- Idempotent: if the ticket is already assigned to the caller, nothing changes and no activity entry is written.\n- To assign a *different* user, or to unassign, use `update_ticket` with an explicit `assigneeId` (or `null`).\n- Answers with a summary of the ticket (no description); the returned `assigneeId` is the confirmation.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ticketKey":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"}},"required":["ticketKey"]}}}},"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"columnId":{"type":["string","null"]},"title":{"type":"string"},"assigneeId":{"type":["string","null"]},"agentAssigneeId":{"anyOf":[{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z][a-z0-9-]*$"},{"type":"null"}]},"tagIds":{"type":"array","items":{"type":"string"}},"commentCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","boardId","columnId","title","assigneeId","agentAssigneeId","tagIds","commentCount","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"412":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/tickets{search}":{"get":{"operationId":"search_tickets","summary":"Semantic ticket search across a workspace.","description":"Embeds the query text via Vertex AI and ranks workspace tickets by cosine distance.\n\n- `distance` is **cosine distance**, smaller is closer (0 = identical, 2 = opposite).\n- Results are ordered by `distance` ascending.\n- `boardKey` is repeatable; omit it to search every board in the workspace.\n- `maxDistance` defaults to `0.6` — results beyond that are dropped server-side as low-confidence noise.\n- The `embedding` vector is server-side state and is NEVER included on the returned tickets; only the numeric distance is exposed.\n- Tickets created before this feature shipped (and not yet backfilled) are excluded — `findNearest` cannot rank documents that lack the vector field.\n- Each hit's ticket is a summary plus a `descriptionPreview` of the first 160 characters of the description. Pass `view=full` for every field of every hit, descriptions included — that answer is large; reading the one ticket you wanted with `get_ticket` is usually cheaper.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":2000},"in":"query","name":"q","required":true},{"schema":{"anyOf":[{"type":"string","pattern":"^[A-Z]{3,5}$"},{"maxItems":50,"type":"array","items":{"type":"string","pattern":"^[A-Z]{3,5}$"}}]},"in":"query","name":"boardKey","required":false},{"schema":{"type":"integer","minimum":1,"maximum":100},"in":"query","name":"limit","required":false},{"schema":{"type":"number","minimum":0,"maximum":2},"in":"query","name":"maxDistance","required":false},{"schema":{"default":"summary","type":"string","enum":["summary","full"]},"in":"query","name":"view","required":false},{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"ticket":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"columnId":{"type":["string","null"]},"title":{"type":"string"},"description":{"type":"string"},"rank":{"type":"string"},"tagIds":{"type":"array","items":{"type":"string"}},"assigneeId":{"type":["string","null"]},"agentAssigneeId":{"anyOf":[{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z][a-z0-9-]*$"},{"type":"null"}]},"attachments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"fileName":{"type":"string","minLength":1},"contentType":{"type":"string","minLength":1},"size":{"type":"integer","minimum":0,"maximum":9007199254740991},"uploadedBy":{"type":"string","minLength":1},"uploadedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","fileName","contentType","size","uploadedBy","uploadedAt"],"additionalProperties":false}},"commentCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"statusChangedAt":{"type":["number","null"]},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"createdBy":{"type":"string"},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","boardId","columnId","title","description","rank","tagIds","assigneeId","agentAssigneeId","attachments","commentCount","statusChangedAt","createdAt","createdBy","updatedAt"],"additionalProperties":false},"distance":{"type":"number","minimum":0,"maximum":2}},"required":["ticket","distance"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"ticket":{"type":"object","properties":{"id":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"columnId":{"type":["string","null"]},"title":{"type":"string"},"assigneeId":{"type":["string","null"]},"agentAssigneeId":{"anyOf":[{"type":"string","minLength":1,"maxLength":40,"pattern":"^[a-z][a-z0-9-]*$"},{"type":"null"}]},"tagIds":{"type":"array","items":{"type":"string"}},"commentCount":{"type":"integer","minimum":0,"maximum":9007199254740991},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"descriptionPreview":{"type":"string","maxLength":160}},"required":["id","boardId","columnId","title","assigneeId","agentAssigneeId","tagIds","commentCount","updatedAt","descriptionPreview"],"additionalProperties":false},"distance":{"type":"number","minimum":0,"maximum":2}},"required":["ticket","distance"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}]}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/boards/{key}/tickets/{ticketKey}/comments":{"get":{"operationId":"list_comments","summary":"List comments on a ticket.","description":"Cursor-paginated. Ordered by `(createdAt, id)` ascending. Includes tombstoned comments (`deletedAt != null`) so consumers can render `[deleted]` placeholders identically to the SPA.","parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false},{"schema":{"type":"string","minLength":1},"in":"query","name":"cursor","required":false},{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"in":"path","name":"ticketKey","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"ticketId":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"authorId":{"type":"string","minLength":1},"parentId":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"body":{"type":"string"},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"editedAt":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"deletedAt":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"deletedBy":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]}},"required":["id","ticketId","boardId","authorId","parentId","body","createdAt","updatedAt","editedAt","deletedAt","deletedBy"],"additionalProperties":false}},"nextCursor":{"type":["string","null"]}},"required":["items","nextCursor"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}},"post":{"operationId":"create_comment","summary":"Post a comment on a ticket.","description":"Creates a top-level comment when `parentId` is null/absent, or a reply when `parentId` references a top-level comment on the same ticket. Replies-to-replies and replies to tombstoned parents are rejected. Increments the ticket's `commentCount` atomically.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":10000},"parentId":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]}},"required":["body"],"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"in":"path","name":"ticketKey","required":true}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","minLength":1},"ticketId":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"authorId":{"type":"string","minLength":1},"parentId":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"body":{"type":"string"},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"editedAt":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"deletedAt":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"deletedBy":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]}},"required":["id","ticketId","boardId","authorId","parentId","body","createdAt","updatedAt","editedAt","deletedAt","deletedBy"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"412":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/boards/{key}/tickets/{ticketKey}/comments/{commentId}":{"get":{"operationId":"get_comment","summary":"Get one comment.","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"in":"path","name":"ticketKey","required":true},{"schema":{"type":"string","minLength":1},"in":"path","name":"commentId","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","minLength":1},"ticketId":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"authorId":{"type":"string","minLength":1},"parentId":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"body":{"type":"string"},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"editedAt":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"deletedAt":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"deletedBy":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]}},"required":["id","ticketId","boardId","authorId","parentId","body","createdAt","updatedAt","editedAt","deletedAt","deletedBy"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}},"patch":{"operationId":"update_comment","summary":"Edit a comment (author only).","description":"Only the comment's author may edit. Tombstoned comments cannot be edited. Sets `editedAt` and `updatedAt` to the current epoch ms.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":10000}},"required":["body"],"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"in":"path","name":"ticketKey","required":true},{"schema":{"type":"string","minLength":1},"in":"path","name":"commentId","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","minLength":1},"ticketId":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"authorId":{"type":"string","minLength":1},"parentId":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"body":{"type":"string"},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"editedAt":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"deletedAt":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"deletedBy":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]}},"required":["id","ticketId","boardId","authorId","parentId","body","createdAt","updatedAt","editedAt","deletedAt","deletedBy"],"additionalProperties":false}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"412":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}},"delete":{"operationId":"delete_comment","summary":"Soft-delete a comment (author or workspace admin).","description":"Sets `deletedAt` and `deletedBy`; preserves `body`. The parent ticket's `commentCount` is decremented atomically. Repeated soft-deletes are idempotent (return the existing tombstone state without further decrementing).","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"in":"path","name":"ticketKey","required":true},{"schema":{"type":"string","minLength":1},"in":"path","name":"commentId","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","minLength":1},"ticketId":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"boardId":{"type":"string","pattern":"^[A-Z]{3,5}$"},"authorId":{"type":"string","minLength":1},"parentId":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]},"body":{"type":"string"},"createdAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"updatedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"editedAt":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"deletedAt":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"deletedBy":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}]}},"required":["id","ticketId","boardId","authorId","parentId","body","createdAt","updatedAt","editedAt","deletedAt","deletedBy"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/boards/{key}/tickets/{ticketKey}/attachments":{"get":{"operationId":"list_attachments","summary":"List a ticket's file attachments.","description":"Returns the attachment metadata (id, filename, content type, size, uploader, timestamp) for a ticket. The bytes are fetched separately via `get_attachment`, which mints a short-lived signed download URL. The same metadata also rides on the ticket itself (`get_ticket` / `resolve_ticket`).","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"in":"path","name":"ticketKey","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"fileName":{"type":"string","minLength":1},"contentType":{"type":"string","minLength":1},"size":{"type":"integer","minimum":0,"maximum":9007199254740991},"uploadedBy":{"type":"string","minLength":1},"uploadedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","fileName","contentType","size","uploadedBy","uploadedAt"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}},"/v1/workspaces/{slug}/boards/{key}/tickets/{ticketKey}/attachments/{attachmentId}":{"get":{"operationId":"get_attachment","summary":"Get an attachment with a temporary download URL.","description":"Returns one attachment's metadata plus a short-lived signed `downloadUrl` (and its `expiresAt`, epoch ms) for fetching the file bytes. The URL is minted per request — do not cache it past `expiresAt`. Use this to actually download a file listed by `list_attachments`.","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){4,19}$"},"in":"path","name":"slug","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}$"},"in":"path","name":"key","required":true},{"schema":{"type":"string","pattern":"^[A-Z]{3,5}-[1-9]\\d*$"},"in":"path","name":"ticketKey","required":true},{"schema":{"type":"string","minLength":1},"in":"path","name":"attachmentId","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"attachment":{"type":"object","properties":{"id":{"type":"string","minLength":1},"fileName":{"type":"string","minLength":1},"contentType":{"type":"string","minLength":1},"size":{"type":"integer","minimum":0,"maximum":9007199254740991},"uploadedBy":{"type":"string","minLength":1},"uploadedAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","fileName","contentType","size","uploadedBy","uploadedAt"],"additionalProperties":false},"downloadUrl":{"type":"string","format":"uri"},"expiresAt":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["attachment","downloadUrl","expiresAt"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["invalid-argument","unauthenticated","permission-denied","not-found","failed-precondition","already-exists","resource-exhausted","internal"]}},"required":["error","code"],"additionalProperties":false}}}}}}}},"servers":[{"url":"https://api.can.randomfact.com"}],"security":[{"oauth2":[]}]}