# Group Relations Work packages may be related to each other in different ways. ``` +--------------+ +--------------+ | | 1 1 | | | Work package +-------------+--------------+ Work package | | | from | to | | +--------------+ | +--------------+ +------+-------+ | Relation | +--------------+ | type | | reverseType | | description | | delay | +--------------+ ``` ## Actions | Link | Description | Condition | |:-------------------:| -------------------------------------------------------------------- | --------------------------------------------- | | update | Updates the relation between two work packages via a form | **Permission**: manage work package relations | | updateImmediately | Updates the relation between two work packages | **Permission**: manage work package relations | | delete | Destroys the relation between the two work packages | **Permission**: manage work package relations | ## Linked Properties | Link | Description | Type | Constraints | Supported operations | Condition | |:-------------:|-------------------------------------- | ------------- | ----------- | -------------------- | --------------------------------------------- | | self | This relation | Relation | not null | READ | **Permission**: view work packages | | schema | The schema of this relation | Schema | not null | READ | | | from | The emanating work package | WorkPackage | not null | READ | **Permission**: view work packages | | to | The work package the relation ends in | WorkPackage | not null | READ | **Permission**: view work packages | ## Local Properties | Property | Description | Type | Constraints | Supported operations | | :---------------:| ------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------- | -------------------- | | id | Relation ID | Integer | x > 0 | READ | | name | The internationalized name of this kind of relation | String | | READ | type | Which kind of relation (blocks, precedes, etc.) | String | in: relates, duplicates, duplicated, blocks, blocked, precedes, follows, includes, partof, requires, required | READ / WRITE | | reverseType | The kind of relation from the other WP's perspective | String | in: relates, duplicates, duplicated, blocks, blocked, precedes, follows, includes, partof, requires, required | READ | | description | Short text further describing the relation | String | | READ / WRITE | | delay* | The delay in days between closing of `from` and start of `to` | Integer | x >= 0 | READ / WRITE | \* Only applicable for some relation types such as "follows". You can check using the relation by schema endpoint at `/api/v3/relations/schema/{type}`. ## Relation [/api/v3/relations/{id}] + Model + Body { "_links": { "self": { "href": "/api/v3/relations/1" }, "update": { "href": "/api/v3/relations/1/form", "method": "POST" }, "updateImmediately": { "href": "/api/v3/relations/1", "method": "PATCH" }, "delete": { "href": "/api/v3/relations/1", "method": "DELETE" }, "from": { "href": "/api/v3/work_packages/42", "title": "Steel Delivery" }, "to": { "href": "/api/v3/work_packages/84", "title": "Bending the steel" } }, "_type": "Relation", "id": 1, "name": "precedes", "type": "precedes", "reverseType": "follows", "description": "We can't bend the steel before it's been delivered!", "delay": 0 } ## View Relation [GET] + Parameters + id (required, integer, `1`) ... Relation id + Response 200 (application/hal+json) [Relation][] + Response 404 (application/hal+json) Returned if the relation does not exist or the client does not have sufficient permissions to see it. **Required permission:** view work packages for the involved work packages + Body { "_type": "Error", "errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound", "message": "The specified relation does not exist." } ## Edit Relation [PATCH] When calling this endpoint the client provides a single object, containing the properties and links that it wants to change, in the body. It is only allowed to provide properties or links supporting the **write** operation. Note that changing the `type` of a relation invariably also changes the respective `reverseType` as well as the "name" of it. The returned Relation object will reflect that change. For instance if you change a Relation's `type` to "follows" then the `reverseType` will be changed to `precedes`. + Parameters + id (required, integer, `1`) ... Relation ID + Request Update Relation (application/json) + Body { "type": "blocks", "description": "Actually the supplier has to bend the steel before they can deliver it." "delay": 3 } + Response 200 (application/hal+json) [Relation][] + Response 400 (application/hal+json) Occurs when the client did not send a valid JSON object in the request body. + Body { "_type": "Error", "errorIdentifier": "urn:openproject-org:api:v3:errors:InvalidRequestBody", "message": "The request body was not a single JSON object." } + Response 404 (application/hal+json) Returned if the relation does not exist or the client does not have sufficient permissions to see it. **Required permission:** manage work package relations + Body { "_type": "Error", "errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound", "message": "The specified relation does not exist." } + Response 422 (application/hal+json) Returned if: * the client tries to modify a read-only property (`PropertyIsReadOnly`) * a constraint for a property was violated (`PropertyConstraintViolation`) * the client provides a link to an invalid resource (`ResourceTypeMismatch`) or a work package that does not exist or for which the client does not have sufficient permissions to see it (**required permissions**: `view work packages` for the involved work packages). + Body { "_type": "Error", "errorIdentifier": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation", "message": "Delay must be a number greater than or equal to 0", "_embedded": { "details": { "attribute": "delay" } } } ## Delete Relation [DELETE] Deletes the relation. + Parameters + id (required, integer, `1`) ... Relation ID + Response 204 (application/hal+json) Returned if the relation was deleted successfully. The response body is empty. + Body + Response 403 (application/hal+json) Returned if the client does not have sufficient permissions. **Required permission:** manage work package relations + Body { "_type": "Error", "errorIdentifier": "urn:openproject-org:api:v3:errors:MissingPermission", "message": "You are not allowed to delete this relation." } + Response 404 (application/hal+json) Returned if the relation does not exist or the client does not have sufficient permissions to see it. **Required permission:** manage work package relations + Body { "_type": "Error", "errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound", "message": "The specified relation does not exist." } ## Relation schema [/api/v3/relations/schema] + Model + Body { "_type": "Schema", "_links": { "self": { "href": "/api/v3/relations/schema" } }, "id": { "name": "ID", "type": "Integer", "writable": false }, "type": { "name": "Type", "type": "String", "writable": true }, "reverseType": { "name": "Reverse Type", "type": "String", "writable": false }, "description": { "name": "Description", "type": "String", "writable": true }, "from": { "name": "From work package", "type": "WorkPackage", "writable": false }, "to": { "name": "To work package", "type": "WorkPackage", "writable": false }, "delay": { "name": "Delay", "type": "Integer", "writable": true } } ## View relation schema [GET] + Response 200 (application/hal+json) [Relation schema][] ## Relation schema for type [/api/v3/relations/schema/{type}] The exact schema for a relation may depend on it's type. For instance the "follows" relation has an additional "delay" field which is not applicable for the other relations. ## View relation schema for type [GET] + Parameters + type (required, string, `follows`) ... Type of the schema + Response 200 (application/hal+json) [Relation schema][] + Response 404 (application/hal+json) Returned if the relation type does not exist or the client does not have sufficient permissions to see it. **Required permission:** manage work package relations + Body { "_type": "Error", "errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound", "message": "The specified relation type does not exist." } ## Relations [/api/v3/relations{?filters,sortBy}] + Model + Body { "_links": { "self": { "href": "/api/v3/relations" } }, "total": 3, "count": 1, "_type": "Collection", "_embedded": { "elements": [ { "_links": { "self": { "href": "/api/v3/relations/1" }, "update": { "href": "/api/v3/relations/1/form", "method": "POST" }, "updateImmediately": { "href": "/api/v3/relations/1", "method": "PATCH" }, "delete": { "href": "/api/v3/relations/1", "method": "DELETE" }, "from": { "href": "/api/v3/work_packages/42", "title": "Steel Delivery" }, "to": { "href": "/api/v3/work_packages/84", "title": "Bending the steel" } }, "_type": "Relation", "id": 1, "name": "precedes", "type": "precedes", "reverseType": "follows", "description": "We can't bend the steel before it's been delivered!", "delay": 0 } ] } } ## List Relations [GET] Lists all relations according to the given (optional, logically conjunctive) filters and ordered by ID. The response only includes relations between work packages which the user is allowed to see. + Parameters + filters (optional, string, `[{ "from": { "operator": "=", "values": 42 }" }]`) ... JSON specifying filter conditions. Accepts the same format as returned by the [queries](#queries) endpoint. Valid fields to filter by are: + id - ID of relation + from - ID of work package from which the filtered relations emanates. + to - ID of work package to which this related points. + involved - ID of either the `from` or the `to` work package. + type - The type of relation to filter by, e.g. "follows". + sortBy (optional, string, `[["type", "asc"]]`) ... JSON specifying sort criteria. Accepts the same format as returned by the [queries](#queries) endpoint. + Response 200 (application/hal+json) [Relations][] ## Relation edit form [/api/v3/relations/{id}/form] This endpoint returns a form to allow a guided creation of a new work package relation. The returned form will be pre-filled with default values for every property, if available. For more details and all possible responses see the general specification of [Forms](#forms). + Model + Body { "_links": { "self": { "href": "/api/v3/relations/form" }, "validate": { "href": "/api/v3/relations/form", "method": "POST" }, "commit": { "href": "/api/v3/relations", "method": "PATCH" } }, "_type": "Form", "_embedded": { "payload": { "_links": { "from": { "href": "/api/v3/work_packages/4534" }, "to": { "href": "/api/v3/work_packages/3857" } }, "_type": "WorkPackage", "type": "follows", "delay": 3, "description": "let it rest for 3 days" }, "schema": { "_type": "Schema", "_links": { "self": { "href": "/api/v3/relations/schema" } }, "id": { "name": "ID", "type": "Integer", "writable": false }, "type": { "name": "Type", "type": "String", "writable": true, "allowedValues": [ "relates", "duplicates", "duplicated", "blocks", "blocked", "precedes", "follows", "includes", "partof", "requires", "required" ] }, "reverseType": { "name": "Reverse Type", "type": "String", "writable": false }, "description": { "name": "Description", "type": "String", "writable": true }, "from": { "name": "From work package", "type": "WorkPackage", "writeable": false }, "to": { "name": "To work package", "type": "WorkPackage", "writable": false }, "delay": { "name": "Delay", "type": "Integer", "writable": true } }, "validationErrors": { "from": { "_type": "Error", "errorIdentifier": "urn:openproject-org:api:v3:errors:BadExampleError", "message": "For the purpose of this example we need a validation error. The remainder of the response pretends there were no errors." } } } } ## Relation edit form [POST] + Request { "_type": "Relation", "type": "follows", "description": "let it rest for 3 days", "delay": 3 } + Parameters + id (required, integer, `1`) ... ID of the relation being modified + Response 200 (application/hal+json) [Relation edit form][] + Response 403 (application/hal+json) Returned if the client does not have sufficient permissions. **Required permission:** manage work package relations *Note that you will only receive this error, if you are at least allowed to see the involved work packages.* + Body { "_type": "Error", "errorIdentifier": "urn:openproject-org:api:v3:errors:MissingPermission", "message": "You are not allowed to edit the specified relation." } + Response 404 (application/hal+json) Returned if the relation does not exist or the client does not have sufficient permissions to see it. **Required permission:** view (involved) work package(s), manage work package relations + Body { "_type": "Error", "errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound", "message": "The specified relation does not exist." }