[#71358] improve API specification for versions

- split into read and write models
- add custom field pattern properties
- improved description for endpoints
- add extracted examples
This commit is contained in:
Eric Schubert
2026-02-11 16:35:03 +01:00
parent db6aaaa984
commit 10d472052d
13 changed files with 381 additions and 319 deletions
@@ -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"
@@ -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: "<p>First draft of the energy weapon ... (behold, Alderaan *evil_laughter*)</p>"
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"
@@ -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
@@ -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
@@ -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
@@ -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'
@@ -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"
@@ -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
@@ -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
@@ -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
+17 -5
View File
@@ -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:
+85 -110
View File
@@ -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
+47 -98
View File
@@ -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