{ "openapi": "3.0.0", "paths": { "/api/health": { "get": { "operationId": "HealthController_check", "parameters": [], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "example": { "status": "ok", "postgres": "up", "mongo": "up", "redis": "up" } } } } }, "503": { "description": "A database is down" } }, "summary": "API and databases status", "tags": [ "Health" ], "security": [] } }, "/api/auth/config": { "get": { "operationId": "AuthController_config", "parameters": [], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthorizationConfigDto" } } } } }, "summary": "How to sign in with Pireon (null when not configured)", "tags": [ "Auth" ], "security": [] } }, "/api/auth/token": { "post": { "description": "For browsers (Pireon has no CORS) and Swagger UI: adds the client secret server-side. Apps with their own Pireon OAuth client can get tokens from Pireon directly; any valid Pireon access token is accepted by this API.", "operationId": "AuthController_token", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IssueTokenDto" } }, "application/x-www-form-urlencoded": { "schema": { "$ref": "#/components/schemas/IssueTokenDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TokenResponseDto" } } } }, "401": { "description": "Pireon rejected the grant" } }, "summary": "Exchange a grant for Pireon tokens (proxy of Pireon /oauth/token)", "tags": [ "Auth" ], "security": [] } }, "/api/users/me": { "get": { "operationId": "UsersController_me", "parameters": [], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MeDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "The user behind the access token", "tags": [ "Users" ] } }, "/api/users": { "get": { "description": "Needs the `users:read` scope in the access token.", "operationId": "UsersController_search", "parameters": [ { "name": "search", "required": false, "in": "query", "description": "Name or email", "schema": { "default": "", "type": "string" } }, { "name": "limit", "required": false, "in": "query", "schema": { "minimum": 1, "maximum": 100, "default": 20, "type": "number" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/UserDto" } } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Search Pireon users (to assign tickets or add members)", "tags": [ "Users" ] } }, "/api/users/{id}": { "get": { "operationId": "UsersController_findOne", "parameters": [ { "name": "id", "required": true, "in": "path", "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "A Pireon user", "tags": [ "Users" ] } }, "/api/webhooks/pireon": { "post": { "description": "`user.deactivated` closes the user's sessions; `token.revoked` forgets the token. Disabled unless PIREON_WEBHOOK_SECRET or PIREON_PASSWORD_WEBHOOK_SECRET is set.", "operationId": "PireonWebhookController_receive", "parameters": [ { "name": "x-webhook-signature", "required": true, "in": "header", "schema": { "type": "string" } }, { "name": "X-Webhook-Signature", "in": "header", "description": "HMAC-SHA256 of the raw body with the secret of the Pireon client that registered the webhook (hex)", "required": true, "schema": { "type": "string" } } ], "responses": { "204": { "description": "Processed" }, "401": { "description": "Missing or invalid signature" } }, "summary": "Pireon events (called by Pireon, not by apps)", "tags": [ "Webhooks" ], "security": [] } }, "/api/calendar/{file}": { "get": { "description": "Unfinished tickets with a due date (assigned or followed), planned and running sprints, and planned releases with a date, as all-day events.", "operationId": "CalendarController_ics", "parameters": [ { "name": "file", "required": true, "in": "path", "schema": { "type": "string" } } ], "responses": { "200": { "description": "" } }, "summary": "A calendar to subscribe to (`{token}.ics`, no session)", "tags": [ "Users" ], "security": [] } }, "/api/me/calendar": { "get": { "operationId": "CalendarController_mine", "parameters": [], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CalendarFeedDto" } } } }, "204": { "description": "I have none" } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "My calendar URL, if I made one", "tags": [ "Users" ] }, "post": { "operationId": "CalendarController_create", "parameters": [], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CalendarFeedDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "A new secret calendar URL (the previous one stops working)", "tags": [ "Users" ] }, "delete": { "operationId": "CalendarController_revoke", "parameters": [], "responses": { "204": { "description": "" } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "My calendar URL stops working", "tags": [ "Users" ] } }, "/api/projects": { "get": { "operationId": "ProjectsController_mine", "parameters": [], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ProjectDto" } } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Projects where I am a member", "tags": [ "Projects" ] }, "post": { "operationId": "ProjectsController_create", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateProjectDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Create a project (you become its owner)", "tags": [ "Projects" ] } }, "/api/projects/{project}": { "get": { "operationId": "ProjectsController_findOne", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProjectDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "A project with its members and settings", "tags": [ "Projects" ] }, "patch": { "operationId": "ProjectsController_update", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateProjectDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Rename, describe or make public/private a project (owner/admin)", "tags": [ "Projects" ] }, "delete": { "description": "Deletes the project and, right after (asynchronously, through a saga), its tickets, comments and releases; links from tickets of other projects are removed and the key becomes free. Cannot be undone from the API. `confirm` must be the project key.", "operationId": "ProjectsController_remove", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } }, { "name": "confirm", "required": true, "in": "query", "description": "The project key, to confirm the deletion", "schema": { "example": "WEB", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Delete a project (owner only)", "tags": [ "Projects" ] } }, "/api/projects/{project}/settings": { "put": { "description": "Replaces the whole configuration (send what GET /projects/{project} returns, changed). Values can be added, renamed, reordered or archived, never removed: tickets and statistics keep referring to them.", "operationId": "ProjectsController_updateSettings", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProjectSettingsBodyDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Statuses, transitions, ticket types and areas (owner/admin)", "tags": [ "Projects" ] } }, "/api/projects/{project}/board": { "get": { "operationId": "ProjectsController_board", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } }, { "name": "releaseId", "required": false, "in": "query", "description": "Only this release", "schema": { "format": "uuid", "type": "string" } }, { "name": "assigneeId", "required": false, "in": "query", "description": "Only this person (Pireon user id)", "schema": { "type": "string" } }, { "name": "area", "required": false, "in": "query", "description": "An area id", "schema": { "example": "FRONTEND", "type": "string" } }, { "name": "type", "required": false, "in": "query", "description": "Ticket type ids", "schema": { "type": "array", "items": { "type": "string" } } }, { "name": "priority", "required": false, "in": "query", "schema": { "type": "array", "items": { "$ref": "#/components/schemas/IssuePriority" } } }, { "name": "label", "required": false, "in": "query", "schema": { "type": "array", "items": { "type": "string" } } }, { "name": "search", "required": false, "in": "query", "description": "Matches key, title or description", "schema": { "type": "string" } }, { "name": "unassigned", "required": false, "in": "query", "description": "Only tickets without assignee", "schema": { "type": "boolean" } }, { "name": "sprintId", "required": false, "in": "query", "description": "Only this sprint", "schema": { "format": "uuid", "type": "string" } }, { "name": "perColumn", "required": false, "in": "query", "schema": { "minimum": 1, "maximum": 200, "default": 50, "type": "number" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/BoardColumnDto" } } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Kanban board: one column per status", "tags": [ "Projects" ] } }, "/api/projects/{project}/stats": { "get": { "operationId": "ProjectsController_stats", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProjectStatsDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Tracking dashboard: counts by status, type, person…", "tags": [ "Projects" ] } }, "/api/projects/{project}/analytics": { "get": { "description": "Created vs resolved per week, cumulative flow per day, cycle and lead time, throughput per person and QA pass/fail.", "operationId": "ProjectsController_analytics", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } }, { "name": "days", "required": false, "in": "query", "schema": { "minimum": 7, "maximum": 365, "default": 90, "type": "number" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProjectAnalyticsDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Statistics of the last `days` days", "tags": [ "Projects" ] } }, "/api/projects/{project}/insights": { "get": { "description": "Sprint under way (pace against time), overdue, due-soon, blocked and stuck tickets, aging of the work under way against the p85 cycle time, and average days in each in-progress and QA status.", "operationId": "ProjectsController_insights", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } }, { "name": "since", "required": false, "in": "query", "description": "ISO instant (e.g. your last visit): the answer also tells what changed after it", "schema": { "example": "2026-10-14T08:00:00Z", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProjectInsightsDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "The dashboard", "tags": [ "Projects" ] } }, "/api/projects/{project}/activity": { "get": { "operationId": "ProjectsController_activity", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } }, { "name": "issueId", "required": false, "in": "query", "description": "Only this ticket", "schema": { "format": "uuid", "type": "string" } }, { "name": "limit", "required": false, "in": "query", "schema": { "minimum": 1, "maximum": 200, "default": 50, "type": "number" } }, { "name": "before", "required": false, "in": "query", "description": "Cursor: entries older than this date", "schema": { "format": "date-time", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ActivityDto" } } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Activity feed (newest first)", "tags": [ "Projects" ] } }, "/api/projects/{project}/members": { "post": { "description": "The user must exist and be active in Pireon.", "operationId": "ProjectsController_addMember", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AddMemberDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Add a Pireon user to the project (owner/admin)", "tags": [ "Projects" ] } }, "/api/projects/{project}/members/{userId}": { "patch": { "operationId": "ProjectsController_changeMemberRole", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } }, { "name": "userId", "required": true, "in": "path", "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChangeMemberRoleDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Change a member's role (owner/admin)", "tags": [ "Projects" ] }, "delete": { "operationId": "ProjectsController_removeMember", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } }, { "name": "userId", "required": true, "in": "path", "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Remove a member (owner/admin, or yourself to leave)", "tags": [ "Projects" ] } }, "/api/issues/{issue}/watch": { "put": { "description": "Followers are told when it moves, is reassigned or gets a comment. Commenting follows it too.", "operationId": "IssuesController_watch", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Follow a ticket (members, viewers included)", "tags": [ "Issues" ] }, "delete": { "operationId": "IssuesController_unwatch", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Stop following a ticket", "tags": [ "Issues" ] } }, "/api/me/issues": { "get": { "description": "Assigned to me by default; with assignedToMe=false, any ticket of my projects (e.g. waiting for QA).", "operationId": "IssuesController_mine", "parameters": [ { "name": "limit", "required": false, "in": "query", "schema": { "minimum": 1, "maximum": 200, "default": 50, "type": "number" } }, { "name": "offset", "required": false, "in": "query", "schema": { "minimum": 0, "default": 0, "type": "number" } }, { "name": "assignedToMe", "required": false, "in": "query", "description": "true: tickets assigned to me. false: any ticket of my projects (e.g. ?assignedToMe=false&category=QA)", "schema": { "default": true, "type": "boolean" } }, { "name": "watching", "required": false, "in": "query", "description": "Only the tickets I follow (with assignedToMe=false, whoever they are assigned to)", "schema": { "type": "boolean" } }, { "name": "status", "required": false, "in": "query", "description": "Status ids. Repeat the parameter or separate with commas", "schema": { "type": "array", "items": { "type": "string" } } }, { "name": "category", "required": false, "in": "query", "description": "Whatever each project calls its statuses", "schema": { "type": "array", "items": { "$ref": "#/components/schemas/StatusCategory" } } }, { "name": "search", "required": false, "in": "query", "description": "Matches key, title or description", "schema": { "type": "string" } }, { "name": "project", "required": false, "in": "query", "description": "Only these of my projects (ids). Repeat or separate with commas", "schema": { "type": "array", "items": { "type": "string" } } }, { "name": "priority", "required": false, "in": "query", "schema": { "type": "array", "items": { "$ref": "#/components/schemas/IssuePriority" } } }, { "name": "bugsOnly", "required": false, "in": "query", "description": "Only types with the bug icon", "schema": { "type": "boolean" } }, { "name": "overdue", "required": false, "in": "query", "description": "Only open tickets past their due date", "schema": { "type": "boolean" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IssuePageDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "My work: tickets across all my projects", "tags": [ "Issues" ] } }, "/api/projects/{project}/issues": { "get": { "operationId": "IssuesController_search", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } }, { "name": "limit", "required": false, "in": "query", "schema": { "minimum": 1, "maximum": 200, "default": 50, "type": "number" } }, { "name": "offset", "required": false, "in": "query", "schema": { "minimum": 0, "default": 0, "type": "number" } }, { "name": "status", "required": false, "in": "query", "description": "Status ids. Repeat the parameter or separate with commas", "schema": { "type": "array", "items": { "type": "string" } } }, { "name": "category", "required": false, "in": "query", "schema": { "type": "array", "items": { "$ref": "#/components/schemas/StatusCategory" } } }, { "name": "type", "required": false, "in": "query", "description": "Ticket type ids", "schema": { "type": "array", "items": { "type": "string" } } }, { "name": "area", "required": false, "in": "query", "description": "Area ids", "schema": { "type": "array", "items": { "type": "string" } } }, { "name": "priority", "required": false, "in": "query", "schema": { "type": "array", "items": { "$ref": "#/components/schemas/IssuePriority" } } }, { "name": "assigneeId", "required": false, "in": "query", "description": "Pireon user id", "schema": { "type": "string" } }, { "name": "unassigned", "required": false, "in": "query", "description": "Only tickets without assignee", "schema": { "type": "boolean" } }, { "name": "releaseId", "required": false, "in": "query", "schema": { "format": "uuid", "type": "string" } }, { "name": "label", "required": false, "in": "query", "schema": { "type": "array", "items": { "type": "string" } } }, { "name": "parent", "required": false, "in": "query", "description": "Only the tickets hanging from this one (id or key)", "schema": { "example": "WEB-3", "type": "string" } }, { "name": "sprintId", "required": false, "in": "query", "description": "Only this sprint", "schema": { "format": "uuid", "type": "string" } }, { "name": "noSprint", "required": false, "in": "query", "description": "Only tickets in no sprint", "schema": { "type": "boolean" } }, { "name": "watching", "required": false, "in": "query", "description": "Only the tickets I follow (none without a token)", "schema": { "type": "boolean" } }, { "name": "dueFrom", "required": false, "in": "query", "description": "Due on or after this day", "schema": { "format": "date", "type": "string" } }, { "name": "dueTo", "required": false, "in": "query", "description": "Due on or before this day", "schema": { "format": "date", "type": "string" } }, { "name": "noEstimate", "required": false, "in": "query", "description": "Only tickets nobody estimated", "schema": { "type": "boolean" } }, { "name": "noArea", "required": false, "in": "query", "description": "Only tickets with no area", "schema": { "type": "boolean" } }, { "name": "updatedBefore", "required": false, "in": "query", "description": "Only tickets not updated since this instant (ISO)", "schema": { "type": "string" } }, { "name": "field", "required": false, "in": "query", "description": "Custom values the tickets must hold, as FIELD:value. Repeat the parameter for several", "schema": { "example": [ "BROWSER:Safari" ], "type": "array", "items": { "type": "string" } } }, { "name": "sort", "required": false, "in": "query", "description": "RECENT (default): last updated first. RANK: backlog order.", "schema": { "$ref": "#/components/schemas/IssueSort" } }, { "name": "search", "required": false, "in": "query", "description": "Matches key, title or description", "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IssuePageDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Search the tickets of a project", "tags": [ "Issues" ] }, "post": { "description": "Starts in the project's first active TODO-category status (BACKLOG by default). The response carries its key (e.g. WEB-13).", "operationId": "IssuesController_create", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateIssueDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Create a ticket", "tags": [ "Issues" ] } }, "/api/projects/{project}/epics": { "get": { "description": "With the progress of the tickets hanging from each one (done or cancelled, and story points).", "operationId": "IssuesController_epics", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/EpicDto" } } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Epics: top-level tickets that group others", "tags": [ "Issues" ] } }, "/api/issues/{issue}": { "get": { "operationId": "IssuesController_findOne", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IssueDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "A ticket", "tags": [ "Issues" ] }, "patch": { "operationId": "IssuesController_update", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateIssueDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Edit title, description, type, priority, area, labels…", "tags": [ "Issues" ] }, "delete": { "description": "Whoever opened it, or an owner/admin. Hidden everywhere; restore it within 30 days or it is deleted for good.", "operationId": "IssuesController_trash", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Move the ticket to the trash", "tags": [ "Issues" ] } }, "/api/issues/{issue}/status": { "put": { "description": "Only the transitions in `allowedTransitions` are accepted (422 otherwise). QA_FAILED and CANCELLED need a reason.", "operationId": "IssuesController_changeStatus", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChangeStatusDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Move the ticket through the workflow (incl. QA)", "tags": [ "Issues" ] } }, "/api/issues/{issue}/assignee": { "put": { "operationId": "IssuesController_assign", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AssignIssueDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Assign to a project member (null to unassign)", "tags": [ "Issues" ] } }, "/api/issues/{issue}/release": { "put": { "operationId": "IssuesController_setRelease", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetIssueReleaseDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Put the ticket in a planned release (null takes it out)", "tags": [ "Issues" ] } }, "/api/issues/{issue}/restore": { "post": { "operationId": "IssuesController_restore", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Bring the ticket back from the trash", "tags": [ "Issues" ] } }, "/api/issues/{issue}/vote": { "put": { "description": "Anyone signed in, on a public project (that is the point: the people it is for say what they want); members on a private one. Voting twice changes nothing.", "operationId": "IssuesController_vote", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Vote for the ticket", "tags": [ "Issues" ] }, "delete": { "operationId": "IssuesController_unvote", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Take back my vote for the ticket", "tags": [ "Issues" ] } }, "/api/issues/{issue}/duplicate": { "post": { "description": "Copies what it says (type, title, description, area, priority, labels, Figma, estimate, dates, parent and checklist steps, unticked), not where it stands: the copy starts in the first status, unassigned, out of sprints and releases, without comments or files. The result carries its key.", "operationId": "IssuesController_duplicate", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Duplicate the ticket", "tags": [ "Issues" ] } }, "/api/projects/{project}/trash": { "get": { "operationId": "IssuesController_trashed", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/IssueDto" } } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "The project's tickets in the trash, newest first", "tags": [ "Issues" ] } }, "/api/issues/bulk": { "post": { "description": "Each ticket goes through the normal rules (permissions, workflow, open sprints and releases) and may refuse on its own; the answer says which.", "operationId": "IssuesController_bulkUpdate", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkUpdateIssuesDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulkResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "The same change on up to 100 tickets", "tags": [ "Issues" ] } }, "/api/issues/{issue}/parent": { "put": { "description": "Same project, three levels at most (epic → ticket → subtask), no loops. null takes it back to the top.", "operationId": "IssuesController_setParent", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetIssueParentDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Place the ticket under an epic or another ticket", "tags": [ "Issues" ] } }, "/api/issues/{issue}/rank": { "put": { "description": "Between the ticket that ends up above it and the one below (either may be left out for the top or the bottom). Board columns follow the same order.", "operationId": "IssuesController_rank", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RankIssueDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Move the ticket in the backlog", "tags": [ "Issues" ] } }, "/api/issues/{issue}/checklist": { "post": { "operationId": "IssuesController_addChecklistItem", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChecklistItemBodyDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Add a step to the ticket's checklist", "tags": [ "Issues" ] } }, "/api/issues/{issue}/checklist/{item}": { "patch": { "operationId": "IssuesController_updateChecklistItem", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } }, { "name": "item", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateChecklistItemDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Reword, tick or untick a checklist step", "tags": [ "Issues" ] }, "delete": { "operationId": "IssuesController_removeChecklistItem", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } }, { "name": "item", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Remove a checklist step", "tags": [ "Issues" ] } }, "/api/issues/{issue}/links": { "post": { "description": "e.g. WEB-3 DEPENDS_ON API-7, WEB-9 TESTS WEB-3. May cross projects.", "operationId": "IssuesController_link", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LinkIssueDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Relate tickets (FE ↔ BE ↔ QA)", "tags": [ "Issues" ] } }, "/api/issues/{issue}/links/{type}/{target}": { "delete": { "operationId": "IssuesController_unlink", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } }, { "name": "type", "required": true, "in": "path", "schema": { "$ref": "#/components/schemas/IssueLinkType" } }, { "name": "target", "required": true, "in": "path", "description": "Other ticket: id or key", "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Remove a relation", "tags": [ "Issues" ] } }, "/api/issues/{issue}/comments": { "get": { "operationId": "IssuesController_listComments", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } }, { "name": "limit", "required": false, "in": "query", "schema": { "minimum": 1, "maximum": 200, "default": 50, "type": "number" } }, { "name": "offset", "required": false, "in": "query", "schema": { "minimum": 0, "default": 0, "type": "number" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentPageDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Comments of the ticket (oldest first)", "tags": [ "Issues" ] }, "post": { "operationId": "IssuesController_addComment", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AddCommentDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Comment on the ticket, or answer a comment (replyTo)", "tags": [ "Issues" ] } }, "/api/issues/{issue}/history": { "get": { "operationId": "IssuesController_history", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } }, { "name": "limit", "required": false, "in": "query", "schema": { "minimum": 1, "maximum": 200, "default": 50, "type": "number" } }, { "name": "offset", "required": false, "in": "query", "schema": { "minimum": 0, "default": 0, "type": "number" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ActivityDto" } } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "History of the ticket (newest first)", "tags": [ "Issues" ] } }, "/api/issues/{issue}/attachments": { "post": { "description": "Multipart with the file as `file` and, optionally, `commentId` to place it under a comment. Up to ATTACHMENTS_MAX_MB megabytes (25 by default) and 50 files per ticket.", "operationId": "AttachmentsController_attach", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "$ref": "#/components/schemas/AttachFileDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AttachmentResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Attach a file to a ticket (members)", "tags": [ "Issues" ] } }, "/api/issues/{issue}/attachments/{attachmentId}": { "get": { "operationId": "AttachmentsController_download", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } }, { "name": "attachmentId", "required": true, "in": "path", "schema": { "type": "string" } } ], "responses": { "200": { "description": "The file" }, "400": { "description": "Invalid input", "content": { "application/octet-stream": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/octet-stream": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/octet-stream": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/octet-stream": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Download one of a ticket's files", "tags": [ "Issues" ] }, "delete": { "operationId": "AttachmentsController_remove", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } }, { "name": "attachmentId", "required": true, "in": "path", "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Remove a file (whoever uploaded it, or an owner/admin)", "tags": [ "Issues" ] } }, "/api/comments/{commentId}": { "patch": { "operationId": "CommentsController_edit", "parameters": [ { "name": "commentId", "required": true, "in": "path", "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentBodyDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Edit a comment (author only)", "tags": [ "Comments" ] }, "delete": { "operationId": "CommentsController_delete", "parameters": [ { "name": "commentId", "required": true, "in": "path", "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Delete a comment (author or project admin)", "tags": [ "Comments" ] } }, "/api/comments/{commentId}/reactions": { "post": { "description": "One of 👍 👎 😄 🎉 😕 ❤️ 🚀 👀; repeating it changes nothing.", "operationId": "CommentsController_react", "parameters": [ { "name": "commentId", "required": true, "in": "path", "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReactToCommentDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "React to a comment, or take the reaction back (members)", "tags": [ "Comments" ] } }, "/api/me/releases": { "get": { "operationId": "ReleasesController_upcoming", "parameters": [ { "name": "limit", "required": false, "in": "query", "schema": { "minimum": 1, "maximum": 50, "default": 10, "type": "number" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ReleaseDto" } } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Planned releases of all my projects, soonest target date first", "tags": [ "Releases" ] } }, "/api/projects/{project}/releases": { "get": { "operationId": "ReleasesController_list", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ReleaseDto" } } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Releases of a project", "tags": [ "Releases" ] }, "post": { "operationId": "ReleasesController_create", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateReleaseDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Plan a release (owner/admin)", "tags": [ "Releases" ] } }, "/api/releases/{releaseId}": { "get": { "operationId": "ReleasesController_findOne", "parameters": [ { "name": "releaseId", "required": true, "in": "path", "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReleaseDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "A release", "tags": [ "Releases" ] }, "patch": { "operationId": "ReleasesController_update", "parameters": [ { "name": "releaseId", "required": true, "in": "path", "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateReleaseDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Rename, describe or move the target date", "tags": [ "Releases" ] } }, "/api/releases/{releaseId}/progress": { "get": { "operationId": "ReleasesController_progress", "parameters": [ { "name": "releaseId", "required": true, "in": "path", "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReleaseProgressDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Finished tickets out of the total", "tags": [ "Releases" ] } }, "/api/releases/{releaseId}/burnup": { "get": { "operationId": "ReleasesController_burnup", "parameters": [ { "name": "releaseId", "required": true, "in": "path", "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReleaseBurnupDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Burnup: tickets in the release and finished ones, day by day", "tags": [ "Releases" ] } }, "/api/releases/{releaseId}/issues": { "get": { "operationId": "ReleasesController_issuesOf", "parameters": [ { "name": "releaseId", "required": true, "in": "path", "schema": { "type": "string" } }, { "name": "limit", "required": false, "in": "query", "schema": { "minimum": 1, "maximum": 200, "default": 50, "type": "number" } }, { "name": "offset", "required": false, "in": "query", "schema": { "minimum": 0, "default": 0, "type": "number" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IssuePageDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Tickets included in the release", "tags": [ "Releases" ] } }, "/api/releases/{releaseId}/publish": { "post": { "description": "Fails (422) while it has unfinished tickets unless `force` is true.", "operationId": "ReleasesController_publish", "parameters": [ { "name": "releaseId", "required": true, "in": "path", "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PublishReleaseDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Ship the release", "tags": [ "Releases" ] } }, "/api/releases/{releaseId}/notes": { "put": { "description": "Also after the release ships; not once archived.", "operationId": "ReleasesController_writeNotes", "parameters": [ { "name": "releaseId", "required": true, "in": "path", "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReleaseNotesDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Write the release notes (Markdown)", "tags": [ "Releases" ] } }, "/api/releases/{releaseId}/notes/draft": { "get": { "description": "Grouped by type; nothing is saved.", "operationId": "ReleasesController_notesDraft", "parameters": [ { "name": "releaseId", "required": true, "in": "path", "schema": { "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReleaseNotesDraftDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "A Markdown draft of the notes from the finished tickets", "tags": [ "Releases" ] } }, "/api/releases/{releaseId}/archive": { "post": { "description": "Its unfinished tickets move to `moveTo` (an open release of the same project) or leave it.", "operationId": "ReleasesController_archive", "parameters": [ { "name": "releaseId", "required": true, "in": "path", "schema": { "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ArchiveReleaseDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Archive a planned release", "tags": [ "Releases" ] } }, "/api/explore/projects": { "get": { "description": "Their board, tickets, comments, releases, activity and statistics can be read without a token too.", "operationId": "ExploreController_publicProjects", "parameters": [], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ProjectDto" } } } } } }, "summary": "Public projects (no token needed)", "tags": [ "Explore" ], "security": [] } }, "/api/explore/projects/{project}/showcase": { "get": { "description": "For public websites: epics with their dates and progress, the latest releases (with the notes of shipped ones), the sprint under way and open tickets labelled good-first-issue. Paths point into the web app.", "operationId": "ExploreController_showcase", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ShowcaseDto" } } } }, "404": { "description": "Not a public project" } }, "summary": "A public project's showcase (no token needed)", "tags": [ "Explore" ], "security": [] } }, "/api/explore/projects/{project}/proposals": { "post": { "description": "For public projects that take proposals. It becomes a ticket labelled `propuesta`, opened by TaskStream in the first status (Bug or Feature), signed with `author` if given. Five per address every 15 minutes.", "operationId": "ExploreController_propose", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProposalDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProposalResultDto" } } } }, "403": { "description": "It does not take proposals" }, "404": { "description": "Not a public project" }, "429": { "description": "Too many from this address" } }, "summary": "Report a bug or propose an idea (no token needed)", "tags": [ "Explore" ], "security": [] } }, "/api/me/notifications": { "get": { "operationId": "NotificationsController_mine", "parameters": [ { "name": "unreadOnly", "required": false, "in": "query", "description": "Only unread ones", "schema": { "default": false, "type": "boolean" } }, { "name": "limit", "required": false, "in": "query", "schema": { "minimum": 1, "maximum": 100, "default": 30, "type": "number" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MyNotificationsDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "My notifications, newest first", "tags": [ "Users" ] } }, "/api/me/notifications/read": { "post": { "operationId": "NotificationsController_markRead", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MarkNotificationsReadDto" } } } }, "responses": { "200": { "description": "Done" }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Mark notifications as read (all of them without `ids`)", "tags": [ "Users" ] } }, "/api/me/notification-settings": { "get": { "operationId": "NotificationsController_settings", "parameters": [], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificationSettingsResponseDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Whether I get copies by e-mail", "tags": [ "Users" ] }, "put": { "operationId": "NotificationsController_updateSettings", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificationSettingsDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NotificationSettingsResponseDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Turn e-mail copies on or off", "tags": [ "Users" ] } }, "/api/me/push-subscriptions": { "post": { "operationId": "NotificationsController_subscribePush", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PushSubscriptionDto" } } } }, "responses": { "204": { "description": "" }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Push on this device (a browser's Web Push subscription)", "tags": [ "Users" ] }, "delete": { "operationId": "NotificationsController_unsubscribePush", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PushEndpointDto" } } } }, "responses": { "204": { "description": "" } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Push off on this device", "tags": [ "Users" ] } }, "/api/projects/{project}/filters": { "get": { "operationId": "SavedFiltersController_list", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/SavedFilterDto" } } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "My views of the project's board, then the shared ones", "tags": [ "Saved filters" ] }, "post": { "description": "Project members only. `shared` makes it visible to the whole project (not for viewers).", "operationId": "SavedFiltersController_save", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SaveFilterDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SavedFilterIdDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Save board filters under a name", "tags": [ "Saved filters" ] } }, "/api/filters/{id}": { "delete": { "operationId": "SavedFiltersController_delete", "parameters": [ { "name": "id", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "responses": { "204": { "description": "" }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Delete a saved view (whoever saved it, or an admin if shared)", "tags": [ "Saved filters" ] } }, "/api/me/views": { "get": { "operationId": "SavedFiltersController_myViews", "parameters": [], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/MyViewDto" } } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "My saved views of my work, across my projects (by name)", "tags": [ "Saved filters" ] }, "post": { "description": "Run it with GET /api/me/issues and the same criteria (project, priority, bugsOnly, overdue…).", "operationId": "SavedFiltersController_saveMyView", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SaveMyViewDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SavedFilterIdDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Save a view of my work under a name", "tags": [ "Saved filters" ] } }, "/api/me/views/{id}": { "delete": { "operationId": "SavedFiltersController_deleteMyView", "parameters": [ { "name": "id", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "responses": { "204": { "description": "" }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Delete one of my views", "tags": [ "Saved filters" ] } }, "/api/projects/{project}/sprints": { "get": { "description": "The one under way, the planned ones, then the closed ones.", "operationId": "SprintsController_list", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/SprintDto" } } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "A project's sprints", "tags": [ "Sprints" ] }, "post": { "operationId": "SprintsController_create", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateSprintDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Plan a sprint (owners and admins)", "tags": [ "Sprints" ] } }, "/api/sprints/{sprint}": { "get": { "operationId": "SprintsController_findOne", "parameters": [ { "name": "sprint", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SprintDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "A sprint", "tags": [ "Sprints" ] }, "patch": { "operationId": "SprintsController_update", "parameters": [ { "name": "sprint", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateSprintDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Rename, re-date or change the goal (not once closed)", "tags": [ "Sprints" ] }, "delete": { "description": "Its tickets go back to the backlog.", "operationId": "SprintsController_delete", "parameters": [ { "name": "sprint", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Delete a sprint that never started", "tags": [ "Sprints" ] } }, "/api/sprints/{sprint}/start": { "post": { "operationId": "SprintsController_start", "parameters": [ { "name": "sprint", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Start a planned sprint (only one under way per project)", "tags": [ "Sprints" ] } }, "/api/sprints/{sprint}/close": { "post": { "description": "Unfinished tickets move to `carryOverTo` (another open sprint) or back to the backlog; finished ones stay as its record.", "operationId": "SprintsController_close", "parameters": [ { "name": "sprint", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CloseSprintDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Close the sprint under way", "tags": [ "Sprints" ] } }, "/api/sprints/{sprint}/progress": { "get": { "operationId": "SprintsController_progress", "parameters": [ { "name": "sprint", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SprintProgressDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Finished tickets and points", "tags": [ "Sprints" ] } }, "/api/sprints/{sprint}/burndown": { "get": { "operationId": "SprintsController_burndown", "parameters": [ { "name": "sprint", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SprintBurndownDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Open tickets and points, day by day, against the ideal line", "tags": [ "Sprints" ] } }, "/api/sprints/{sprint}/issues": { "get": { "operationId": "SprintsController_issuesOf", "parameters": [ { "name": "sprint", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } }, { "name": "limit", "required": false, "in": "query", "schema": { "minimum": 1, "maximum": 200, "default": 50, "type": "number" } }, { "name": "offset", "required": false, "in": "query", "schema": { "minimum": 0, "default": 0, "type": "number" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IssuePageDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Tickets in the sprint, in backlog order", "tags": [ "Sprints" ] } }, "/api/issues/{issue}/sprint": { "put": { "operationId": "SprintsController_setIssueSprint", "parameters": [ { "name": "issue", "required": true, "in": "path", "description": "Ticket id or key", "schema": { "example": "WEB-12", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetIssueSprintDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommandResultDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Put the ticket in a sprint (null: the backlog)", "tags": [ "Sprints" ] } }, "/api/projects/{project}/git-integration": { "get": { "operationId": "GitController_integration", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GitIntegrationDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "The project's repositories and the webhook URL they share (secrets, for admins)", "tags": [ "Git" ] } }, "/api/projects/{project}/git-integration/repositories": { "post": { "description": "Turns the integration on with the first one. Every repository uses the same webhook URL; its secret tells them apart.", "operationId": "GitController_addRepository", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AddGitRepositoryDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GitRepositoryDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Add a repository, with its own secret (owners and admins)", "tags": [ "Git" ] } }, "/api/projects/{project}/git-integration/repositories/{repository}/secret": { "post": { "operationId": "GitController_rotateSecret", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } }, { "name": "repository", "required": true, "in": "path", "description": "Repository id", "schema": { "type": "string" } } ], "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GitRepositoryDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Give a repository a new secret (the old one stops working)", "tags": [ "Git" ] } }, "/api/projects/{project}/git-integration/repositories/{repository}": { "delete": { "operationId": "GitController_removeRepository", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } }, { "name": "repository", "required": true, "in": "path", "description": "Repository id", "schema": { "type": "string" } } ], "responses": { "204": { "description": "" }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Remove a repository: its webhooks are refused, what it linked stays", "tags": [ "Git" ] } }, "/api/webhooks/git/{project}": { "post": { "description": "Push and pull/merge request events from any repository of the project; the secret it signs with says which (GitHub and Gitea: HMAC-SHA256 of the body; GitLab: X-Gitlab-Token). Other events are acknowledged and ignored.", "operationId": "GitController_receive", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GitDeliveryResultDto" } } } }, "403": { "description": "Unknown project, integration off or bad signature" } }, "summary": "Webhook for GitHub, Gitea or GitLab (called by the Git host)", "tags": [ "Git" ], "security": [] } }, "/api/webhook-events": { "get": { "operationId": "WebhooksController_events", "parameters": [], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "string" } } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Event names a webhook can subscribe to", "tags": [ "Webhooks" ] } }, "/api/projects/{project}/webhooks": { "get": { "operationId": "WebhooksController_list", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/WebhookDto" } } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "The project's webhooks (owners and admins)", "tags": [ "Webhooks" ] }, "post": { "description": "The answer carries the secret, the only time it is shown.", "operationId": "WebhooksController_create", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateWebhookDto" } } } }, "responses": { "201": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookCreatedDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Add a webhook", "tags": [ "Webhooks" ] } }, "/api/outgoing-webhooks/{webhook}": { "patch": { "operationId": "WebhooksController_update", "parameters": [ { "name": "webhook", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UpdateWebhookDto" } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Change the URL or the events, pause or resume", "tags": [ "Webhooks" ] }, "delete": { "operationId": "WebhooksController_delete", "parameters": [ { "name": "webhook", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "responses": { "204": { "description": "" }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Delete a webhook", "tags": [ "Webhooks" ] } }, "/api/outgoing-webhooks/{webhook}/test": { "post": { "operationId": "WebhooksController_test", "parameters": [ { "name": "webhook", "required": true, "in": "path", "schema": { "format": "uuid", "type": "string" } } ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookDeliveryDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Send a ping now and tell how it went", "tags": [ "Webhooks" ] } }, "/api/projects/{project}/export.csv": { "get": { "description": "UTF-8 with BOM. Cells that a spreadsheet would run as a formula start with a quote mark.", "operationId": "TransferController_exportCsv", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } } ], "responses": { "200": { "description": "The CSV file" }, "400": { "description": "Invalid input", "content": { "text/csv": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "text/csv": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "text/csv": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "text/csv": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] }, {} ], "summary": "Every ticket of the project as CSV", "tags": [ "Import and export" ] } }, "/api/projects/{project}/import": { "post": { "description": "TaskStream export or Jira CSV export, up to 5 MB and 2000 rows. Types, statuses and people are matched by id or name; the rest falls back with a warning. With dryRun=true nothing is created.", "operationId": "TransferController_importCsv", "parameters": [ { "name": "project", "required": true, "in": "path", "description": "Project id or key", "schema": { "example": "WEB", "type": "string" } }, { "name": "dryRun", "required": false, "in": "query", "description": "Only tell what would be created", "schema": { "default": false, "type": "boolean" } } ], "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "type": "object", "properties": { "file": { "type": "string", "format": "binary" } }, "required": [ "file" ] } } } }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImportReportDto" } } } }, "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "401": { "description": "Missing or rejected Pireon token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "403": { "description": "Not a member of the project (or not allowed)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "409": { "description": "Someone changed it at the same time: retry", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } }, "422": { "description": "Business rule (e.g. a transition the workflow forbids)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiErrorDto" } } } } }, "security": [ { "pireon-oauth": [] }, { "pireon": [] } ], "summary": "Create tickets from a CSV (owners and admins)", "tags": [ "Import and export" ] } } }, "info": { "title": "Pireon TaskStream API", "description": "REST API of **Pireon TaskStream** for other apps: projects, tickets (bugs, features,\nUI changes, tasks and QA), workflow, comments, relations and releases.\n\n### Authentication\nEvery endpoint (except `/auth`, `/health` and the webhook) needs a **Pireon access\ntoken**, so any app or user that consumes it goes through Pireon's OAuth:\n\n- **Authorization Code + PKCE** against `oauth.pireon.dev/oauth/authorize`\n (the \"Authorize\" button here uses it; register `/api/docs/oauth2-redirect.html`\n as a redirect URI of the client).\n- An app with its own Pireon OAuth client can get tokens from Pireon directly and\n send them as `Authorization: Bearer `.\n\nWhat you can see and change depends on your role in each project.\n\n### Writes are eventually consistent\nCommands answer `{ id, key?, version }` as soon as the event is stored. Reads come from\na read model that catches up in milliseconds: a `GET` right after a write may still\nshow the previous version (or 404 right after a create).\n\n### Real time\nFor live updates use the GraphQL subscriptions at `/graphql` (graphql-ws).", "version": "1.0.0", "contact": {} }, "tags": [ { "name": "Projects", "description": "Projects, members, board, stats and activity" }, { "name": "Issues", "description": "Tickets: search, create, workflow, relations, comments" }, { "name": "Comments", "description": "Edit and delete comments" }, { "name": "Releases", "description": "Versions that group tickets" }, { "name": "Users", "description": "The signed-in user and the Pireon directory" }, { "name": "Auth", "description": "Pireon OAuth token proxy" }, { "name": "Health", "description": "Liveness of the API and its databases" }, { "name": "Webhooks", "description": "Called by Pireon" } ], "servers": [ { "url": "/", "description": "This server (the paths already include /api)" } ], "components": { "securitySchemes": { "pireon-oauth": { "type": "oauth2", "flows": { "authorizationCode": { "authorizationUrl": "https://oauth.pireon.dev/oauth/authorize", "tokenUrl": "/api/auth/token", "refreshUrl": "/api/auth/token", "scopes": { "users:read": "Search Pireon users" } }, "password": { "tokenUrl": "/api/auth/token", "refreshUrl": "/api/auth/token", "scopes": { "users:read": "Search Pireon users" } } }, "description": "Pireon OAuth2 (Laravel Passport)" }, "pireon": { "scheme": "bearer", "bearerFormat": "JWT", "type": "http", "description": "A Pireon access token obtained elsewhere" } }, "schemas": { "AuthorizationConfigDto": { "type": "object", "properties": { "authorizeUrl": { "type": "string", "example": "https://oauth.pireon.dev/oauth/authorize" }, "clientId": { "type": "string", "nullable": true, "description": "Public id of the authorization_code client (\"Sign in with Pireon\"); null when only email + password is configured" }, "scopes": { "example": [ "users:read" ], "type": "array", "items": { "type": "string" } }, "passwordGrant": { "type": "boolean", "description": "Whether email + password sign-in is allowed" } }, "required": [ "authorizeUrl", "clientId", "scopes", "passwordGrant" ] }, "IssueTokenDto": { "type": "object", "properties": { "grant_type": { "type": "string", "enum": [ "authorization_code", "password", "refresh_token" ] }, "code": { "type": "string", "description": "authorization_code: code returned by Pireon" }, "code_verifier": { "type": "string", "description": "authorization_code: PKCE verifier" }, "redirect_uri": { "type": "string", "description": "authorization_code: redirect URI used to authorize" }, "username": { "type": "string", "description": "password: Pireon email" }, "password": { "type": "string", "description": "password: Pireon password" }, "refresh_token": { "type": "string", "description": "refresh_token" } }, "required": [ "grant_type" ] }, "TokenResponseDto": { "type": "object", "properties": { "access_token": { "type": "string" }, "refresh_token": { "type": "string", "nullable": true }, "expires_in": { "type": "number", "description": "Seconds" }, "token_type": { "type": "string", "example": "Bearer" } }, "required": [ "access_token", "refresh_token", "expires_in", "token_type" ] }, "MeDto": { "type": "object", "properties": { "id": { "type": "string", "description": "Pireon user id" }, "name": { "type": "string" }, "email": { "type": "string" }, "isActive": { "type": "boolean" }, "roles": { "description": "Global roles in Pireon", "type": "array", "items": { "type": "string" } }, "appRoles": { "description": "Roles inside the task-stream OAuth client", "type": "array", "items": { "type": "string" } } }, "required": [ "id", "name", "email", "isActive", "roles", "appRoles" ] }, "ApiErrorDto": { "type": "object", "properties": { "statusCode": { "type": "number", "example": 404 }, "code": { "type": "string", "description": "Domain error code", "enum": [ "NOT_FOUND", "FORBIDDEN", "VALIDATION", "CONFLICT", "BUSINESS_RULE" ] }, "message": { "description": "Human message (a list of messages for invalid input)", "oneOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" } } ], "example": "Issue not found" } }, "required": [ "statusCode", "message" ] }, "UserDto": { "type": "object", "properties": { "id": { "type": "string", "description": "Pireon user id" }, "name": { "type": "string" }, "email": { "type": "string" }, "isActive": { "type": "boolean" } }, "required": [ "id", "name", "email", "isActive" ] }, "CalendarFeedDto": { "type": "object", "properties": { "token": { "type": "string", "description": "Secret of the calendar URL: GET /api/calendar/{token}.ics (iCalendar, no session)" }, "createdAt": { "type": "string" } }, "required": [ "token", "createdAt" ] }, "UserRefDto": { "type": "object", "properties": { "id": { "type": "string", "description": "Pireon user id" }, "name": { "type": "string" } }, "required": [ "id", "name" ] }, "ProjectRole": { "type": "string", "enum": [ "OWNER", "ADMIN", "MEMBER", "VIEWER" ] }, "ProjectMemberDto": { "type": "object", "properties": { "user": { "$ref": "#/components/schemas/UserRefDto" }, "role": { "allOf": [ { "$ref": "#/components/schemas/ProjectRole" } ] } }, "required": [ "user", "role" ] }, "StatusCategory": { "type": "string", "enum": [ "TODO", "IN_PROGRESS", "QA", "DONE", "CANCELLED" ] }, "SettingColor": { "type": "string", "enum": [ "slate", "stone", "violet", "blue", "sky", "teal", "green", "amber", "orange", "red", "pink" ] }, "WorkflowStatusDto": { "type": "object", "properties": { "id": { "type": "string", "example": "IN_REVIEW", "description": "Stable id on tickets" }, "name": { "type": "string", "example": "En revisión" }, "category": { "allOf": [ { "$ref": "#/components/schemas/StatusCategory" } ] }, "color": { "allOf": [ { "$ref": "#/components/schemas/SettingColor" } ] }, "requiresReason": { "type": "boolean", "description": "Entering it needs a reason" }, "archived": { "type": "boolean", "description": "No new tickets or transitions into it" }, "wipLimit": { "type": "number", "nullable": true, "description": "Work-in-progress limit (a warning, not a lock)" } }, "required": [ "id", "name", "category", "color", "requiresReason", "archived", "wipLimit" ] }, "StatusTransitionsDto": { "type": "object", "properties": { "from": { "type": "string", "example": "IN_QA" }, "to": { "example": [ "DONE", "QA_FAILED" ], "type": "array", "items": { "type": "string" } } }, "required": [ "from", "to" ] }, "TypeIcon": { "type": "string", "enum": [ "bug", "feature", "palette", "task", "qa", "flag", "star-fill", "rocket", "document", "light-bulb", "key", "support" ] }, "IssueTemplateDto": { "type": "object", "properties": { "description": { "type": "string", "nullable": true }, "checklist": { "type": "array", "items": { "type": "string" } } }, "required": [ "description", "checklist" ] }, "IssueTypeOptionDto": { "type": "object", "properties": { "id": { "type": "string", "example": "BUG" }, "name": { "type": "string", "example": "Bug" }, "icon": { "allOf": [ { "$ref": "#/components/schemas/TypeIcon" } ] }, "color": { "allOf": [ { "$ref": "#/components/schemas/SettingColor" } ] }, "archived": { "type": "boolean" }, "template": { "description": "What a new ticket of the type starts with", "allOf": [ { "$ref": "#/components/schemas/IssueTemplateDto" } ] } }, "required": [ "id", "name", "icon", "color", "archived" ] }, "AreaOptionDto": { "type": "object", "properties": { "id": { "type": "string", "example": "FRONTEND" }, "name": { "type": "string", "example": "Frontend" }, "archived": { "type": "boolean" } }, "required": [ "id", "name", "archived" ] }, "CustomFieldType": { "type": "string", "enum": [ "TEXT", "NUMBER", "DATE", "SELECT" ], "description": "DATE values are YYYY-MM-DD" }, "CustomFieldDefinitionDto": { "type": "object", "properties": { "id": { "type": "string", "example": "BROWSER" }, "name": { "type": "string", "example": "Navegador" }, "type": { "description": "DATE values are YYYY-MM-DD", "allOf": [ { "$ref": "#/components/schemas/CustomFieldType" } ] }, "options": { "description": "The choices of a SELECT field", "type": "array", "items": { "type": "string" } }, "archived": { "type": "boolean" } }, "required": [ "id", "name", "type", "options", "archived" ] }, "ProjectSettingsDto": { "type": "object", "properties": { "statuses": { "description": "In board order", "type": "array", "items": { "$ref": "#/components/schemas/WorkflowStatusDto" } }, "transitions": { "type": "array", "items": { "$ref": "#/components/schemas/StatusTransitionsDto" } }, "issueTypes": { "type": "array", "items": { "$ref": "#/components/schemas/IssueTypeOptionDto" } }, "areas": { "type": "array", "items": { "$ref": "#/components/schemas/AreaOptionDto" } }, "customFields": { "type": "array", "items": { "$ref": "#/components/schemas/CustomFieldDefinitionDto" } }, "checklistBeforeDone": { "type": "boolean", "description": "Definition of done: tickets reach DONE only with their checklist ticked" } }, "required": [ "statuses", "transitions", "issueTypes", "areas", "customFields", "checklistBeforeDone" ] }, "ProjectDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "key": { "type": "string", "example": "WEB", "description": "Prefix of the ticket keys" }, "name": { "type": "string", "example": "Checkout revamp" }, "description": { "type": "string", "nullable": true }, "isPublic": { "type": "boolean", "description": "Readable by anyone, also without a token" }, "acceptsProposals": { "type": "boolean", "description": "Takes bug reports and ideas from anyone (POST /api/explore/projects/{project}/proposals) while public" }, "owner": { "$ref": "#/components/schemas/UserRefDto" }, "members": { "type": "array", "items": { "$ref": "#/components/schemas/ProjectMemberDto" } }, "settings": { "$ref": "#/components/schemas/ProjectSettingsDto" }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" }, "version": { "type": "number", "description": "Version of the aggregate (event count)" } }, "required": [ "id", "key", "name", "description", "isPublic", "acceptsProposals", "owner", "members", "settings", "createdAt", "updatedAt", "version" ] }, "CreateProjectDto": { "type": "object", "properties": { "key": { "type": "string", "example": "WEB", "description": "2-10 letters/digits starting with a letter → tickets WEB-1, WEB-2…" }, "name": { "type": "string", "example": "Checkout revamp", "maxLength": 120 }, "description": { "type": "string", "nullable": true, "maxLength": 5000 }, "isPublic": { "type": "boolean", "default": false, "description": "Anyone can read it without signing in (board, tickets, comments, releases, activity, statistics)" }, "template": { "type": "string", "nullable": true, "example": "API", "description": "A project you own or administer (id or key) to start from: its statuses, transitions, types, areas, custom fields and automation rules are copied" } }, "required": [ "key", "name" ] }, "CommandResultDto": { "type": "object", "properties": { "id": { "type": "string", "description": "Id of the aggregate written" }, "key": { "type": "string", "description": "Human key when one was assigned (project or issue)", "example": "WEB-13" }, "version": { "type": "number", "description": "Version after the write. Writes are acknowledged at once and the read model catches up asynchronously: a GET may briefly return the previous version (or 404 right after a create)." } }, "required": [ "id", "version" ] }, "UpdateProjectDto": { "type": "object", "properties": { "name": { "type": "string", "example": "Checkout revamp", "maxLength": 120 }, "description": { "type": "string", "nullable": true, "maxLength": 5000 }, "isPublic": { "type": "boolean", "default": false, "description": "Anyone can read it without signing in (board, tickets, comments, releases, activity, statistics)" }, "acceptsProposals": { "type": "boolean", "description": "Take bug reports and ideas from anyone through the public form (while public)" } } }, "WorkflowStatusBodyDto": { "type": "object", "properties": { "id": { "type": "string", "example": "IN_REVIEW", "description": "Never change an existing id" }, "name": { "type": "string", "example": "En revisión", "maxLength": 40 }, "category": { "allOf": [ { "$ref": "#/components/schemas/StatusCategory" } ] }, "color": { "allOf": [ { "$ref": "#/components/schemas/SettingColor" } ] }, "requiresReason": { "type": "boolean", "default": false }, "archived": { "type": "boolean", "default": false }, "wipLimit": { "type": "number", "nullable": true, "minimum": 1, "maximum": 999, "description": "Work-in-progress limit (null: none)" } }, "required": [ "id", "name", "category", "color" ] }, "StatusTransitionsBodyDto": { "type": "object", "properties": { "from": { "type": "string", "example": "IN_QA" }, "to": { "example": [ "DONE", "QA_FAILED" ], "type": "array", "items": { "type": "string" } } }, "required": [ "from", "to" ] }, "IssueTemplateBodyDto": { "type": "object", "properties": { "description": { "type": "string", "nullable": true, "maxLength": 5000 }, "checklist": { "maxItems": 20, "type": "array", "items": { "type": "string" } } } }, "IssueTypeOptionBodyDto": { "type": "object", "properties": { "id": { "type": "string", "example": "SPIKE" }, "name": { "type": "string", "example": "Spike", "maxLength": 40 }, "icon": { "allOf": [ { "$ref": "#/components/schemas/TypeIcon" } ] }, "color": { "allOf": [ { "$ref": "#/components/schemas/SettingColor" } ] }, "archived": { "type": "boolean", "default": false }, "template": { "nullable": true, "description": "What a new ticket of the type starts with", "type": "object", "allOf": [ { "$ref": "#/components/schemas/IssueTemplateBodyDto" } ] } }, "required": [ "id", "name", "icon", "color" ] }, "AreaOptionBodyDto": { "type": "object", "properties": { "id": { "type": "string", "example": "DATA" }, "name": { "type": "string", "example": "Datos", "maxLength": 40 }, "archived": { "type": "boolean", "default": false } }, "required": [ "id", "name" ] }, "CustomFieldDefinitionBodyDto": { "type": "object", "properties": { "id": { "type": "string", "example": "BROWSER" }, "name": { "type": "string", "example": "Navegador", "maxLength": 40 }, "type": { "description": "Cannot change once the field exists. DATE: YYYY-MM-DD", "allOf": [ { "$ref": "#/components/schemas/CustomFieldType" } ] }, "options": { "maxItems": 50, "example": [ "Chrome", "Safari", "Firefox" ], "description": "The choices of a SELECT field", "type": "array", "items": { "type": "string" } }, "archived": { "type": "boolean", "default": false } }, "required": [ "id", "name", "type" ] }, "ProjectSettingsBodyDto": { "type": "object", "properties": { "statuses": { "description": "In board order. Values cannot be removed: archive them instead.", "type": "array", "items": { "$ref": "#/components/schemas/WorkflowStatusBodyDto" } }, "transitions": { "type": "array", "items": { "$ref": "#/components/schemas/StatusTransitionsBodyDto" } }, "issueTypes": { "type": "array", "items": { "$ref": "#/components/schemas/IssueTypeOptionBodyDto" } }, "areas": { "type": "array", "items": { "$ref": "#/components/schemas/AreaOptionBodyDto" } }, "customFields": { "description": "Absent: unchanged. Fields cannot be removed: archive them.", "type": "array", "items": { "$ref": "#/components/schemas/CustomFieldDefinitionBodyDto" } }, "checklistBeforeDone": { "type": "boolean", "description": "Definition of done: tickets reach a DONE status only with their checklist ticked (owners and admins may override). Absent: unchanged" } }, "required": [ "statuses", "transitions", "issueTypes", "areas" ] }, "IssuePriority": { "type": "string", "enum": [ "LOWEST", "LOW", "MEDIUM", "HIGH", "CRITICAL" ] }, "ReleaseRefDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string", "example": "v1.4.0" } }, "required": [ "id", "name" ] }, "SprintRefDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string", "example": "Sprint 14" } }, "required": [ "id", "name" ] }, "IssueLinkType": { "type": "string", "enum": [ "BLOCKS", "DEPENDS_ON", "TESTS", "DUPLICATES", "RELATES_TO" ] }, "LinkDirection": { "type": "string", "enum": [ "OUTWARD", "INWARD" ], "description": "OUTWARD: this issue → other. INWARD: other → this issue." }, "IssueLinkDto": { "type": "object", "properties": { "type": { "allOf": [ { "$ref": "#/components/schemas/IssueLinkType" } ] }, "direction": { "description": "OUTWARD: this issue → other. INWARD: other → this issue.", "allOf": [ { "$ref": "#/components/schemas/LinkDirection" } ] }, "issueId": { "type": "string", "format": "uuid" }, "issueKey": { "type": "string", "example": "WEB-3" } }, "required": [ "type", "direction", "issueId", "issueKey" ] }, "AttachmentDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "fileName": { "type": "string", "example": "captura-login.png" }, "mimeType": { "type": "string", "example": "image/png" }, "size": { "type": "number", "description": "Bytes", "example": 48213 }, "uploadedBy": { "$ref": "#/components/schemas/UserRefDto" }, "uploadedAt": { "type": "string", "format": "date-time" }, "commentId": { "type": "string", "nullable": true, "format": "uuid", "description": "The comment it was attached to, if any" } }, "required": [ "id", "fileName", "mimeType", "size", "uploadedBy", "uploadedAt", "commentId" ] }, "IssueParentDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "key": { "type": "string", "example": "WEB-3" }, "title": { "type": "string", "example": "Pago con tarjeta" } }, "required": [ "id", "key", "title" ] }, "ChecklistItemDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "text": { "type": "string", "example": "Actualizar el changelog" }, "done": { "type": "boolean" } }, "required": [ "id", "text", "done" ] }, "DevLinkKind": { "type": "string", "enum": [ "COMMIT", "BRANCH", "PULL_REQUEST" ] }, "DevLinkState": { "type": "string", "enum": [ "OPEN", "MERGED", "CLOSED" ] }, "DevLinkDto": { "type": "object", "properties": { "kind": { "allOf": [ { "$ref": "#/components/schemas/DevLinkKind" } ] }, "url": { "type": "string" }, "title": { "type": "string" }, "ref": { "type": "string", "description": "Short SHA, branch or PR number" }, "state": { "nullable": true, "allOf": [ { "$ref": "#/components/schemas/DevLinkState" } ] }, "provider": { "type": "string", "example": "gitea" }, "repository": { "type": "string", "nullable": true, "example": "api", "description": "The project's name for the repository it came from" }, "author": { "type": "string", "nullable": true }, "at": { "type": "string", "format": "date-time" } }, "required": [ "kind", "url", "title", "ref", "state", "provider", "repository", "author", "at" ] }, "IssueDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "projectId": { "type": "string", "format": "uuid" }, "projectKey": { "type": "string", "example": "WEB" }, "number": { "type": "number", "example": 12 }, "key": { "type": "string", "example": "WEB-12", "description": "Human key" }, "type": { "type": "string", "example": "BUG", "description": "A ticket type id" }, "area": { "type": "string", "nullable": true, "example": "FRONTEND" }, "title": { "type": "string" }, "description": { "type": "string", "nullable": true }, "status": { "type": "string", "example": "IN_PROGRESS", "description": "A status id" }, "statusCategory": { "allOf": [ { "$ref": "#/components/schemas/StatusCategory" } ] }, "allowedTransitions": { "description": "Statuses this ticket can move to next (project's workflow)", "type": "array", "items": { "type": "string" } }, "priority": { "allOf": [ { "$ref": "#/components/schemas/IssuePriority" } ] }, "reporter": { "$ref": "#/components/schemas/UserRefDto" }, "assignee": { "nullable": true, "type": "object", "allOf": [ { "$ref": "#/components/schemas/UserRefDto" } ] }, "release": { "nullable": true, "type": "object", "allOf": [ { "$ref": "#/components/schemas/ReleaseRefDto" } ] }, "sprint": { "nullable": true, "type": "object", "allOf": [ { "$ref": "#/components/schemas/SprintRefDto" } ] }, "labels": { "type": "array", "items": { "type": "string" } }, "figmaUrl": { "type": "string", "nullable": true, "description": "Figma frame" }, "storyPoints": { "type": "number", "nullable": true }, "startDate": { "type": "string", "nullable": true, "format": "date", "description": "When work should start (roadmap)" }, "dueDate": { "type": "string", "nullable": true, "format": "date" }, "customFields": { "type": "object", "additionalProperties": { "type": "string" }, "example": { "BROWSER": "Safari" }, "description": "Custom field id → value (only those set)" }, "links": { "type": "array", "items": { "$ref": "#/components/schemas/IssueLinkDto" } }, "attachments": { "type": "array", "items": { "$ref": "#/components/schemas/AttachmentDto" } }, "watchers": { "description": "People following it", "type": "array", "items": { "$ref": "#/components/schemas/UserRefDto" } }, "parent": { "nullable": true, "description": "The epic or ticket this one breaks down", "type": "object", "allOf": [ { "$ref": "#/components/schemas/IssueParentDto" } ] }, "blockedBy": { "description": "Open tickets it waits for: the ones that block it and the ones it depends on", "type": "array", "items": { "$ref": "#/components/schemas/IssueParentDto" } }, "votes": { "type": "number", "description": "How many want it done" }, "voted": { "type": "boolean", "description": "Whether I voted for it (false without a token)" }, "rank": { "type": "string", "description": "Place in the backlog and its board column (ascending, as text)" }, "checklist": { "type": "array", "items": { "$ref": "#/components/schemas/ChecklistItemDto" } }, "trashedAt": { "type": "string", "nullable": true, "format": "date-time", "description": "In the trash since then; null when it is not" }, "devLinks": { "description": "Commits, branches and pull requests that mention it", "type": "array", "items": { "$ref": "#/components/schemas/DevLinkDto" } }, "commentCount": { "type": "number" }, "createdAt": { "type": "string", "format": "date-time" }, "updatedAt": { "type": "string", "format": "date-time" }, "version": { "type": "number" } }, "required": [ "id", "projectId", "projectKey", "number", "key", "type", "area", "title", "description", "status", "statusCategory", "allowedTransitions", "priority", "reporter", "assignee", "release", "sprint", "labels", "figmaUrl", "storyPoints", "startDate", "dueDate", "customFields", "links", "attachments", "watchers", "parent", "blockedBy", "votes", "voted", "rank", "checklist", "trashedAt", "devLinks", "commentCount", "createdAt", "updatedAt", "version" ] }, "BoardColumnDto": { "type": "object", "properties": { "status": { "type": "string", "example": "IN_PROGRESS" }, "issues": { "type": "array", "items": { "$ref": "#/components/schemas/IssueDto" } }, "total": { "type": "number", "description": "Tickets in the column (may exceed `issues`)" } }, "required": [ "status", "issues", "total" ] }, "CountByStatusDto": { "type": "object", "properties": { "key": { "type": "string", "example": "IN_PROGRESS", "description": "Status id" }, "count": { "type": "number" } }, "required": [ "key", "count" ] }, "CountByKeyDto": { "type": "object", "properties": { "key": { "type": "string", "description": "Type, priority or area (\"NONE\" = unset)" }, "count": { "type": "number" } }, "required": [ "key", "count" ] }, "CountByAssigneeDto": { "type": "object", "properties": { "user": { "nullable": true, "description": "Null = unassigned", "type": "object", "allOf": [ { "$ref": "#/components/schemas/UserRefDto" } ] }, "count": { "type": "number" } }, "required": [ "user", "count" ] }, "ProjectStatsDto": { "type": "object", "properties": { "total": { "type": "number" }, "open": { "type": "number", "description": "Not done nor cancelled" }, "byStatus": { "type": "array", "items": { "$ref": "#/components/schemas/CountByStatusDto" } }, "byType": { "type": "array", "items": { "$ref": "#/components/schemas/CountByKeyDto" } }, "byPriority": { "type": "array", "items": { "$ref": "#/components/schemas/CountByKeyDto" } }, "byArea": { "type": "array", "items": { "$ref": "#/components/schemas/CountByKeyDto" } }, "byAssignee": { "description": "Open tickets per person", "type": "array", "items": { "$ref": "#/components/schemas/CountByAssigneeDto" } } }, "required": [ "total", "open", "byStatus", "byType", "byPriority", "byArea", "byAssignee" ] }, "CreatedResolvedDto": { "type": "object", "properties": { "week": { "type": "string", "format": "date", "description": "Monday of the week" }, "created": { "type": "number" }, "resolved": { "type": "number" } }, "required": [ "week", "created", "resolved" ] }, "FlowSeriesDto": { "type": "object", "properties": { "status": { "type": "string", "example": "IN_PROGRESS" }, "counts": { "description": "One value per date", "type": "array", "items": { "type": "number" } } }, "required": [ "status", "counts" ] }, "CumulativeFlowDto": { "type": "object", "properties": { "dates": { "type": "array", "items": { "type": "string", "format": "date" } }, "series": { "type": "array", "items": { "$ref": "#/components/schemas/FlowSeriesDto" } } }, "required": [ "dates", "series" ] }, "DurationStatsDto": { "type": "object", "properties": { "count": { "type": "number" }, "averageDays": { "type": "number", "nullable": true }, "p85Days": { "type": "number", "nullable": true, "description": "85% of tickets take at most this long" } }, "required": [ "count", "averageDays", "p85Days" ] }, "ThroughputDto": { "type": "object", "properties": { "week": { "type": "string", "format": "date" }, "user": { "nullable": true, "type": "object", "allOf": [ { "$ref": "#/components/schemas/UserRefDto" } ] }, "count": { "type": "number" } }, "required": [ "week", "user", "count" ] }, "QaStatsDto": { "type": "object", "properties": { "passed": { "type": "number", "description": "Left QA to a done status" }, "failed": { "type": "number", "description": "Left QA back to work" }, "failureRate": { "type": "number", "nullable": true, "minimum": 0, "maximum": 1 } }, "required": [ "passed", "failed", "failureRate" ] }, "ProjectAnalyticsDto": { "type": "object", "properties": { "from": { "type": "string", "format": "date-time" }, "to": { "type": "string", "format": "date-time" }, "createdVsResolved": { "type": "array", "items": { "$ref": "#/components/schemas/CreatedResolvedDto" } }, "cumulativeFlow": { "description": "Tickets in each status at the end of every day", "allOf": [ { "$ref": "#/components/schemas/CumulativeFlowDto" } ] }, "cycleTime": { "description": "Start of work → done", "allOf": [ { "$ref": "#/components/schemas/DurationStatsDto" } ] }, "leadTime": { "description": "Creation → done", "allOf": [ { "$ref": "#/components/schemas/DurationStatsDto" } ] }, "throughput": { "type": "array", "items": { "$ref": "#/components/schemas/ThroughputDto" } }, "qa": { "$ref": "#/components/schemas/QaStatsDto" } }, "required": [ "from", "to", "createdVsResolved", "cumulativeFlow", "cycleTime", "leadTime", "throughput", "qa" ] }, "SprintPulseDto": { "type": "object", "properties": { "sprintId": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "startDate": { "type": "string", "format": "date" }, "endDate": { "type": "string", "format": "date" }, "totalDays": { "type": "number" }, "daysLeft": { "type": "number", "description": "Days left after today" }, "tickets": { "type": "number" }, "doneTickets": { "type": "number" }, "points": { "type": "number" }, "donePoints": { "type": "number" }, "pacePerDay": { "type": "number", "nullable": true }, "neededPerDay": { "type": "number", "nullable": true }, "behind": { "type": "boolean", "description": "At this pace, what is open would not be closed" } }, "required": [ "sprintId", "name", "startDate", "endDate", "totalDays", "daysLeft", "tickets", "doneTickets", "points", "donePoints", "pacePerDay", "neededPerDay", "behind" ] }, "InsightIssueDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "key": { "type": "string", "example": "WEB-12" }, "title": { "type": "string" }, "status": { "type": "string", "description": "Status id" }, "assignee": { "nullable": true, "type": "object", "allOf": [ { "$ref": "#/components/schemas/UserRefDto" } ] }, "days": { "type": "number", "description": "Days in its status (aging, stuck) or past / to its due date" }, "dueDate": { "type": "string", "nullable": true, "format": "date" } }, "required": [ "id", "key", "title", "status", "assignee", "days", "dueDate" ] }, "RisksDto": { "type": "object", "properties": { "overdue": { "type": "array", "items": { "$ref": "#/components/schemas/InsightIssueDto" } }, "overdueCount": { "type": "number" }, "dueSoon": { "description": "Due within 7 days", "type": "array", "items": { "$ref": "#/components/schemas/InsightIssueDto" } }, "dueSoonCount": { "type": "number" }, "blocked": { "type": "array", "items": { "$ref": "#/components/schemas/InsightIssueDto" } }, "blockedCount": { "type": "number" }, "stuck": { "type": "array", "items": { "$ref": "#/components/schemas/InsightIssueDto" } }, "stuckCount": { "type": "number" }, "stuckDays": { "type": "number" } }, "required": [ "overdue", "overdueCount", "dueSoon", "dueSoonCount", "blocked", "blockedCount", "stuck", "stuckCount", "stuckDays" ] }, "AgingDto": { "type": "object", "properties": { "issues": { "type": "array", "items": { "$ref": "#/components/schemas/InsightIssueDto" } }, "thresholdDays": { "type": "number", "nullable": true, "description": "p85 cycle time of the last 90 days" } }, "required": [ "issues", "thresholdDays" ] }, "StatusTimeDto": { "type": "object", "properties": { "status": { "type": "string" }, "averageDays": { "type": "number", "nullable": true }, "samples": { "type": "number" }, "open": { "type": "number" }, "wipLimit": { "type": "number", "nullable": true }, "overLimit": { "type": "boolean" } }, "required": [ "status", "averageDays", "samples", "open", "wipLimit", "overLimit" ] }, "ReleaseForecastDto": { "type": "object", "properties": { "releaseId": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "targetDate": { "type": "string", "nullable": true, "format": "date" }, "total": { "type": "number" }, "finished": { "type": "number" }, "likelyDate": { "type": "string", "nullable": true, "format": "date", "description": "Half of the simulated futures finish by then" }, "safeDate": { "type": "string", "nullable": true, "format": "date", "description": "85% finish by then" }, "verdict": { "type": "string", "enum": [ "DONE", "NO_DATE", "UNKNOWN", "ON_TRACK", "AT_RISK", "LATE" ] } }, "required": [ "releaseId", "name", "targetDate", "total", "finished", "likelyDate", "safeDate", "verdict" ] }, "ChangesSinceDto": { "type": "object", "properties": { "since": { "type": "string" }, "created": { "type": "array", "items": { "$ref": "#/components/schemas/InsightIssueDto" } }, "createdCount": { "type": "number" }, "finished": { "type": "array", "items": { "$ref": "#/components/schemas/InsightIssueDto" } }, "finishedCount": { "type": "number" }, "returned": { "description": "Sent back from QA", "type": "array", "items": { "$ref": "#/components/schemas/InsightIssueDto" } }, "returnedCount": { "type": "number" }, "mentions": { "type": "number", "description": "Times you were mentioned here" } }, "required": [ "since", "created", "createdCount", "finished", "finishedCount", "returned", "returnedCount", "mentions" ] }, "TeamLoadDto": { "type": "object", "properties": { "user": { "$ref": "#/components/schemas/UserRefDto" }, "openTickets": { "type": "number" }, "openPoints": { "type": "number" }, "blocked": { "type": "number" }, "pointsPerSprint": { "type": "number", "nullable": true, "description": "Points closed per sprint, last three closed sprints" }, "overloaded": { "type": "boolean" } }, "required": [ "user", "openTickets", "openPoints", "blocked", "pointsPerSprint", "overloaded" ] }, "BacklogHealthDto": { "type": "object", "properties": { "open": { "type": "number" }, "unestimated": { "type": "number" }, "noArea": { "type": "number" }, "unassigned": { "type": "number" }, "stale": { "type": "number" }, "staleDays": { "type": "number" } }, "required": [ "open", "unestimated", "noArea", "unassigned", "stale", "staleDays" ] }, "PriorityCountDto": { "type": "object", "properties": { "priority": { "allOf": [ { "$ref": "#/components/schemas/IssuePriority" } ] }, "count": { "type": "number" } }, "required": [ "priority", "count" ] }, "BugWeekDto": { "type": "object", "properties": { "week": { "type": "string", "format": "date", "description": "Monday (UTC)" }, "created": { "type": "number" }, "closed": { "type": "number" } }, "required": [ "week", "created", "closed" ] }, "QaByAreaDto": { "type": "object", "properties": { "area": { "type": "string", "nullable": true, "description": "Null: no area" }, "returned": { "type": "number" }, "passed": { "type": "number" } }, "required": [ "area", "returned", "passed" ] }, "EscapedBugsDto": { "type": "object", "properties": { "releaseId": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "releasedAt": { "type": "string" }, "bugs": { "type": "number", "description": "Bugs reported in the 14 days after" } }, "required": [ "releaseId", "name", "releasedAt", "bugs" ] }, "QualityDto": { "type": "object", "properties": { "openBugsByPriority": { "type": "array", "items": { "$ref": "#/components/schemas/PriorityCountDto" } }, "bugWeeks": { "description": "Last 8 weeks, oldest first", "type": "array", "items": { "$ref": "#/components/schemas/BugWeekDto" } }, "qaByArea": { "type": "array", "items": { "$ref": "#/components/schemas/QaByAreaDto" } }, "escaped": { "type": "array", "items": { "$ref": "#/components/schemas/EscapedBugsDto" } } }, "required": [ "openBugsByPriority", "bugWeeks", "qaByArea", "escaped" ] }, "OptionCountDto": { "type": "object", "properties": { "value": { "type": "string" }, "count": { "type": "number" } }, "required": [ "value", "count" ] }, "FieldBreakdownDto": { "type": "object", "properties": { "fieldId": { "type": "string" }, "counts": { "type": "array", "items": { "$ref": "#/components/schemas/OptionCountDto" } }, "none": { "type": "number", "description": "Open tickets with no value" } }, "required": [ "fieldId", "counts", "none" ] }, "ProjectInsightsDto": { "type": "object", "properties": { "generatedAt": { "type": "string" }, "sprint": { "nullable": true, "type": "object", "allOf": [ { "$ref": "#/components/schemas/SprintPulseDto" } ] }, "risks": { "$ref": "#/components/schemas/RisksDto" }, "aging": { "$ref": "#/components/schemas/AgingDto" }, "bottlenecks": { "type": "array", "items": { "$ref": "#/components/schemas/StatusTimeDto" } }, "releases": { "type": "array", "items": { "$ref": "#/components/schemas/ReleaseForecastDto" } }, "changes": { "nullable": true, "description": "Only when asked with `since`", "type": "object", "allOf": [ { "$ref": "#/components/schemas/ChangesSinceDto" } ] }, "team": { "type": "array", "items": { "$ref": "#/components/schemas/TeamLoadDto" } }, "backlog": { "$ref": "#/components/schemas/BacklogHealthDto" }, "quality": { "$ref": "#/components/schemas/QualityDto" }, "fields": { "description": "One per active list custom field", "type": "array", "items": { "$ref": "#/components/schemas/FieldBreakdownDto" } } }, "required": [ "generatedAt", "sprint", "risks", "aging", "bottlenecks", "releases", "changes", "team", "backlog", "quality", "fields" ] }, "ActivityDto": { "type": "object", "properties": { "id": { "type": "string" }, "type": { "type": "string", "example": "IssueStatusChanged" }, "projectId": { "type": "string", "format": "uuid" }, "issueId": { "type": "string", "nullable": true }, "issueKey": { "type": "string", "nullable": true, "example": "WEB-12" }, "actor": { "$ref": "#/components/schemas/UserRefDto" }, "summary": { "type": "string", "example": "Ana movió WEB-12 de En curso a En revisión" }, "occurredAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "type", "projectId", "issueId", "issueKey", "actor", "summary", "occurredAt" ] }, "AddMemberDto": { "type": "object", "properties": { "userId": { "type": "string", "description": "Pireon user id (see GET /users)" }, "role": { "default": "MEMBER", "allOf": [ { "$ref": "#/components/schemas/ProjectRole" } ] } }, "required": [ "userId" ] }, "ChangeMemberRoleDto": { "type": "object", "properties": { "role": { "allOf": [ { "$ref": "#/components/schemas/ProjectRole" } ] } }, "required": [ "role" ] }, "IssuePageDto": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/IssueDto" } }, "total": { "type": "number", "description": "Total matches (for pagination)" } }, "required": [ "items", "total" ] }, "IssueSort": { "type": "string", "enum": [ "RECENT", "RANK" ] }, "CreateIssueDto": { "type": "object", "properties": { "description": { "type": "string", "nullable": true, "maxLength": 50000 }, "area": { "type": "string", "nullable": true, "example": "FRONTEND", "description": "An area id of the project's settings" }, "priority": { "allOf": [ { "$ref": "#/components/schemas/IssuePriority" } ] }, "labels": { "maxItems": 20, "type": "array", "items": { "type": "string" } }, "figmaUrl": { "type": "string", "nullable": true, "description": "Figma frame (https) for UI changes" }, "storyPoints": { "type": "number", "nullable": true, "minimum": 0, "maximum": 100 }, "startDate": { "type": "string", "nullable": true, "format": "date", "description": "When work should start (roadmap)" }, "dueDate": { "type": "string", "nullable": true, "format": "date" }, "customFields": { "type": "object", "additionalProperties": { "type": "string", "nullable": true }, "example": { "BROWSER": "Safari" }, "description": "Custom field id → value. Only the fields to change; null or '' clears one" }, "type": { "type": "string", "example": "BUG", "description": "A ticket type id of the project's settings" }, "title": { "type": "string", "example": "El botón de pagar no responde en Safari", "maxLength": 255 }, "assigneeId": { "type": "string", "nullable": true, "description": "Pireon user id" }, "releaseId": { "type": "string", "nullable": true, "format": "uuid" }, "parent": { "type": "string", "nullable": true, "example": "WEB-3", "description": "Epic or ticket of the same project the new one breaks down (id or key)" } }, "required": [ "type", "title" ] }, "ChildProgressDto": { "type": "object", "properties": { "total": { "type": "number" }, "finished": { "type": "number", "description": "Done or cancelled" }, "percent": { "type": "number", "minimum": 0, "maximum": 100 }, "storyPoints": { "type": "number" }, "finishedStoryPoints": { "type": "number" } }, "required": [ "total", "finished", "percent", "storyPoints", "finishedStoryPoints" ] }, "EpicDto": { "type": "object", "properties": { "issue": { "$ref": "#/components/schemas/IssueDto" }, "progress": { "$ref": "#/components/schemas/ChildProgressDto" } }, "required": [ "issue", "progress" ] }, "UpdateIssueDto": { "type": "object", "properties": { "description": { "type": "string", "nullable": true, "maxLength": 50000 }, "area": { "type": "string", "nullable": true, "example": "FRONTEND", "description": "An area id of the project's settings" }, "priority": { "allOf": [ { "$ref": "#/components/schemas/IssuePriority" } ] }, "labels": { "maxItems": 20, "type": "array", "items": { "type": "string" } }, "figmaUrl": { "type": "string", "nullable": true, "description": "Figma frame (https) for UI changes" }, "storyPoints": { "type": "number", "nullable": true, "minimum": 0, "maximum": 100 }, "startDate": { "type": "string", "nullable": true, "format": "date", "description": "When work should start (roadmap)" }, "dueDate": { "type": "string", "nullable": true, "format": "date" }, "customFields": { "type": "object", "additionalProperties": { "type": "string", "nullable": true }, "example": { "BROWSER": "Safari" }, "description": "Custom field id → value. Only the fields to change; null or '' clears one" }, "type": { "type": "string", "example": "FEATURE", "description": "A ticket type id" }, "title": { "type": "string", "maxLength": 255 } } }, "ChangeStatusDto": { "type": "object", "properties": { "status": { "type": "string", "example": "IN_REVIEW", "description": "A status id of the project's settings, among the ticket's allowedTransitions" }, "reason": { "type": "string", "nullable": true, "description": "Required by statuses with requiresReason (e.g. QA_FAILED)" } }, "required": [ "status" ] }, "AssignIssueDto": { "type": "object", "properties": { "assigneeId": { "type": "string", "nullable": true, "description": "Pireon user id of a project member, or null to unassign" } }, "required": [ "assigneeId" ] }, "SetIssueReleaseDto": { "type": "object", "properties": { "releaseId": { "type": "string", "nullable": true, "format": "uuid", "description": "Planned release, or null to take the ticket out" } }, "required": [ "releaseId" ] }, "BulkUpdateIssuesDto": { "type": "object", "properties": { "issueIds": { "maxItems": 100, "type": "array", "items": { "type": "string", "format": "uuid" } }, "status": { "type": "string", "example": "IN_PROGRESS" }, "unassign": { "type": "boolean", "description": "Unassign everything" }, "assigneeId": { "type": "string", "description": "Pireon user id of a member" }, "noSprint": { "type": "boolean", "description": "Back to the backlog" }, "sprintId": { "type": "string", "format": "uuid" }, "noRelease": { "type": "boolean", "description": "Out of their release" }, "releaseId": { "type": "string", "format": "uuid" }, "priority": { "allOf": [ { "$ref": "#/components/schemas/IssuePriority" } ] }, "addLabels": { "type": "array", "items": { "type": "string" } } }, "required": [ "issueIds" ] }, "BulkIssueResultDto": { "type": "object", "properties": { "issueId": { "type": "string", "format": "uuid" }, "ok": { "type": "boolean" }, "error": { "type": "string", "nullable": true } }, "required": [ "issueId", "ok", "error" ] }, "BulkResultDto": { "type": "object", "properties": { "updated": { "type": "number" }, "results": { "type": "array", "items": { "$ref": "#/components/schemas/BulkIssueResultDto" } } }, "required": [ "updated", "results" ] }, "SetIssueParentDto": { "type": "object", "properties": { "parent": { "type": "string", "nullable": true, "example": "WEB-3", "description": "Epic or ticket of the same project (id or key), or null to take it back to the top" } }, "required": [ "parent" ] }, "RankIssueDto": { "type": "object", "properties": { "above": { "type": "string", "nullable": true, "example": "WEB-4", "description": "The ticket that ends up right above (id or key; null: the top)" }, "below": { "type": "string", "nullable": true, "example": "WEB-9", "description": "The ticket that ends up right below (id or key; null: the bottom)" } } }, "ChecklistItemBodyDto": { "type": "object", "properties": { "text": { "type": "string", "example": "Actualizar el changelog", "maxLength": 300 } }, "required": [ "text" ] }, "UpdateChecklistItemDto": { "type": "object", "properties": { "text": { "type": "string", "maxLength": 300 }, "done": { "type": "boolean" } } }, "LinkIssueDto": { "type": "object", "properties": { "type": { "allOf": [ { "$ref": "#/components/schemas/IssueLinkType" } ] }, "targetIssue": { "type": "string", "example": "API-3", "description": "Other ticket: id or key" } }, "required": [ "type", "targetIssue" ] }, "CommentReactionDto": { "type": "object", "properties": { "emoji": { "type": "string", "example": "👍" }, "users": { "type": "array", "items": { "$ref": "#/components/schemas/UserRefDto" } } }, "required": [ "emoji", "users" ] }, "CommentDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "issueId": { "type": "string", "format": "uuid" }, "author": { "$ref": "#/components/schemas/UserRefDto" }, "body": { "type": "string", "description": "Empty on a deleted comment kept for its replies" }, "replyTo": { "type": "string", "nullable": true, "format": "uuid", "description": "The top-level comment it answers; null for a top-level one" }, "deleted": { "type": "boolean", "description": "Deleted, but kept (without its text) while it has replies" }, "reactions": { "description": "In the order they are offered; only the ones somebody chose", "type": "array", "items": { "$ref": "#/components/schemas/CommentReactionDto" } }, "createdAt": { "type": "string", "format": "date-time" }, "editedAt": { "type": "string", "nullable": true, "format": "date-time" }, "version": { "type": "number" } }, "required": [ "id", "issueId", "author", "body", "replyTo", "deleted", "reactions", "createdAt", "editedAt", "version" ] }, "CommentPageDto": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/CommentDto" } }, "total": { "type": "number" } }, "required": [ "items", "total" ] }, "AddCommentDto": { "type": "object", "properties": { "body": { "type": "string", "example": "Reproducido en Safari 17.", "maxLength": 20000 }, "replyTo": { "type": "string", "format": "uuid", "description": "Comment it answers (one level: answering a reply joins its thread)" } }, "required": [ "body" ] }, "AttachFileDto": { "type": "object", "properties": { "file": { "type": "string", "format": "binary", "description": "The file" }, "commentId": { "type": "string", "format": "uuid", "description": "One of the ticket's comments, to show the file under it" } }, "required": [ "file" ] }, "AttachmentResultDto": { "type": "object", "properties": { "id": { "type": "string", "description": "Id of the aggregate written" }, "key": { "type": "string", "description": "Human key when one was assigned (project or issue)", "example": "WEB-13" }, "version": { "type": "number", "description": "Version after the write. Writes are acknowledged at once and the read model catches up asynchronously: a GET may briefly return the previous version (or 404 right after a create)." }, "attachmentId": { "type": "string", "format": "uuid", "description": "The new file; `![name](attachment:)` shows an image inside a description or comment" } }, "required": [ "id", "version", "attachmentId" ] }, "CommentBodyDto": { "type": "object", "properties": { "body": { "type": "string", "example": "Reproducido en Safari 17.", "maxLength": 20000 } }, "required": [ "body" ] }, "ReactToCommentDto": { "type": "object", "properties": { "emoji": { "type": "string", "enum": [ "👍", "👎", "😄", "🎉", "😕", "❤️", "🚀", "👀" ], "example": "👍" }, "on": { "type": "boolean", "description": "true adds the reaction, false takes it back" } }, "required": [ "emoji", "on" ] }, "ReleaseStatus": { "type": "string", "enum": [ "PLANNED", "RELEASED", "ARCHIVED" ] }, "ReleaseDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "projectId": { "type": "string", "format": "uuid" }, "name": { "type": "string", "example": "v1.4.0" }, "description": { "type": "string", "nullable": true }, "targetDate": { "type": "string", "nullable": true, "format": "date" }, "status": { "allOf": [ { "$ref": "#/components/schemas/ReleaseStatus" } ] }, "releasedAt": { "type": "string", "nullable": true, "format": "date-time" }, "notes": { "type": "string", "nullable": true, "description": "What shipped, told for people (Markdown)" }, "createdAt": { "type": "string", "format": "date-time" }, "version": { "type": "number" } }, "required": [ "id", "projectId", "name", "description", "targetDate", "status", "releasedAt", "notes", "createdAt", "version" ] }, "CreateReleaseDto": { "type": "object", "properties": { "name": { "type": "string", "example": "v1.4.0", "maxLength": 60 }, "description": { "type": "string", "nullable": true, "maxLength": 5000 }, "targetDate": { "type": "string", "nullable": true, "format": "date", "example": "2026-11-14" } }, "required": [ "name" ] }, "UpdateReleaseDto": { "type": "object", "properties": { "name": { "type": "string", "example": "v1.4.0", "maxLength": 60 }, "description": { "type": "string", "nullable": true, "maxLength": 5000 }, "targetDate": { "type": "string", "nullable": true, "format": "date", "example": "2026-11-14" } } }, "ReleaseProgressDto": { "type": "object", "properties": { "total": { "type": "number" }, "finished": { "type": "number" }, "percent": { "type": "number", "minimum": 0, "maximum": 100 }, "byStatus": { "type": "array", "items": { "$ref": "#/components/schemas/CountByStatusDto" } } }, "required": [ "total", "finished", "percent", "byStatus" ] }, "ReleaseBurnupDto": { "type": "object", "properties": { "releaseId": { "type": "string", "format": "uuid" }, "targetDate": { "type": "string", "nullable": true, "format": "date" }, "dates": { "type": "array", "items": { "type": "string", "format": "date" } }, "scope": { "description": "Tickets in the release (not cancelled)", "type": "array", "items": { "type": "number" } }, "done": { "type": "array", "items": { "type": "number" } } }, "required": [ "releaseId", "targetDate", "dates", "scope", "done" ] }, "PublishReleaseDto": { "type": "object", "properties": { "force": { "type": "boolean", "default": false, "description": "Publish even with unfinished tickets" } } }, "ReleaseNotesDto": { "type": "object", "properties": { "notes": { "type": "string", "nullable": true, "maxLength": 20000, "description": "Markdown; null removes the notes" } }, "required": [ "notes" ] }, "ReleaseNotesDraftDto": { "type": "object", "properties": { "markdown": { "type": "string", "example": "## v1.4.0\n\n### Novedades\n\n- Pago con tarjeta (WEB-1)\n" } }, "required": [ "markdown" ] }, "ArchiveReleaseDto": { "type": "object", "properties": { "moveTo": { "type": "string", "nullable": true, "format": "uuid", "description": "Open release of the same project that takes its unfinished tickets; null or absent: they leave it" } } }, "ShowcaseProjectDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "key": { "type": "string", "example": "WEB" }, "name": { "type": "string" }, "description": { "type": "string", "nullable": true } }, "required": [ "id", "key", "name", "description" ] }, "ShowcaseSprintDto": { "type": "object", "properties": { "name": { "type": "string" }, "goal": { "type": "string", "nullable": true }, "startDate": { "type": "string", "format": "date" }, "endDate": { "type": "string", "format": "date" }, "percent": { "type": "number" } }, "required": [ "name", "goal", "startDate", "endDate", "percent" ] }, "ShowcaseEpicDto": { "type": "object", "properties": { "key": { "type": "string" }, "title": { "type": "string" }, "startDate": { "type": "string", "nullable": true, "format": "date" }, "dueDate": { "type": "string", "nullable": true, "format": "date" }, "percent": { "type": "number" }, "done": { "type": "boolean" }, "votes": { "type": "number", "description": "How many want it" }, "path": { "type": "string", "example": "/p/WEB/issues/WEB-3", "description": "In the web app" } }, "required": [ "key", "title", "startDate", "dueDate", "percent", "done", "votes", "path" ] }, "ShowcaseReleaseDto": { "type": "object", "properties": { "name": { "type": "string" }, "status": { "allOf": [ { "$ref": "#/components/schemas/ReleaseStatus" } ] }, "targetDate": { "type": "string", "nullable": true }, "releasedAt": { "type": "string", "nullable": true }, "percent": { "type": "number" }, "notes": { "type": "string", "nullable": true, "description": "Shipped ones only" } }, "required": [ "name", "status", "targetDate", "releasedAt", "percent", "notes" ] }, "ShowcaseIssueDto": { "type": "object", "properties": { "key": { "type": "string" }, "title": { "type": "string" }, "type": { "type": "string", "description": "A ticket type id" }, "path": { "type": "string", "example": "/p/WEB/issues/WEB-9" } }, "required": [ "key", "title", "type", "path" ] }, "ShowcaseProposalDto": { "type": "object", "properties": { "key": { "type": "string" }, "title": { "type": "string" }, "type": { "type": "string", "description": "A ticket type id" }, "path": { "type": "string", "example": "/p/WEB/issues/WEB-9" }, "votes": { "type": "number", "description": "How many want it" } }, "required": [ "key", "title", "type", "path", "votes" ] }, "ShowcaseProposalsDto": { "type": "object", "properties": { "open": { "type": "boolean", "description": "Whether it takes bug reports and ideas now" }, "path": { "type": "string", "nullable": true, "example": "/p/WEB/proponer", "description": "The form in the web app, while it takes them" }, "top": { "description": "Open proposals, most voted first", "type": "array", "items": { "$ref": "#/components/schemas/ShowcaseProposalDto" } } }, "required": [ "open", "path", "top" ] }, "ShowcaseDto": { "type": "object", "properties": { "project": { "$ref": "#/components/schemas/ShowcaseProjectDto" }, "activeSprint": { "nullable": true, "type": "object", "allOf": [ { "$ref": "#/components/schemas/ShowcaseSprintDto" } ] }, "roadmap": { "type": "array", "items": { "$ref": "#/components/schemas/ShowcaseEpicDto" } }, "releases": { "type": "array", "items": { "$ref": "#/components/schemas/ShowcaseReleaseDto" } }, "goodFirst": { "description": "Open tickets labelled good-first-issue", "type": "array", "items": { "$ref": "#/components/schemas/ShowcaseIssueDto" } }, "proposals": { "$ref": "#/components/schemas/ShowcaseProposalsDto" } }, "required": [ "project", "activeSprint", "roadmap", "releases", "goodFirst", "proposals" ] }, "ProposalDto": { "type": "object", "properties": { "kind": { "type": "string", "enum": [ "BUG", "IDEA" ], "description": "A bug report or an idea" }, "title": { "type": "string", "minLength": 3, "maxLength": 150 }, "description": { "type": "string", "maxLength": 5000, "description": "What happens, or what they would like (Markdown)" }, "author": { "type": "string", "maxLength": 80, "description": "How they sign it; shown in the ticket (no e-mail: it would be public)" }, "website": { "type": "string", "description": "Leave empty: a field only bots fill in" } }, "required": [ "kind", "title" ] }, "ProposalResultDto": { "type": "object", "properties": { "key": { "type": "string", "nullable": true, "example": "WEB-42", "description": "The ticket it became" }, "path": { "type": "string", "nullable": true, "example": "/p/WEB/issues/WEB-42", "description": "Where to see it in the web app" } }, "required": [ "key", "path" ] }, "NotificationKind": { "type": "string", "enum": [ "ASSIGNED", "STATUS_CHANGED", "QA_FAILED", "COMMENTED", "MENTIONED", "REPLIED", "PROPOSED", "WATCHED", "ADDED_TO_PROJECT", "REMINDER" ] }, "NotificationDto": { "type": "object", "properties": { "id": { "type": "string" }, "kind": { "allOf": [ { "$ref": "#/components/schemas/NotificationKind" } ] }, "projectId": { "type": "string", "format": "uuid" }, "projectKey": { "type": "string", "example": "WEB" }, "issueId": { "type": "string", "nullable": true, "format": "uuid" }, "issueKey": { "type": "string", "nullable": true, "example": "WEB-12" }, "actor": { "$ref": "#/components/schemas/UserRefDto" }, "summary": { "type": "string", "example": "Ana te asignó WEB-12: Login roto en Safari" }, "readAt": { "type": "string", "nullable": true, "format": "date-time", "description": "Null: unread" }, "createdAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "kind", "projectId", "projectKey", "issueId", "issueKey", "actor", "summary", "readAt", "createdAt" ] }, "MyNotificationsDto": { "type": "object", "properties": { "items": { "type": "array", "items": { "$ref": "#/components/schemas/NotificationDto" } }, "unread": { "type": "number", "description": "All my unread ones, not just these" } }, "required": [ "items", "unread" ] }, "MarkNotificationsReadDto": { "type": "object", "properties": { "ids": { "description": "Omit to mark all of them", "type": "array", "items": { "type": "string" } } } }, "NotificationSettingsResponseDto": { "type": "object", "properties": { "email": { "type": "boolean", "description": "Copies by e-mail" }, "emailAvailable": { "type": "boolean", "description": "Whether this installation can send e-mail" }, "pushPublicKey": { "type": "string", "nullable": true, "description": "VAPID public key to subscribe a device to push with; null: no push here" } }, "required": [ "email", "emailAvailable", "pushPublicKey" ] }, "NotificationSettingsDto": { "type": "object", "properties": { "email": { "type": "boolean", "description": "Copies by e-mail" } }, "required": [ "email" ] }, "PushSubscriptionDto": { "type": "object", "properties": { "endpoint": { "type": "string", "description": "The push service URL (PushSubscription.endpoint)" }, "p256dh": { "type": "string", "description": "keys.p256dh of the subscription" }, "auth": { "type": "string", "description": "keys.auth of the subscription" } }, "required": [ "endpoint", "p256dh", "auth" ] }, "PushEndpointDto": { "type": "object", "properties": { "endpoint": { "type": "string", "description": "The endpoint of the device to turn off" } }, "required": [ "endpoint" ] }, "SavedFilterCriteriaResponseDto": { "type": "object", "properties": { "types": { "type": "array", "items": { "type": "string" } }, "areas": { "type": "array", "items": { "type": "string" } }, "priorities": { "type": "array", "items": { "$ref": "#/components/schemas/IssuePriority" } }, "assigneeId": { "type": "string", "nullable": true }, "unassigned": { "type": "boolean" }, "releaseId": { "type": "string", "nullable": true, "format": "uuid" }, "labels": { "type": "array", "items": { "type": "string" } }, "search": { "type": "string", "nullable": true } } }, "SavedFilterDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "projectId": { "type": "string", "format": "uuid" }, "owner": { "$ref": "#/components/schemas/UserRefDto" }, "name": { "type": "string", "example": "Bugs críticos de frontend" }, "shared": { "type": "boolean", "description": "Visible to the whole project" }, "criteria": { "$ref": "#/components/schemas/SavedFilterCriteriaResponseDto" }, "createdAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "projectId", "owner", "name", "shared", "criteria", "createdAt" ] }, "SavedFilterCriteriaDto": { "type": "object", "properties": { "types": { "description": "Ticket type ids", "type": "array", "items": { "type": "string" } }, "areas": { "description": "Area ids", "type": "array", "items": { "type": "string" } }, "priorities": { "type": "array", "items": { "$ref": "#/components/schemas/IssuePriority" } }, "assigneeId": { "type": "string", "nullable": true, "description": "Pireon user id" }, "unassigned": { "type": "boolean" }, "releaseId": { "type": "string", "nullable": true, "format": "uuid" }, "labels": { "type": "array", "items": { "type": "string" } }, "search": { "type": "string", "nullable": true, "maxLength": 200 } } }, "SaveFilterDto": { "type": "object", "properties": { "name": { "type": "string", "example": "Bugs críticos de frontend", "maxLength": 60 }, "shared": { "type": "object", "default": false, "description": "Visible to the whole project (members, not viewers, share)" }, "criteria": { "$ref": "#/components/schemas/SavedFilterCriteriaDto" } }, "required": [ "name", "criteria" ] }, "SavedFilterIdDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" } }, "required": [ "id" ] }, "MyViewCriteriaResponseDto": { "type": "object", "properties": { "projectIds": { "type": "array", "items": { "type": "string", "format": "uuid" } }, "assignedToMe": { "type": "boolean" }, "watching": { "type": "boolean" }, "categories": { "type": "array", "items": { "$ref": "#/components/schemas/StatusCategory" } }, "priorities": { "type": "array", "items": { "$ref": "#/components/schemas/IssuePriority" } }, "bugsOnly": { "type": "boolean" }, "overdue": { "type": "boolean" }, "search": { "type": "string" } } }, "MyViewDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string", "example": "Bugs críticos de todos mis proyectos" }, "criteria": { "$ref": "#/components/schemas/MyViewCriteriaResponseDto" }, "createdAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "name", "criteria", "createdAt" ] }, "MyViewCriteriaDto": { "type": "object", "properties": { "projectIds": { "description": "Only these of my projects (empty: all)", "type": "array", "items": { "type": "string", "format": "uuid" } }, "assignedToMe": { "type": "boolean" }, "watching": { "type": "boolean", "description": "Only the tickets I follow" }, "categories": { "type": "array", "items": { "$ref": "#/components/schemas/StatusCategory" } }, "priorities": { "type": "array", "items": { "$ref": "#/components/schemas/IssuePriority" } }, "bugsOnly": { "type": "boolean", "description": "Only types with the bug icon" }, "overdue": { "type": "boolean", "description": "Only open tickets past due" }, "search": { "type": "string", "maxLength": 200 } } }, "SaveMyViewDto": { "type": "object", "properties": { "name": { "type": "string", "example": "Bugs críticos de todos mis proyectos", "maxLength": 60 }, "criteria": { "$ref": "#/components/schemas/MyViewCriteriaDto" } }, "required": [ "name", "criteria" ] }, "SprintStatus": { "type": "string", "enum": [ "PLANNED", "ACTIVE", "CLOSED" ] }, "SprintDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "projectId": { "type": "string", "format": "uuid" }, "name": { "type": "string", "example": "Sprint 14" }, "goal": { "type": "string", "nullable": true }, "startDate": { "type": "string", "format": "date" }, "endDate": { "type": "string", "format": "date", "description": "Last day, included" }, "status": { "allOf": [ { "$ref": "#/components/schemas/SprintStatus" } ] }, "startedAt": { "type": "string", "nullable": true, "format": "date-time" }, "closedAt": { "type": "string", "nullable": true, "format": "date-time" }, "createdAt": { "type": "string", "format": "date-time" }, "version": { "type": "number" } }, "required": [ "id", "projectId", "name", "goal", "startDate", "endDate", "status", "startedAt", "closedAt", "createdAt", "version" ] }, "CreateSprintDto": { "type": "object", "properties": { "name": { "type": "string", "example": "Sprint 14", "maxLength": 80 }, "goal": { "type": "string", "nullable": true, "maxLength": 500, "example": "Pagos con tarjeta en producción" }, "startDate": { "type": "string", "format": "date", "example": "2026-10-12" }, "endDate": { "type": "string", "format": "date", "example": "2026-10-23", "description": "Last day, included" } }, "required": [ "name", "startDate", "endDate" ] }, "UpdateSprintDto": { "type": "object", "properties": { "name": { "type": "string", "example": "Sprint 14", "maxLength": 80 }, "goal": { "type": "string", "nullable": true, "maxLength": 500, "example": "Pagos con tarjeta en producción" }, "startDate": { "type": "string", "format": "date", "example": "2026-10-12" }, "endDate": { "type": "string", "format": "date", "example": "2026-10-23", "description": "Last day, included" } } }, "CloseSprintDto": { "type": "object", "properties": { "carryOverTo": { "type": "string", "nullable": true, "format": "uuid", "description": "Open sprint of the same project that takes the unfinished tickets; null or absent: back to the backlog" } } }, "SprintProgressDto": { "type": "object", "properties": { "total": { "type": "number" }, "finished": { "type": "number", "description": "Done or cancelled" }, "percent": { "type": "number", "minimum": 0, "maximum": 100 }, "storyPoints": { "type": "number" }, "finishedStoryPoints": { "type": "number" } }, "required": [ "total", "finished", "percent", "storyPoints", "finishedStoryPoints" ] }, "SprintBurndownDto": { "type": "object", "properties": { "sprintId": { "type": "string", "format": "uuid" }, "dates": { "type": "array", "items": { "type": "string", "format": "date" } }, "scope": { "nullable": true, "description": "Tickets in the sprint (null: days to come)", "type": "array", "items": { "type": "number" } }, "remaining": { "nullable": true, "type": "array", "items": { "type": "number" } }, "remainingPoints": { "nullable": true, "type": "array", "items": { "type": "number" } }, "ideal": { "type": "array", "items": { "type": "number" } } }, "required": [ "sprintId", "dates", "scope", "remaining", "remainingPoints", "ideal" ] }, "SetIssueSprintDto": { "type": "object", "properties": { "sprintId": { "type": "string", "nullable": true, "format": "uuid", "description": "Open sprint of the project, or null for the backlog" } }, "required": [ "sprintId" ] }, "GitRepositoryDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "name": { "type": "string", "example": "api" }, "secret": { "type": "string", "nullable": true, "description": "Webhook secret of this repository; only owners and admins see it" }, "createdAt": { "type": "string", "format": "date-time" } }, "required": [ "id", "name", "secret", "createdAt" ] }, "GitIntegrationDto": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "On while there is at least one repository" }, "webhookPath": { "type": "string", "example": "/api/webhooks/git/3f2c…", "description": "The same for every repository of the project" }, "repositories": { "type": "array", "items": { "$ref": "#/components/schemas/GitRepositoryDto" } } }, "required": [ "enabled", "webhookPath", "repositories" ] }, "AddGitRepositoryDto": { "type": "object", "properties": { "name": { "type": "string", "example": "api", "maxLength": 40, "description": "The project's name for it (api, web, admin…); unique" } }, "required": [ "name" ] }, "GitDeliveryResultDto": { "type": "object", "properties": { "recorded": { "type": "number", "description": "Tickets that got something new" } }, "required": [ "recorded" ] }, "WebhookDeliveryDto": { "type": "object", "properties": { "at": { "type": "string", "format": "date-time" }, "event": { "type": "string", "example": "issue.created" }, "status": { "type": "number", "nullable": true, "description": "HTTP status" }, "ok": { "type": "boolean" }, "error": { "type": "string", "nullable": true } }, "required": [ "at", "event", "status", "ok", "error" ] }, "WebhookDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "projectId": { "type": "string", "format": "uuid" }, "url": { "type": "string" }, "events": { "type": "array", "items": { "type": "string" } }, "active": { "type": "boolean" }, "createdBy": { "$ref": "#/components/schemas/UserRefDto" }, "createdAt": { "type": "string", "format": "date-time" }, "lastDelivery": { "nullable": true, "type": "object", "allOf": [ { "$ref": "#/components/schemas/WebhookDeliveryDto" } ] } }, "required": [ "id", "projectId", "url", "events", "active", "createdBy", "createdAt", "lastDelivery" ] }, "CreateWebhookDto": { "type": "object", "properties": { "url": { "type": "string", "example": "https://chat.example.org/hooks/taskstream" }, "events": { "example": [ "issue.status_changed", "release.*" ], "description": "Event names (GET /api/webhook-events), family.* or *", "type": "array", "items": { "type": "string" } } }, "required": [ "url", "events" ] }, "WebhookCreatedDto": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "secret": { "type": "string", "description": "Signs every delivery. Shown only now." } }, "required": [ "id", "secret" ] }, "UpdateWebhookDto": { "type": "object", "properties": { "url": { "type": "string", "example": "https://chat.example.org/hooks/taskstream" }, "events": { "example": [ "issue.status_changed", "release.*" ], "description": "Event names (GET /api/webhook-events), family.* or *", "type": "array", "items": { "type": "string" } }, "active": { "type": "boolean", "description": "Paused webhooks get nothing" } } }, "ImportLineDto": { "type": "object", "properties": { "line": { "type": "number", "description": "Line of the file (the header is 1)" }, "reason": { "type": "string" }, "message": { "type": "string" } }, "required": [ "line" ] }, "ImportReportDto": { "type": "object", "properties": { "format": { "type": "string", "enum": [ "taskstream", "jira" ] }, "dryRun": { "type": "boolean", "description": "Nothing was created: a preview" }, "rows": { "type": "number", "description": "Rows that become tickets" }, "created": { "type": "number" }, "keys": { "example": [ "WEB-41", "WEB-42" ], "type": "array", "items": { "type": "string" } }, "skipped": { "type": "array", "items": { "$ref": "#/components/schemas/ImportLineDto" } }, "warnings": { "type": "array", "items": { "$ref": "#/components/schemas/ImportLineDto" } } }, "required": [ "format", "dryRun", "rows", "created", "keys", "skipped", "warnings" ] } } } }