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 

View Relation
/api/v3/relations/{id}
  • Parameters
  • id
    integer (required) Example: 1

    Relation id

  • Response  200
  • Headers
    Content-Type: application/hal+json
    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
    }
  • Response  404
  • 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

    Headers
    Content-Type: application/hal+json
    Body
    {
      "_type": "Error",
      "errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
      "message": "The specified relation does not exist."
    }
Edit Relation
/api/v3/relations/{id}

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
    integer (required) Example: 1

    Relation ID

  • Request  Update Relation
  • Headers
    Content-Type: application/json
    Body
    {
        "type": "blocks",
        "description": "Actually the supplier has to bend the steel before they can deliver it."
        "delay": 3
    }
  • Response  200
  • Headers
    Content-Type: application/hal+json
    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
    }
  • Response  400
  • Occurs when the client did not send a valid JSON object in the request body.

    Headers
    Content-Type: application/hal+json
    Body
    {
      "_type": "Error",
      "errorIdentifier": "urn:openproject-org:api:v3:errors:InvalidRequestBody",
      "message": "The request body was not a single JSON object."
    }
  • Response  404
  • Returned if the relation does not exist or the client does not have sufficient permissions to see it.

    Required permission: manage work package relations

    Headers
    Content-Type: application/hal+json
    Body
    {
      "_type": "Error",
      "errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
      "message": "The specified relation does not exist."
    }
  • Response  422
  • 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).

    Headers
    Content-Type: application/hal+json
    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
/api/v3/relations/{id}

Deletes the relation.

  • Parameters
  • id
    integer (required) Example: 1

    Relation ID

  • Response  204
  • Returned if the relation was deleted successfully. The response body is empty.

    Headers
    Content-Type: application/hal+json
  • Response  403
  • Returned if the client does not have sufficient permissions.

    Required permission: manage work package relations

    Headers
    Content-Type: application/hal+json
    Body
    {
      "_type": "Error",
      "errorIdentifier": "urn:openproject-org:api:v3:errors:MissingPermission",
      "message": "You are not allowed to delete this relation."
    }
  • Response  404
  • Returned if the relation does not exist or the client does not have sufficient permissions to see it.

    Required permission: manage work package relations

    Headers
    Content-Type: application/hal+json
    Body
    {
      "_type": "Error",
      "errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
      "message": "The specified relation does not exist."
    }

Relation schema 

View relation schema
/api/v3/relations/schema
  • Response  200
  • Headers
    Content-Type: application/hal+json
    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
      }
    }

Relation schema for 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
/api/v3/relations/schema/{type}
  • Parameters
  • type
    string (required) Example: follows

    Type of the schema

  • Response  200
  • Headers
    Content-Type: application/hal+json
    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
      }
    }
  • Response  404
  • 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

    Headers
    Content-Type: application/hal+json
    Body
    {
      "_type": "Error",
      "errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
      "message": "The specified relation type does not exist."
    }

Relations 

List Relations
/api/v3/relations{?filters,sortBy}

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
    string (optional) Example: [{ "from": { "operator": "=", "values": 42 }" }]

    JSON specifying filter conditions. Accepts the same format as returned by the 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
    string (optional) Example: [["type", "asc"]]

    JSON specifying sort criteria. Accepts the same format as returned by the queries endpoint.

  • Response  200
  • Headers
    Content-Type: application/hal+json
    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
          }
        ]
      }
    }

Relation edit 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.

Relation edit form
/api/v3/relations/{id}/form
  • Parameters
  • id
    integer (required) Example: 1

    ID of the relation being modified

  • Request
  • Body
    {
      "_type": "Relation",
      "type": "follows",
      "description": "let it rest for 3 days",
      "delay": 3
    }
  • Response  200
  • Headers
    Content-Type: application/hal+json
    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."
          }
        }
      }
    }
  • Response  403
  • 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.

    Headers
    Content-Type: application/hal+json
    Body
    {
      "_type": "Error",
      "errorIdentifier": "urn:openproject-org:api:v3:errors:MissingPermission",
      "message": "You are not allowed to edit the specified relation."
    }
  • Response  404
  • 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

    Headers
    Content-Type: application/hal+json
    Body
    {
      "_type": "Error",
      "errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
      "message": "The specified relation does not exist."
    }