diff --git a/docs/api/apiv3/components/examples/version_create_request.yml b/docs/api/apiv3/components/examples/version_create_request.yml new file mode 100644 index 00000000000..c2633a64af2 --- /dev/null +++ b/docs/api/apiv3/components/examples/version_create_request.yml @@ -0,0 +1,17 @@ +# Example: Version create request +--- +description: Request to create a basic version with custom fields +value: + name: v0.9.1-alpha + startDate: "2026-02-02" + endDate: "2026-02-09" + status: open + sharing: tree + customField14: true + _links: + definingProject: + href: "/api/v3/projects/10" + title: "Death Star" + customField23: + href: "/api/v3/users/18" + title: "Mara Jade" diff --git a/docs/api/apiv3/components/examples/version_simple_response.yml b/docs/api/apiv3/components/examples/version_simple_response.yml new file mode 100644 index 00000000000..bcc5458a8f3 --- /dev/null +++ b/docs/api/apiv3/components/examples/version_simple_response.yml @@ -0,0 +1,41 @@ +# Example: Version simple response +--- +description: Simple response showing a single version +value: + _type: Version + id: 3 + name: v0.9.1-alpha + description: + format: plain + raw: "First draft of the energy weapon ... (behold, Alderaan *evil_laughter*)" + html: "

First draft of the energy weapon ... (behold, Alderaan *evil_laughter*)

" + startDate: "2026-02-02" + endDate: "2026-02-09" + status: closed + sharing: none + createdAt: "2026-02-06T09:30:49.157Z" + updatedAt: "2026-02-10T09:53:21.620Z" + customField14: true + _links: + self: + href: "/api/v3/versions/1" + title: "v0.1.0-alpha" + schema: + href: "/api/v3/versions/schema" + update: + href: "/api/v3/versions/1/form" + method: "post" + updateImmediately: + href: "/api/v3/versions/1" + method: "patch" + delete: + href: "/api/v3/versions/1" + method: "delete" + availableInProjects: + href: "/api/v3/versions/1/workspaces" + definingProject: + href: "/api/v3/projects/10" + title: "Death Star" + customField23: + href: "/api/v3/users/18" + title: "Mara Jade" diff --git a/docs/api/apiv3/components/examples/version_update_name_request.yml b/docs/api/apiv3/components/examples/version_update_name_request.yml new file mode 100644 index 00000000000..acce296bc0f --- /dev/null +++ b/docs/api/apiv3/components/examples/version_update_name_request.yml @@ -0,0 +1,5 @@ +# Example: Version update name response +--- +description: Example request body to update the name of a version. +value: + name: v0.9.1-alpha diff --git a/docs/api/apiv3/components/schemas/custom_field_linked_properties.yml b/docs/api/apiv3/components/schemas/custom_field_linked_properties.yml new file mode 100644 index 00000000000..bb109392211 --- /dev/null +++ b/docs/api/apiv3/components/schemas/custom_field_linked_properties.yml @@ -0,0 +1,15 @@ +# Schema: CustomFieldLinkedProperties +--- +type: object +patternProperties: + "^customField\\d+": + allOf: + - $ref: "./link.yml" + - description: |- + A custom field value that belongs to a custom field of a reference type: + + - Hierarchy + - List + - User + - Version + - Weighted item list diff --git a/docs/api/apiv3/components/schemas/custom_field_properties.yml b/docs/api/apiv3/components/schemas/custom_field_properties.yml new file mode 100644 index 00000000000..b3aab87897d --- /dev/null +++ b/docs/api/apiv3/components/schemas/custom_field_properties.yml @@ -0,0 +1,20 @@ +# Schema: CustomFieldProperties +--- +type: object +patternProperties: + "^customField\\d+": + type: + - "null" + - number + - boolean + - string + description: |- + A custom field value, that belongs to a custom field of a simple type: + + - Boolean + - Date + - Float + - Integer + - Link (URL) + - Text + - Long text diff --git a/docs/api/apiv3/components/schemas/version_collection_model.yml b/docs/api/apiv3/components/schemas/version_collection_model.yml new file mode 100644 index 00000000000..a80d0dd6944 --- /dev/null +++ b/docs/api/apiv3/components/schemas/version_collection_model.yml @@ -0,0 +1,30 @@ +# Schema: UserCollectionModel +--- +allOf: + - $ref: './collection_model.yml' + - type: object + required: + - _links + - _embedded + properties: + _links: + type: object + required: + - self + properties: + self: + allOf: + - $ref: './link.yml' + - description: |- + This version collection + + **Resource**: Collection + _embedded: + type: object + required: + - elements + properties: + elements: + type: array + items: + $ref: './version_read_model.yml' diff --git a/docs/api/apiv3/components/schemas/version_model.yml b/docs/api/apiv3/components/schemas/version_read_model.yml similarity index 55% rename from docs/api/apiv3/components/schemas/version_model.yml rename to docs/api/apiv3/components/schemas/version_read_model.yml index 1e8d9304291..f9608a13ef2 100644 --- a/docs/api/apiv3/components/schemas/version_model.yml +++ b/docs/api/apiv3/components/schemas/version_read_model.yml @@ -1,11 +1,28 @@ -# Schema: VersionModel +# Schema: VersionReadModel --- type: object +required: + - id + - _type + - name + - description + - startDate + - endDate + - status + - sharing + - createdAt + - updatedAt +allOf: + - $ref: "./custom_field_properties.yml" properties: id: type: integer description: Version id minimum: 1 + _type: + type: string + enum: + - Version name: type: string description: Version name @@ -24,9 +41,25 @@ properties: status: type: string description: The current status of the version + enum: + - open + - locked + - closed sharing: type: string - description: The current status of the version + description: |- + The indicator of how the version is shared between projects. This could be: + - *none*: if the version is only available in the defining project + - *descendants*: if the version is shared with the descendants of the defining project + - *hierarchy*: if the version is shared with the descendants and the ancestors of the defining project + - *tree*: if the version is shared with the root project of the defining project and all descendants of the root project + - *system*: if the version is shared globally + enum: + - none + - descendants + - hierarchy + - tree + - system createdAt: type: string format: date-time @@ -39,8 +72,26 @@ properties: type: object required: - self + - schema + - definingProject - availableInProjects + allOf: + - $ref: "./custom_field_linked_properties.yml" properties: + self: + allOf: + - $ref: "./link.yml" + - description: |- + This version + + **Resource**: Version + schema: + allOf: + - $ref: "./link.yml" + - description: |- + The schema of this version + + **Resource**: VersionSchema update: allOf: - $ref: "./link.yml" @@ -49,6 +100,15 @@ properties: # Conditions + **Permission**: manage versions + delete: + allOf: + - $ref: "./link.yml" + - description: |- + Deletes this version + + # Conditions + **Permission**: manage versions updateImmediately: allOf: @@ -59,13 +119,6 @@ properties: # Conditions **Permission**: manage versions - self: - allOf: - - $ref: "./link.yml" - - description: |- - This version - - **Resource**: Version definingProject: allOf: - $ref: "./link.yml" @@ -80,34 +133,3 @@ properties: Workspaces where this version can be used **Resource**: Workspace -example: - _links: - self: - href: "/api/v3/versions/11" - update: - href: "/api/v3/versions/11/form" - method: POST - updateImmediately: - href: "/api/v3/versions/11" - method: PATCH - definingProject: - href: "/api/v3/projects/11" - availableInProjects: - href: "/api/v3/versions/11/workspaces" - customField4: - href: "/api/v3/custom_options/5" - title: Custom field option - _type: Version - id: 11 - name: v3.0 Alpha - description: - format: plain - raw: This version has a description - html: This version has a description - startDate: '2014-11-20' - endDate: - status: open - sharing: system - customField14: '1234567890' - createdAt: "2025-12-10T13:37:00Z" - updatedAt: "2025-12-10T13:37:00Z" diff --git a/docs/api/apiv3/components/schemas/version_write_model.yml b/docs/api/apiv3/components/schemas/version_write_model.yml new file mode 100644 index 00000000000..859de21214b --- /dev/null +++ b/docs/api/apiv3/components/schemas/version_write_model.yml @@ -0,0 +1,39 @@ +# Schema: VersionWriteModel +--- +type: object +allOf: + - $ref: "./custom_field_properties.yml" +properties: + name: + type: string + description: Version name + description: + $ref: "./formattable.yml" + startDate: + type: + - "string" + - "null" + format: date + endDate: + type: + - "string" + - "null" + format: date + status: + type: string + description: The current status of the version + sharing: + type: string + description: The current status of the version + _links: + type: object + allOf: + - $ref: "./custom_field_linked_properties.yml" + properties: + definingProject: + allOf: + - $ref: "./link.yml" + - description: |- + The workspace to which the version belongs + + **Resource**: Workspace diff --git a/docs/api/apiv3/components/schemas/versions_by_workspace_model.yml b/docs/api/apiv3/components/schemas/versions_by_workspace_model.yml index ea12538ad9e..fcf02a53371 100644 --- a/docs/api/apiv3/components/schemas/versions_by_workspace_model.yml +++ b/docs/api/apiv3/components/schemas/versions_by_workspace_model.yml @@ -1,7 +1,7 @@ # Schema: Versions_by_WorkspaceModel --- allOf: - - "$ref": "./collection_model.yml" + - $ref: "./collection_model.yml" - type: object required: - _links @@ -14,7 +14,7 @@ allOf: properties: self: allOf: - - "$ref": "./link.yml" + - $ref: "./link.yml" - description: |- The versions collection @@ -28,5 +28,5 @@ allOf: readOnly: true items: allOf: - - "$ref": "./version_model.yml" + - $ref: "./version_read_model.yml" - description: Collection of Versions diff --git a/docs/api/apiv3/components/schemas/versions_model.yml b/docs/api/apiv3/components/schemas/versions_model.yml deleted file mode 100644 index 63ae395caf8..00000000000 --- a/docs/api/apiv3/components/schemas/versions_model.yml +++ /dev/null @@ -1,63 +0,0 @@ -# Schema: VersionsModel ---- -type: object -example: - _links: - self: - href: "/api/v3/versions" - total: 3 - count: 3 - _type: Collection - _embedded: - elements: - - _links: - self: - href: "/api/v3/versions/11" - definingProject: - href: "/api/v3/projects/12" - availableInProjects: - href: "/api/v3/versions/11/workspaces" - _type: Version - id: 11 - name: v3.0 Alpha - description: - format: plain - raw: This version has a description - html: This version has a description - startDate: '2014-11-20' - endDate: - status: Open - - _links: - self: - href: "/api/v3/versions/12" - definingProject: - href: "/api/v3/projects/11" - availableInProjects: - href: "/api/v3/versions/12/workspaces" - _type: Version - id: 12 - name: v2.0 - description: - format: plain - raw: '' - html: '' - startDate: - endDate: - status: Closed - - _links: - self: - href: "/api/v3/versions/10" - definingProject: - href: "/api/v3/projects/13" - availableInProjects: - href: "/api/v3/versions/13/workspaces" - _type: Version - id: 10 - name: v1.0 - description: - format: plain - raw: '' - html: '' - startDate: - endDate: - status: Open diff --git a/docs/api/apiv3/openapi-spec.yml b/docs/api/apiv3/openapi-spec.yml index 4c92879d312..77cf963c0b2 100644 --- a/docs/api/apiv3/openapi-spec.yml +++ b/docs/api/apiv3/openapi-spec.yml @@ -1,5 +1,5 @@ --- -openapi: 3.1.0 +openapi: 3.1.2 info: description: |- @@ -657,6 +657,12 @@ components: $ref: "./components/examples/values_property_due_date.yml" ValuesPropertyDate: $ref: "./components/examples/values_property_date.yml" + VersionSimpleResponse: + $ref: "./components/examples/version_simple_response.yml" + VersionCreateRequest: + $ref: "./components/examples/version_create_request.yml" + VersionUpdateNameRequest: + $ref: "./components/examples/version_update_name_request.yml" Views: $ref: "./components/examples/views.yml" ViewWorkPackagesTable: @@ -723,6 +729,10 @@ components: "$ref": "./components/schemas/project_configuration_model.yml" CustomActionModel: "$ref": "./components/schemas/custom_action_model.yml" + CustomFieldLinkedProperties: + "$ref": "./components/schemas/custom_field_linked_properties.yml" + CustomFieldProperties: + "$ref": "./components/schemas/custom_field_properties.yml" CustomOptionModel: "$ref": "./components/schemas/custom_option_model.yml" DayCollectionModel: @@ -969,12 +979,14 @@ components: "$ref": "./components/schemas/user_preferences_model.yml" ValuesPropertyModel: "$ref": "./components/schemas/values_property_model.yml" - VersionModel: - "$ref": "./components/schemas/version_model.yml" + VersionCollectionModel: + "$ref": "./components/schemas/version_collection_model.yml" + VersionReadModel: + "$ref": "./components/schemas/version_read_model.yml" + VersionWriteModel: + "$ref": "./components/schemas/version_write_model.yml" Version_schemaModel: "$ref": "./components/schemas/version_schema_model.yml" - VersionsModel: - "$ref": "./components/schemas/versions_model.yml" Versions_by_WorkspaceModel: "$ref": "./components/schemas/versions_by_workspace_model.yml" View_actionModel: diff --git a/docs/api/apiv3/paths/version.yml b/docs/api/apiv3/paths/version.yml index d4df4a2aaf1..f9752317ad3 100644 --- a/docs/api/apiv3/paths/version.yml +++ b/docs/api/apiv3/paths/version.yml @@ -1,18 +1,66 @@ # /api/v3/versions/{id} --- -delete: +get: + summary: Get version + operationId: get_version + tags: + - Versions + description: Retrieves a version defined by its unique identifier. parameters: - - description: Version id - example: '1' - in: path - name: id - required: true - schema: - type: integer + - description: Version id + example: '1' + in: path + name: id + required: true + schema: + type: integer + responses: + '200': + description: OK + content: + application/hal+json: + schema: + "$ref": "../components/schemas/version_read_model.yml" + examples: + response: + $ref: "../components/examples/version_simple_response.yml" + '404': + content: + application/hal+json: + schema: + $ref: "../components/schemas/error_response.yml" + examples: + response: + value: + _type: Error + errorIdentifier: urn:openproject-org:api:v3:errors:NotFound + message: The requested resource could not be found. + description: |- + Returned if the version does not exist or the client does not have sufficient permissions + to see it. + + **Required permission:** view work packages **or** manage versions (any project where the version is available) + + *Note: A client without sufficient permissions shall not be able to test for the existence of + a version. That's why a 404 is returned here, even if a 403 might be more appropriate.* + +delete: + summary: Delete version + operationId: delete_Version + tags: + - Versions + description: Deletes the version. Entities associated to the version will no longer be assigned to it. + parameters: + - description: Version id + example: '1' + in: path + name: id + required: true + schema: + type: integer responses: '204': description: Returned if the version was successfully deleted - headers: {} '403': content: application/hal+json: @@ -28,7 +76,6 @@ delete: Returned if the client does not have sufficient permissions. **Required permission:** manage versions - headers: {} '404': content: application/hal+json: @@ -48,107 +95,45 @@ delete: *Note: A client without sufficient permissions shall not be able to test for the existence of a version. That's why a 404 is returned here, even if a 403 might be more appropriate.* - headers: {} '406': $ref: "../components/responses/missing_content_type.yml" '415': $ref: "../components/responses/unsupported_media_type.yml" - tags: - - Versions - description: Deletes the version. Work packages associated to the version will no - longer be assigned to it. - operationId: Delete_Version - summary: Delete version -get: - parameters: - - description: Version id - example: '1' - in: path - name: id - required: true - schema: - type: integer - responses: - '200': - content: - application/hal+json: - examples: - response: - value: - _links: - availableInProjects: - href: "/api/v3/versions/11/workspaces" - customField4: - href: "/api/v3/custom_options/5" - title: Custom field option - definingProject: - href: "/api/v3/projects/11" - self: - href: "/api/v3/versions/11" - update: - href: "/api/v3/versions/11/form" - method: POST - updateImmediately: - href: "/api/v3/versions/11" - method: PATCH - _type: Version - customField14: '1234567890' - description: - format: plain - html: This version has a description - raw: This version has a description - endDate: - id: 11 - name: v3.0 Alpha - sharing: system - startDate: '2014-11-20' - status: open - schema: - "$ref": "../components/schemas/version_model.yml" - description: OK - headers: {} - '404': - content: - application/hal+json: - schema: - $ref: "../components/schemas/error_response.yml" - examples: - response: - value: - _type: Error - errorIdentifier: urn:openproject-org:api:v3:errors:NotFound - message: The requested resource could not be found. - description: |- - Returned if the version does not exist or the client does not have sufficient permissions - to see it. - - **Required permission:** view work packages **or** manage versions (any project where the version is available) - - *Note: A client without sufficient permissions shall not be able to test for the existence of - a version. That's why a 404 is returned here, even if a 403 might be more appropriate.* - headers: {} - tags: - - Versions - description: '' - operationId: View_version - summary: View version + patch: + summary: Update Version + operationId: update_Version + tags: + - Versions + description: |- + Updates the given version by applying the attributes provided in the body. Please note that while there is a fixed + set of attributes, custom fields can extend a version's attributes and are accepted by the endpoint. parameters: - - description: Version id - example: '1' - in: path - name: id - required: true - schema: - type: integer + - description: Version id + example: '1' + in: path + name: id + required: true + schema: + type: integer + requestBody: + content: + application/json: + schema: + $ref: "../components/schemas/version_write_model.yml" + examples: + 'update name': + $ref: "../components/examples/version_update_name_request.yml" responses: '200': + description: OK content: application/hal+json: schema: - "$ref": "../components/schemas/version_model.yml" - description: OK - headers: {} + "$ref": "../components/schemas/version_read_model.yml" + examples: + response: + $ref: "../components/examples/version_simple_response.yml" '400': $ref: "../components/responses/invalid_request_body.yml" '403': @@ -166,7 +151,6 @@ patch: Returned if the client does not have sufficient permissions. **Required permission:** Manage versions in the version's project. - headers: {} '404': content: application/hal+json: @@ -186,7 +170,6 @@ patch: *Note: A client without sufficient permissions shall not be able to test for the existence of a version. That's why a 404 is returned here, even if a 403 might be more appropriate.* - headers: {} '406': $ref: "../components/responses/missing_content_type.yml" '415': @@ -196,11 +179,3 @@ patch: Returned if: * a constraint for a property was violated (`PropertyConstraintViolation`) - headers: {} - tags: - - Versions - description: Updates the given version by applying the attributes provided in the - body. Please note that while there is a fixed set of attributes, custom fields - can extend a version's attributes and are accepted by the endpoint. - operationId: Update_Version - summary: Update Version diff --git a/docs/api/apiv3/paths/versions.yml b/docs/api/apiv3/paths/versions.yml index 17065020f5b..39000dd280e 100644 --- a/docs/api/apiv3/paths/versions.yml +++ b/docs/api/apiv3/paths/versions.yml @@ -1,119 +1,78 @@ # /api/v3/versions --- get: + summary: List versions + operationId: list_versions + tags: + - Versions + description: |- + Returns a collection of versions. The client can choose to filter the versions similar to how work packages are + filtered. In addition to the provided filters, the server will reduce the result set to only contain versions, + for which the requesting client has sufficient permissions (*view_work_packages*). parameters: - - description: |- - JSON specifying filter conditions. - Accepts the same format as returned by the [queries](https://www.openproject.org/docs/api/endpoints/queries/) endpoint. - Currently supported filters are: + - name: filters + description: |- + JSON specifying filter conditions. Accepts the same format as returned by + the [queries](https://www.openproject.org/docs/api/endpoints/queries/) endpoint. Currently supported + filters are: - + sharing: filters versions by how they are shared within the server (*none*, *descendants*, *hierarchy*, *tree*, *system*). - + name: filters versions by their name. + - sharing: filters versions by how they are shared within the server (*none*, *descendants*, *hierarchy*, *tree*, *system*). + - name: filters versions by their name. example: '[{ "sharing": { "operator": "=", "values": ["system"] } }]' in: query - name: filters required: false schema: type: string - - description: |- - JSON specifying sort criteria. - Accepts the same format as returned by the [queries](https://www.openproject.org/docs/api/endpoints/queries/) endpoint. Currently supported attributes are: + - name: sortBy + description: |- + JSON specifying sort criteria. Accepts the same format as returned by + the [queries](https://www.openproject.org/docs/api/endpoints/queries/) endpoint. Currently supported + attributes are: - + id: Sort by the version id - + name: Sort by the version name using numeric collation, comparing sequences of decimal digits by their numeric value + - id: Sort by the version id + - name: Sort by the version name using numeric collation, comparing sequences of decimal digits by their numeric value example: '[["name", "desc"]]' in: query - name: sortBy required: false schema: type: string responses: '200': + description: OK content: application/hal+json: - examples: - response: - value: - _embedded: - elements: - - _links: - availableInProjects: - href: "/api/v3/versions/11/workspaces" - definingProject: - href: "/api/v3/projects/12" - self: - href: "/api/v3/versions/11" - _type: Version - description: - format: plain - html: This version has a description - raw: This version has a description - endDate: - id: 11 - name: v3.0 Alpha - startDate: '2014-11-20' - status: Open - - _links: - availableInProjects: - href: "/api/v3/versions/12/workspaces" - definingProject: - href: "/api/v3/projects/11" - self: - href: "/api/v3/versions/12" - _type: Version - description: - format: plain - html: '' - raw: '' - endDate: - id: 12 - name: v2.0 - startDate: - status: Closed - - _links: - availableInProjects: - href: "/api/v3/versions/13/workspaces" - definingProject: - href: "/api/v3/projects/13" - self: - href: "/api/v3/versions/10" - _type: Version - description: - format: plain - html: '' - raw: '' - endDate: - id: 10 - name: v1.0 - startDate: - status: Open - _links: - self: - href: "/api/v3/versions" - _type: Collection - count: 3 - total: 3 schema: - "$ref": "../components/schemas/versions_model.yml" - description: OK - headers: {} + $ref: "../components/schemas/version_collection_model.yml" + +post: + summary: Create version + operationId: create_version tags: - Versions - description: Returns a collection of versions. The client can choose to filter the - versions similar to how work packages are filtered. In addition to the provided - filters, the server will reduce the result set to only contain versions, for which - the requesting client has sufficient permissions (*view_work_packages*). - operationId: List_versions - summary: List versions -post: + description: |- + Creates a new version applying the attributes provided in the body. Please note that while there is a fixed set + of attributes, custom fields can extend a version's attributes and are accepted by the endpoint. + + You can use the form and schema to be retrieve the valid attribute values and by that be guided towards + successful creation. + requestBody: + content: + application/json: + schema: + $ref: "../components/schemas/version_write_model.yml" + examples: + 'create version': + $ref: '../components/examples/version_create_request.yml' responses: '201': + description: Created content: application/hal+json: schema: - "$ref": "../components/schemas/version_model.yml" - description: Created - headers: {} + $ref: "../components/schemas/version_read_model.yml" + examples: + response: + $ref: '../components/examples/version_simple_response.yml' '400': $ref: "../components/responses/invalid_request_body.yml" '403': @@ -131,7 +90,6 @@ post: Returned if the client does not have sufficient permissions. **Required permission:** Manage versions - headers: {} '406': $ref: "../components/responses/missing_content_type.yml" '415': @@ -141,12 +99,3 @@ post: Returned if: * a constraint for a property was violated (`PropertyConstraintViolation`) - headers: {} - tags: - - Versions - description: |- - Creates a new version applying the attributes provided in the body. Please note that while there is a fixed set of attributes, custom fields can extend a version's attributes and are accepted by the endpoint. - - You can use the form and schema to be retrieve the valid attribute values and by that be guided towards successful creation. - operationId: Create_version - summary: Create version