API: Portfolios

Portfolios are one of the types of workspaces in OpenProject structuring the information (e.g. work packages, wikis) into smaller sets. They are typically used to group, structure and manage sub-portfolios, programs and projects that target similar strategic goals of the organization.

As containers, they also control behaviour of the elements within them. One of the most important aspects of this is that portfolios limit permissions by having members with a certain permission set (roles) assigned to them.

Actions

Link Description Condition
update Form endpoint that aids in updating this portfolio Permission: edit workspace
updateImmediately Directly update this portfolio Permission: edit workspace
delete Delete this portfolio Permission: admin
favor Mark this portfolio as favorited by the current user Permission: none but login is required, only present if the portfolio is not yet favorited
disfavor Mark this portfolio as no longer favorited by the current user Permission: none but login is required, only present if the portfolio is favorited
createWorkPackage Form endpoint that aids in preparing and creating a work package Permission: add work packages
createWorkPackageImmediately Directly creates a work package in the portfolio Permission: add work packages

Linked Properties

Link Description Type Constraints Supported operations Condition
self This portfolio Portfolio not null READ
ancestors Array of all ancestors of the portfolio, down from the root node (first element) to the parent (last element). Collection not null READ Permission view portfolio on the ancestor portfolio. Non visible portfolios will be omitted
categories Categories available in this portfolio Collection not null READ
types Types available in this portfolio Collection not null READ Permission: view work packages or manage types
versions Versions available in this portfolio Collection not null READ Permission: view work packages or manage versions
memberships Memberships in the portfolio Collection not null READ Permission: view members
workPackages Work Packages of this portfolio Collection not null READ
parent Parent portfolio of the portfolio Portfolio READ/WRITE Permission edit workspace
status Denotes the status of the portfolio, so whether the portfolio is on track, at risk or is having trouble. PortfolioStatus READ/WRITE Permission edit workspace

Depending on custom fields defined for portfolios, additional links might exist.

Note, that the parent and ancestor links may contain the “undisclosed uri” urn:openportfolio-org:api:v3:undisclosed in case an ancestor portfolio is defined but the client lacks permission to see it. See the general introduction into links’ properties for more information.

Local Properties

Property Description Type Constraints Supported operations
id Portfolios’ id Integer x > 0 READ/WRITE
identifier String READ/WRITE
name String READ/WRITE
active Indicates whether the portfolio is currently active or already archived Boolean READ/WRITE
favorited Indicates whether the portfolio is favorited by the current user Boolean READ
statusExplanation A text detailing and explaining why the portfolio has the reported status Formattable READ/WRITE
public Indicates whether the portfolio is accessible for everybody Boolean READ/WRITE
description Formattable READ/WRITE
createdAt Time of creation DateTime READ
updatedAt Time of the most recent change to the portfolio DateTime READ

Depending on custom fields defined for portfolios, additional properties might exist.

Methods

List portfolios

Returns a collection of portfolios. The collection can be filtered via query parameters similar to how work packages are filtered. In addition to the provided filter, the result set is always limited to only contain portfolios the client is allowed to see.

filters
string

optional query

JSON specifying filter conditions. Accepts the same format as returned by the queries endpoint. Currently supported filters are:

  • active: based on the active property of the portfolio
  • ancestor: filters portfolios by their ancestor. A portfolio is not considered to be its own ancestor.
  • available_project_attributes: filters portfolios based on the activated project attributes.
  • created_at: based on the time the portfolio was created
  • favorited: based on the favorited property of the portfolio
  • id: based on portfolios’ id.
  • latest_activity_at: based on the time the last activity was registered on a portfolio.
  • name_and_identifier: based on both the name and the identifier.
  • parent_id: filters portfolios by their parent.
  • principal: based on members of the portfolio.
  • project_phase_any: based on the project phases active in a portfolio.
  • project_status_code: based on status code of the portfolio
  • storage_id: filters portfolios by linked storages
  • storage_url: filters portfolios by linked storages identified by the host url
  • type_id: based on the types active in a portfolio.
  • user_action: based on the actions the current user has in the portfolio.
  • visible: based on the visibility for the user (id) provided as the filter value. This filter is useful for admins to identify the portfolios visible to a user.

There might also be additional filters based on the custom fields that have been configured.

Each defined lifecycle step will also define a filter in this list endpoint. Given that the elements are not static but rather dynamically created on each OpenProject instance, a list cannot be provided. Those filters follow the schema:

  • project_start_gate_[id]: a filter on a project phase’s start gate active in a portfolio. The id is the id of the phase the gate belongs to.
  • project_finish_gate_[id]: a filter on a project phase’s finish gate active in a portfolio. The id is the id of the phase the gate belongs to.
  • project_phase_[id]: a filter on a project phase active in a portfolio. The id is the id of the phase queried for.

Example:
[{ "ancestor": { "operator": "=", "values": ["1"] }" }]

sortBy
string

optional query

JSON specifying sort criteria. Currently supported orders are:

  • id
  • name
  • typeahead (sorting by hierarchy and name)
  • created_at
  • public
  • latest_activity_at
  • required_disk_space

There might also be additional orders based on the custom fields that have been configured.

Example:
[["id", "asc"]]

select
string

optional query

Comma separated list of properties to include.

Example:
total,elements/identifier,elements/name

200

OK

{
  "_type": "Collection",
  "count": 2,
  "total": 2,
  "pageSize": 20,
  "offset": 1,
  "_embedded": {
    "elements": [
      {
        "_hint": "Portfolio resource shortened for brevity",
        "id": 1,
        "identifier": "connect2030",
        "name": "Digital Connect 2030",
        "active": true,
        "public": true
      },
      {
        "_hint": "Portfolio resource shortened for brevity",
        "id": 2,
        "identifier": "future2050",
        "name": "Digital Future 2050",
        "active": true,
        "public": false
      }
    ]
  },
  "_links": {
    "self": {
      "href": "/api/v3/portfolios?filters=%5B%5D&offset=1&pageSize=20"
    },
    "jumpTo": {
      "href": "/api/v3/portfolios?filters=%5B%5D&offset=%7Boffset%7D&pageSize=20",
      "templated": true
    },
    "changeSize": {
      "href": "/api/v3/portfolios?filters=%5B%5D&offset=1&pageSize=%7Bsize%7D",
      "templated": true
    },
    "representations": [
      {
        "href": "/portfolios.csv?filters=%5B%5D&offset=1&pageSize=20",
        "identifier": "csv",
        "type": "text/csv",
        "title": "CSV"
      },
      {
        "href": "/portfolios.xls?filters=%5B%5D&offset=1&pageSize=20",
        "identifier": "xls",
        "type": "application/vnd.ms-excel",
        "title": "XLS"
      }
    ]
  }
}
PortfolioCollectionModel
{
  "allOf": [
    {
      "$ref": "#/components/schemas/OffsetPaginatedCollectionModel"
    },
    {
      "type": "object",
      "required": [
        "_links",
        "_embedded"
      ],
      "properties": {
        "_links": {
          "allOf": [
            {
              "$ref": "#/components/schemas/OffsetPaginatedCollectionLinks"
            },
            {
              "type": "object",
              "properties": {
                "representations": {
                  "type": "array",
                  "items": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/Link"
                      },
                      {
                        "description": "A portfolio collection representation in a specific file format."
                      }
                    ]
                  }
                }
              }
            }
          ]
        },
        "_embedded": {
          "type": "object",
          "required": [
            "elements"
          ],
          "properties": {
            "elements": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/PortfolioModel"
              }
            }
          }
        }
      }
    }
  ]
}

400

Returned if the client sends invalid request parameters e.g. filters

{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:InvalidQuery",
  "message": "Filters Invalid filter does not exist."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}

View portfolio

id
integer

required path

Portfolio id

Example:
1

200

OK

PortfolioModel
{
  "type": "object",
  "properties": {
    "_type": {
      "type": "string",
      "enum": [
        "Portfolio"
      ]
    },
    "id": {
      "type": "integer",
      "description": "Portfolios' id",
      "minimum": 1
    },
    "identifier": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "active": {
      "type": "boolean",
      "description": "Indicates whether the portfolio is currently active or already archived"
    },
    "favorited": {
      "type": "boolean",
      "description": "Indicates whether the portfolio is favorited by the current user"
    },
    "statusExplanation": {
      "allOf": [
        {
          "$ref": "#/components/schemas/Formattable"
        },
        {
          "description": "A text detailing and explaining why the portfolio has the reported status"
        }
      ]
    },
    "public": {
      "type": "boolean",
      "description": "Indicates whether the portfolio is accessible for everybody"
    },
    "description": {
      "$ref": "#/components/schemas/Formattable"
    },
    "createdAt": {
      "type": "string",
      "format": "date-time",
      "description": "Time of creation. Can be writable by admins with the `apiv3_write_readonly_attributes` setting enabled."
    },
    "updatedAt": {
      "type": "string",
      "format": "date-time",
      "description": "Time of the most recent change to the portfolio"
    },
    "_links": {
      "type": "object",
      "required": [
        "self",
        "categories",
        "types",
        "versions",
        "memberships",
        "workPackages"
      ],
      "properties": {
        "update": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Form endpoint that aids in updating this portfolio\n\n# Conditions\n\n**Permission**: edit workspace"
            }
          ]
        },
        "updateImmediately": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Directly update this portfolio\n\n# Conditions\n\n**Permission**: edit workspace"
            }
          ]
        },
        "delete": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Delete this portfolio\n\n# Conditions\n\n**Permission**: admin"
            }
          ]
        },
        "favor": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Mark this portfolio as favorited by the current user\n\n# Conditions\n\nOnly present if the portfolio is not yet favorited\n\nPermission**: none but login is required"
            }
          ]
        },
        "disfavor": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Mark this portfolio as not favorited by the current user\n\n# Conditions\nOnly present if the portfolio is favorited by the current user\n\nPermission**: none but login is required"
            }
          ]
        },
        "createWorkPackage": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Form endpoint that aids in preparing and creating a work package\n\n# Conditions\n\n**Permission**: add work packages"
            }
          ]
        },
        "createWorkPackageImmediately": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Directly creates a work package in the portfolio\n\n# Conditions\n\n**Permission**: add work packages"
            }
          ]
        },
        "self": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "This portfolio\n\n**Resource**: Portfolio"
            }
          ]
        },
        "categories": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Categories available in this portfolio\n\n**Resource**: Collection"
            }
          ]
        },
        "types": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Types available in this portfolio\n\n**Resource**: Collection\n\n# Conditions\n\n**Permission**: view work packages or manage types"
            }
          ]
        },
        "versions": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Versions available in this portfolio\n\n**Resource**: Collection\n\n# Conditions\n\n**Permission**: view work packages or manage versions"
            }
          ]
        },
        "memberships": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Memberships in the  portfolio\n\n**Resource**: Collection\n\n# Conditions\n\n**Permission**: view members"
            }
          ]
        },
        "workPackages": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Work Packages of this portfolio\n\n**Resource**: Collection"
            }
          ]
        },
        "parent": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Parent of the portfolio\n\n**Resource**: Portfolio\n\n# Conditions\n\n**Permission** edit workspace"
            }
          ]
        },
        "status": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Denotes the status of the portfolio, so whether the portfolio is on track, at risk or is having trouble.\n\n**Resource**: ProjectStatus\n\n# Conditions\n\n**Permission** edit workspace"
            }
          ]
        },
        "storages": {
          "type": "array",
          "items": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Link"
              },
              {
                "description": "The link to a storage that is active for this portfolio.\n\n**Resource**: Storage\n\n# Conditions\n\n**Permission**: view_file_links"
              }
            ]
          }
        },
        "projectStorages": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "The project storage collection of this portfolio.\n\n**Resource**: Collection\n\n# Conditions\n\n**Permission**: view_file_links"
            }
          ]
        },
        "ancestors": {
          "type": "array",
          "items": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Link"
              },
              {
                "description": "A collection of links to the ancestor portfolios.\n\n**Resource**: Portfolio"
              }
            ]
          }
        }
      }
    }
  }
}

404

Returned if the portfolio does not exist or the client does not have sufficient permissions to see it.

Required permission: any permission in the portfolio

Note: A client without sufficient permissions shall not be able to test for the existence of a portfolio. That’s why a 404 is returned here, even if a 403 might be more appropriate.

{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
  "message": "The requested resource could not be found."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}

Update portfolio

Updates the given portfolio by applying the attributes provided in the body.

id
integer

required path

Portfolio id

Example:
1

{
  "_type": {
    "type": "string",
    "enum": [
      "Portfolio"
    ]
  },
  "id": {
    "type": "integer",
    "description": "Portfolios' id",
    "minimum": 1
  },
  "identifier": {
    "type": "string"
  },
  "name": {
    "type": "string"
  },
  "active": {
    "type": "boolean",
    "description": "Indicates whether the portfolio is currently active or already archived"
  },
  "favorited": {
    "type": "boolean",
    "description": "Indicates whether the portfolio is favorited by the current user"
  },
  "statusExplanation": {
    "allOf": [
      {
        "$ref": "#/components/schemas/Formattable"
      },
      {
        "description": "A text detailing and explaining why the portfolio has the reported status"
      }
    ]
  },
  "public": {
    "type": "boolean",
    "description": "Indicates whether the portfolio is accessible for everybody"
  },
  "description": {
    "$ref": "#/components/schemas/Formattable"
  },
  "createdAt": {
    "type": "string",
    "format": "date-time",
    "description": "Time of creation. Can be writable by admins with the `apiv3_write_readonly_attributes` setting enabled."
  },
  "updatedAt": {
    "type": "string",
    "format": "date-time",
    "description": "Time of the most recent change to the portfolio"
  },
  "_links": {
    "type": "object",
    "required": [
      "self",
      "categories",
      "types",
      "versions",
      "memberships",
      "workPackages"
    ],
    "properties": {
      "update": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Form endpoint that aids in updating this portfolio\n\n# Conditions\n\n**Permission**: edit workspace"
          }
        ]
      },
      "updateImmediately": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Directly update this portfolio\n\n# Conditions\n\n**Permission**: edit workspace"
          }
        ]
      },
      "delete": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Delete this portfolio\n\n# Conditions\n\n**Permission**: admin"
          }
        ]
      },
      "favor": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Mark this portfolio as favorited by the current user\n\n# Conditions\n\nOnly present if the portfolio is not yet favorited\n\nPermission**: none but login is required"
          }
        ]
      },
      "disfavor": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Mark this portfolio as not favorited by the current user\n\n# Conditions\nOnly present if the portfolio is favorited by the current user\n\nPermission**: none but login is required"
          }
        ]
      },
      "createWorkPackage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Form endpoint that aids in preparing and creating a work package\n\n# Conditions\n\n**Permission**: add work packages"
          }
        ]
      },
      "createWorkPackageImmediately": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Directly creates a work package in the portfolio\n\n# Conditions\n\n**Permission**: add work packages"
          }
        ]
      },
      "self": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "This portfolio\n\n**Resource**: Portfolio"
          }
        ]
      },
      "categories": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Categories available in this portfolio\n\n**Resource**: Collection"
          }
        ]
      },
      "types": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Types available in this portfolio\n\n**Resource**: Collection\n\n# Conditions\n\n**Permission**: view work packages or manage types"
          }
        ]
      },
      "versions": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Versions available in this portfolio\n\n**Resource**: Collection\n\n# Conditions\n\n**Permission**: view work packages or manage versions"
          }
        ]
      },
      "memberships": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Memberships in the  portfolio\n\n**Resource**: Collection\n\n# Conditions\n\n**Permission**: view members"
          }
        ]
      },
      "workPackages": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Work Packages of this portfolio\n\n**Resource**: Collection"
          }
        ]
      },
      "parent": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Parent of the portfolio\n\n**Resource**: Portfolio\n\n# Conditions\n\n**Permission** edit workspace"
          }
        ]
      },
      "status": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "Denotes the status of the portfolio, so whether the portfolio is on track, at risk or is having trouble.\n\n**Resource**: ProjectStatus\n\n# Conditions\n\n**Permission** edit workspace"
          }
        ]
      },
      "storages": {
        "type": "array",
        "items": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "The link to a storage that is active for this portfolio.\n\n**Resource**: Storage\n\n# Conditions\n\n**Permission**: view_file_links"
            }
          ]
        }
      },
      "projectStorages": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Link"
          },
          {
            "description": "The project storage collection of this portfolio.\n\n**Resource**: Collection\n\n# Conditions\n\n**Permission**: view_file_links"
          }
        ]
      },
      "ancestors": {
        "type": "array",
        "items": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "A collection of links to the ancestor portfolios.\n\n**Resource**: Portfolio"
            }
          ]
        }
      }
    }
  }
}

200

OK

{
  "_type": "Portfolio",
  "_links": {
    "self": {
      "href": "/api/v3/portfolios/1",
      "title": "Lorem"
    },
    "createWorkPackage": {
      "href": "/api/v3/portfolios/1/work_packages/form",
      "method": "post"
    },
    "createWorkPackageImmediate": {
      "href": "/api/v3/portfolios/1/work_packages",
      "method": "post"
    },
    "categories": {
      "href": "/api/v3/portfolios/1/categories"
    },
    "types": {
      "href": "/api/v3/portfolios/1/types"
    },
    "versions": {
      "href": "/api/v3/portfolios/1/versions"
    },
    "workPackages": {
      "href": "/api/v3/portfolios/1/work_packages"
    },
    "memberships": {
      "href": "/api/v3/memberships?filters=[{\"project\":{\"operator\":\"=\",\"values\":[\"1\"]}}]"
    },
    "customField456": {
      "href": "/api/v3/users/315",
      "title": "A user"
    },
    "parent": {
      "href": "/api/v3/portfolios/123",
      "title": "Parent portfolio"
    },
    "ancestors": [
      {
        "href": "/api/v3/portfolios/2",
        "title": "Root portfolio"
      },
      {
        "href": "/api/v3/portfolios/12",
        "title": "Grandparent portfolio"
      },
      {
        "href": "/api/v3/portfolios/123",
        "title": "Parent portfolio"
      }
    ],
    "status": {
      "href": "/api/v3/project_statuses/on_track",
      "title": "On track"
    }
  },
  "id": 1,
  "identifier": "connect2025",
  "name": "Digital Connect 2030",
  "active": true,
  "public": false,
  "statusExplanation": {
    "format": "markdown",
    "raw": "Everything **fine**",
    "html": "<p>Everything <strong>fine</strong></p>"
  },
  "description": {
    "format": "markdown",
    "raw": "This collection showcases a diverse selection of projects that highlight our commitment to excellence and our passion for design. From innovative web applications to stunning graphic designs, each piece reflects our unique approach and dedication to delivering impactful solutions. Discover the journey of our work and see how we bring ideas to life.",
    "html": "<p>This collection showcases a diverse selection of projects that highlight our commitment to excellence and our passion for design. From innovative web applications to stunning graphic designs, each piece reflects our unique approach and dedication to delivering impactful solutions. Discover the journey of our work and see how we bring ideas to life.</p>"
  },
  "createdAt": "2014-05-21T08:51:20.396Z",
  "updatedAt": "2014-05-21T08:51:20.396Z",
  "customField123": 123
}
PortfolioModel
{
  "type": "object",
  "properties": {
    "_type": {
      "type": "string",
      "enum": [
        "Portfolio"
      ]
    },
    "id": {
      "type": "integer",
      "description": "Portfolios' id",
      "minimum": 1
    },
    "identifier": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "active": {
      "type": "boolean",
      "description": "Indicates whether the portfolio is currently active or already archived"
    },
    "favorited": {
      "type": "boolean",
      "description": "Indicates whether the portfolio is favorited by the current user"
    },
    "statusExplanation": {
      "allOf": [
        {
          "$ref": "#/components/schemas/Formattable"
        },
        {
          "description": "A text detailing and explaining why the portfolio has the reported status"
        }
      ]
    },
    "public": {
      "type": "boolean",
      "description": "Indicates whether the portfolio is accessible for everybody"
    },
    "description": {
      "$ref": "#/components/schemas/Formattable"
    },
    "createdAt": {
      "type": "string",
      "format": "date-time",
      "description": "Time of creation. Can be writable by admins with the `apiv3_write_readonly_attributes` setting enabled."
    },
    "updatedAt": {
      "type": "string",
      "format": "date-time",
      "description": "Time of the most recent change to the portfolio"
    },
    "_links": {
      "type": "object",
      "required": [
        "self",
        "categories",
        "types",
        "versions",
        "memberships",
        "workPackages"
      ],
      "properties": {
        "update": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Form endpoint that aids in updating this portfolio\n\n# Conditions\n\n**Permission**: edit workspace"
            }
          ]
        },
        "updateImmediately": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Directly update this portfolio\n\n# Conditions\n\n**Permission**: edit workspace"
            }
          ]
        },
        "delete": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Delete this portfolio\n\n# Conditions\n\n**Permission**: admin"
            }
          ]
        },
        "favor": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Mark this portfolio as favorited by the current user\n\n# Conditions\n\nOnly present if the portfolio is not yet favorited\n\nPermission**: none but login is required"
            }
          ]
        },
        "disfavor": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Mark this portfolio as not favorited by the current user\n\n# Conditions\nOnly present if the portfolio is favorited by the current user\n\nPermission**: none but login is required"
            }
          ]
        },
        "createWorkPackage": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Form endpoint that aids in preparing and creating a work package\n\n# Conditions\n\n**Permission**: add work packages"
            }
          ]
        },
        "createWorkPackageImmediately": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Directly creates a work package in the portfolio\n\n# Conditions\n\n**Permission**: add work packages"
            }
          ]
        },
        "self": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "This portfolio\n\n**Resource**: Portfolio"
            }
          ]
        },
        "categories": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Categories available in this portfolio\n\n**Resource**: Collection"
            }
          ]
        },
        "types": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Types available in this portfolio\n\n**Resource**: Collection\n\n# Conditions\n\n**Permission**: view work packages or manage types"
            }
          ]
        },
        "versions": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Versions available in this portfolio\n\n**Resource**: Collection\n\n# Conditions\n\n**Permission**: view work packages or manage versions"
            }
          ]
        },
        "memberships": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Memberships in the  portfolio\n\n**Resource**: Collection\n\n# Conditions\n\n**Permission**: view members"
            }
          ]
        },
        "workPackages": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Work Packages of this portfolio\n\n**Resource**: Collection"
            }
          ]
        },
        "parent": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Parent of the portfolio\n\n**Resource**: Portfolio\n\n# Conditions\n\n**Permission** edit workspace"
            }
          ]
        },
        "status": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "Denotes the status of the portfolio, so whether the portfolio is on track, at risk or is having trouble.\n\n**Resource**: ProjectStatus\n\n# Conditions\n\n**Permission** edit workspace"
            }
          ]
        },
        "storages": {
          "type": "array",
          "items": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Link"
              },
              {
                "description": "The link to a storage that is active for this portfolio.\n\n**Resource**: Storage\n\n# Conditions\n\n**Permission**: view_file_links"
              }
            ]
          }
        },
        "projectStorages": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Link"
            },
            {
              "description": "The project storage collection of this portfolio.\n\n**Resource**: Collection\n\n# Conditions\n\n**Permission**: view_file_links"
            }
          ]
        },
        "ancestors": {
          "type": "array",
          "items": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Link"
              },
              {
                "description": "A collection of links to the ancestor portfolios.\n\n**Resource**: Portfolio"
              }
            ]
          }
        }
      }
    }
  }
}

400

Occurs when the client did not send a valid JSON object in the request body.

{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:InvalidRequestBody",
  "message": "The request body was not a single JSON object."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}

403

Returned if the client does not have sufficient permissions.

Required permission: edit project for the portfolio to be altered

{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:MissingPermission",
  "message": "You are not authorized to access this resource."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}

404

Returned if the portfolio does not exist or the client does not have sufficient permissions to see it.

Required permission: view project

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.

{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
  "message": "The requested resource could not be found."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}

406

Occurs when the client did not send a Content-Type header

"Missing content-type header"
{
  "type": "string"
}

415

Occurs when the client sends an unsupported Content-Type header.

{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:TypeNotSupported",
  "message": "Expected CONTENT-TYPE to be (expected value) but got (actual value)."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}

422

Returned if:

  • a constraint for a property was violated (PropertyConstraintViolation)
{
  "_embedded": {
    "details": {
      "attribute": "name"
    }
  },
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation",
  "message": "Name can't be blank."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}

Delete portfolio

Deletes the portfolio permanently. As this is a lengthy process, the actual deletion is carried out asynchronously. So the portfolio might exist well after the request has returned successfully. To prevent unwanted changes to the portfolio scheduled for deletion, it is archived at once.

id
integer

required path

Portfolio id

Example:
1

204

Returned if the portfolio was successfully deleted. There is currently no endpoint to query for the actual deletion status. Such an endpoint might be added in the future.

403

Returned if the client does not have sufficient permissions.

Required permission: admin

{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:MissingPermission",
  "message": "You are not authorized to access this resource."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}

404

Returned if the portfolio does not exist or the client does not have sufficient permissions to see it.

Required permission: any permission in the portfolio

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.

{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:NotFound",
  "message": "The requested resource could not be found."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}

406

Occurs when the client did not send a Content-Type header

"Missing content-type header"
{
  "type": "string"
}

415

Occurs when the client sends an unsupported Content-Type header.

{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:TypeNotSupported",
  "message": "Expected CONTENT-TYPE to be (expected value) but got (actual value)."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}

422

Returned if the portfolio cannot be deleted. This can happen when there are still references to the portfolio in other workspaces that need to be severed at first.

{
  "_embedded": {
    "details": {
      "attribute": "base"
    }
  },
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation",
  "message": "Work packages in non descendant projects reference versions of the portfolio or its descendants."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}

Portfolio update form

id
integer

required path

Portfolio id

Example:
1

{
  "type": "object"
}

200

OK

400

Occurs when the client did not send a valid JSON object in the request body.

{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:InvalidRequestBody",
  "message": "The request body was not a single JSON object."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}

403

Returned if the client does not have sufficient permissions.

Required permission: edit workspace in the portfolio

{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:MissingPermission",
  "message": "You are not authorized to access this resource."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}

406

Occurs when the client did not send a Content-Type header

"Missing content-type header"
{
  "type": "string"
}

415

Occurs when the client sends an unsupported Content-Type header.

{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:TypeNotSupported",
  "message": "Expected CONTENT-TYPE to be (expected value) but got (actual value)."
}
ErrorResponse
{
  "type": "object",
  "required": [
    "_type",
    "errorIdentifier",
    "message"
  ],
  "properties": {
    "_embedded": {
      "type": "object",
      "properties": {
        "details": {
          "type": "object",
          "properties": {
            "attribute": {
              "type": "string",
              "example": "project"
            }
          }
        }
      }
    },
    "_type": {
      "type": "string",
      "enum": [
        "Error"
      ]
    },
    "errorIdentifier": {
      "type": "string",
      "example": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation"
    },
    "message": {
      "type": "string",
      "example": "Project can't be blank."
    }
  }
}