openapi: 3.0.3 info: title: 'Forge API Documentation' description: '' version: 1.0.0 servers: - url: 'https://forge.crimsonstrife.live' tags: - name: Endpoints description: '' paths: /api/user: get: summary: '' operationId: getApiUser description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] /api/webhooks/github: post: summary: '' operationId: postApiWebhooksGithub description: '' parameters: [] responses: { } tags: - Endpoints security: [] /api/v1/tickets: post: summary: '' operationId: postApiV1Tickets description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: multipart/form-data: schema: type: object properties: summary: type: string description: 'Must be at least 4 characters. Must not be greater than 200 characters.' example: b nullable: false description: type: string description: 'Must be at least 10 characters. Must not be greater than 8000 characters.' example: 'Et animi quos velit et fugiat.' nullable: false service_product_id: type: string description: 'The id of an existing record in the service_products table.' example: architecto nullable: false email: type: string description: 'Must be a valid email address. Must not be greater than 255 characters.' example: zbailey@example.net nullable: true player_id: type: string description: 'Must not be greater than 255 characters.' example: i nullable: true build: type: string description: 'Must not be greater than 64 characters.' example: 'y' nullable: true platform: type: string description: 'Must not be greater than 32 characters.' example: v nullable: true severity: type: string description: '' example: minor nullable: true enum: - trivial - minor - major - critical metadata: type: object description: '' example: null nullable: true properties: { } attachments: type: array description: 'Must be a file. Must not be greater than 10240 kilobytes.' items: type: string format: binary required: - summary - description - service_product_id security: [] '/api/v1/public/projects/{slug}/issues': get: summary: '' operationId: getApiV1PublicProjectsSlugIssues description: '' parameters: [] responses: 500: description: '' content: application/json: schema: type: object example: message: 'Server Error' properties: message: type: string example: 'Server Error' tags: - Endpoints security: [] parameters: - in: path name: slug description: 'The slug of the project.' example: architecto required: true schema: type: string /api/v1/me: get: summary: '' operationId: getApiV1Me description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] /api/v1/projects: get: summary: '' operationId: getApiV1Projects description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] '/api/v1/projects/{id}': get: summary: '' operationId: getApiV1ProjectsId description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] parameters: - in: path name: id description: 'The ID of the project.' example: 4407c75b-1b43-465d-8b5b-922057becd5f required: true schema: type: string /api/v1/lookups: get: summary: '' operationId: getApiV1Lookups description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] /api/v1/mentions/users: get: summary: 'Users autocompleter.' operationId: usersAutocompleter description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] /api/v1/mentions/issues: get: summary: 'Issues autocompleter.' operationId: issuesAutocompleter description: 'Accepts optional ?project_id=… to scope results.' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] /api/v1/issues: get: summary: '' operationId: getApiV1Issues description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] post: summary: '' operationId: postApiV1Issues description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: application/json: schema: type: object properties: project_id: type: string description: 'Must be a valid UUID. The id of an existing record in the projects table.' example: 6ff8f7f6-1eb3-3525-be4a-3932c805afed nullable: false summary: type: string description: 'Must not be greater than 255 characters.' example: g nullable: false description: type: string description: '' example: 'Eius et animi quos velit et.' nullable: true issue_type_id: type: integer description: 'The id of an existing record in the issue_types table.' example: 16 nullable: false issue_priority_id: type: integer description: 'The id of an existing record in the issue_priorities table.' example: 16 nullable: true issue_status_id: type: integer description: 'The id of an existing record in the issue_statuses table.' example: 16 nullable: true assignee_id: type: string description: 'Must be a valid UUID. The id of an existing record in the users table.' example: a4855dc5-0acb-33c3-b921-f4291f719ca0 nullable: true parent_id: type: string description: 'Must be a valid UUID. The id of an existing record in the issues table.' example: c90237e9-ced5-3af6-88ea-84aeaa148878 nullable: true tags: type: array description: '' example: - architecto items: type: string required: - project_id - summary - issue_type_id security: [] '/api/v1/issues/{id}': get: summary: '' operationId: getApiV1IssuesId description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] put: summary: '' operationId: putApiV1IssuesId description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: false content: application/json: schema: type: object properties: summary: type: string description: 'Must not be greater than 255 characters.' example: b nullable: false description: type: string description: '' example: 'Eius et animi quos velit et.' nullable: true issue_type_id: type: integer description: 'The id of an existing record in the issue_types table.' example: 16 nullable: false issue_priority_id: type: integer description: 'The id of an existing record in the issue_priorities table.' example: 16 nullable: false issue_status_id: type: integer description: 'The id of an existing record in the issue_statuses table.' example: 16 nullable: false assignee_id: type: string description: 'Must be a valid UUID. The id of an existing record in the users table.' example: a4855dc5-0acb-33c3-b921-f4291f719ca0 nullable: true parent_id: type: string description: 'Must be a valid UUID. The id of an existing record in the issues table.' example: c90237e9-ced5-3af6-88ea-84aeaa148878 nullable: true tags: type: array description: '' example: - architecto items: type: string security: [] parameters: - in: path name: id description: 'The ID of the issue.' example: OMP-1 required: true schema: type: string '/api/v1/issues/{issue_id}/transition': post: summary: '' operationId: postApiV1IssuesIssue_idTransition description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: application/json: schema: type: object properties: to_status_id: type: integer description: 'The id of an existing record in the issue_statuses table.' example: 16 nullable: false required: - to_status_id security: [] parameters: - in: path name: issue_id description: 'The ID of the issue.' example: OMP-1 required: true schema: type: string '/api/v1/issues/{issue_id}/comments': post: summary: '' operationId: postApiV1IssuesIssue_idComments description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: application/json: schema: type: object properties: body: type: string description: 'Must not be greater than 65000 characters.' example: b nullable: false required: - body security: [] parameters: - in: path name: issue_id description: 'The ID of the issue.' example: OMP-1 required: true schema: type: string '/api/v1/issues/{issue_id}/attachments': post: summary: '' operationId: postApiV1IssuesIssue_idAttachments description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: multipart/form-data: schema: type: object properties: file: type: string format: binary description: 'Must be a file. Must not be greater than 10240 kilobytes.' nullable: false required: - file security: [] parameters: - in: path name: issue_id description: 'The ID of the issue.' example: OMP-1 required: true schema: type: string '/api/v1/issues/{issue_id}/time/summary': get: summary: 'GET /api/v1/issues/{issue:id}/time/summary' operationId: gETapiv1issuesissueidtimesummary description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] parameters: - in: path name: issue_id description: 'The ID of the issue.' example: OMP-1 required: true schema: type: string '/api/v1/issues/{issue_id}/time/start': post: summary: "POST /api/v1/issues/{issue:id}/time/start\nStarts a running timer for the authenticated user." operationId: pOSTapiv1issuesissueidtimestartStartsARunningTimerForTheAuthenticatedUser description: '' parameters: [] responses: { } tags: - Endpoints security: [] parameters: - in: path name: issue_id description: 'The ID of the issue.' example: OMP-1 required: true schema: type: string '/api/v1/issues/{issue_id}/time/stop': post: summary: "POST /api/v1/issues/{issue:id}/time/stop\nStops the current running timer for the authenticated user." operationId: pOSTapiv1issuesissueidtimestopStopsTheCurrentRunningTimerForTheAuthenticatedUser description: '' parameters: [] responses: { } tags: - Endpoints security: [] parameters: - in: path name: issue_id description: 'The ID of the issue.' example: OMP-1 required: true schema: type: string '/api/v1/issues/{issue_id}/time': post: summary: "POST /api/v1/issues/{issue:id}/time\nManual log: accepts either {seconds} or {started_at, ended_at}, plus optional note." operationId: pOSTapiv1issuesissueidtimeManualLogAcceptsEithersecondsOrstartedAtEndedAtPlusOptionalNote description: '' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: application/json: schema: type: object properties: started_at: type: string description: 'Must be a valid date.' example: '2025-10-01T19:30:24' nullable: false ended_at: type: string description: 'Must be a valid date. Must be a date after started_at.' example: '2051-10-25' nullable: false note: type: string description: 'Must not be greater than 2000 characters.' example: 'n' nullable: true required: - started_at - ended_at security: [] parameters: - in: path name: issue_id description: 'The ID of the issue.' example: OMP-1 required: true schema: type: string