API: Basic Objects

Links to other resources in the API are represented uniformly by so called link objects.

Local Properties

Property Description Type Required Nullable Default
href URL to the referenced resource (might be relative) String
title Representative label for the resource String
templated If true the href contains parts that need to be replaced by the client Boolean false
method The HTTP verb to use when requesting the resource String GET
payload The payload to send in the request to achieve the desired result String unspecified
identifier An optional unique identifier to the link object String unspecified

All link objects must contain the href property, though it might be null. Thus the following is a valid link object: { "href": null } whereas { } is not a valid link object. The meaning of "href": null is that no resource is referenced. For example a work package without an assignee will still have an assignee link, but its href will be null.

If a title is present, the client can display the title to the user when referring to the resource.

Templated links are links that contain client replaceable parts. Replaceable parts are enclosed in braces. For example the link api/v3/example/{id} is not complete in itself, but the client needs to replace the string {id} itself. As of now the API does not indicate the valid replacement values.

The method indicates which HTTP verb the client must use when following the link for the intended purpose.

If a payload is specified, it needs to be sent as the body of the request to achieve the desired result (e.g. perform the action represented by the link). If no payload is specified, there is either no payload to send or a valid payload is not specified by the link object. A payload might also be templated slightly. If the templated property is true, a payload might contain replaceable parts in its strings (e.g. { "href": "/api/v3/examples/{example_id}" }).

Note: When writing links (e.g. during a PATCH operation) only changes to href are accepted. Changes to all other properties will be silently ignored.

For resources invisible to the client (e.g. because of missing permissions), a link will contain the uri urn:openproject-org:api:v3:undisclosed instead of a url. This indicates the existence of a value without revealing the actual value. An example for this is the parent project. A project resource which itself might be visible to the client can have a reference to a parent project invisible to the same client. Revealing the existence of a parent over hiding has the benefit of allowing the client to make an informed decision of whether to keep the existing reference or updating it. Sending ‘{ “href”: “urn:openproject-org:api:v3:undisclosed” }` for a resource will have the effect of keeping the original value. This is especially beneficial if the client creates and updates resources based on the payload object provided as part of a form as is recommended when interacting with the API.

Errors

In case of an error, the API will respond with an appropriate HTTP status code. For responses with an HTTP status of 4xx and 5xx the body will always contain a single error object. Error objects shall give the client additional details about the cause of an erroneous response.

General errors

  • Error objects have their _type set to Error

  • The errorIdentifier serves as a unique (and machine readable) identifier for a specific error cause

    • There may be multiple possible error identifiers per HTTP status code
    • There may be multiple possible HTTP status codes per error identifier
    • The “List of Error Identifiers” defines the possible mappings between HTTP status and error identifier
  • The message contains a human readable concise message describing the error

    • It optionally includes specific information, for example which permission would have been needed to perform an action
    • It is localized depending on the users preferences
    • It must not include HTML or other kind of markup
    • Error messages form complete sentences including punctuation
Example
{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:InternalServerError",
  "message": "An internal server error occurred. This is not your fault."
}

Embedded error information

Errors might optionally contain embedded objects that contain further information.

Error details

Under the embedded key details there might be an object describing the error more verbosely. For example if the error affects a specific field, this field could be defined there.

Example
{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:examples:ExampleError",
  "message": "This is an example error.",
  "_embedded": {
    "details": {
      "_type": "ExampleErrorDetailInformation",
      "erroneousField": "subject"
    }
  }
}

Multiple error objects

To ease implementation of basic clients it is guaranteed that the response body always only contains a single error object. However it is allowed that an error object embeds other error objects under the key errors, thereby aggregating them.

The errorIdentifier of such an object is always urn:openproject-org:api:v3:errors:MultipleErrors. The message can either describe one of the embedded errors or simply state that multiple errors occurred.

Example
{
  "_type": "Error",
  "errorIdentifier": "urn:openproject-org:api:v3:errors:MultipleErrors",
  "message": "Multiple fields violated their constraints.",
  "_embedded": {
    "errors": [
      {
        "_type": "Error",
        "errorIdentifier": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation",
        "...": "..."
      },
      {
        "_type": "Error",
        "errorIdentifier": "urn:openproject-org:api:v3:errors:PropertyConstraintViolation",
        "...": "..."
      }
    ]
  }
}

List of Error Identifiers

  • urn:openproject-org:api:v3:errors:InvalidQuery (HTTP 400) The query contained a value that did not match the servers expectation

  • urn:openproject-org:api:v3:errors:InvalidRenderContext (HTTP 400) The client specified a rendering context that does not exist

  • urn:openproject-org:api:v3:errors:InvalidRequestBody (HTTP 400) The format of the request body did not match the servers expectation

  • urn:openproject-org:api:v3:errors:InvalidSignal (HTTP 400) The client specified a select not available on the resource, e.g because the property/link does not exist on it.

  • urn:openproject-org:api:v3:errors:InvalidUserStatusTransition (HTTP 400) The client used an invalid transition in the attempt to change the status of a user account.

  • urn:openproject-org:api:v3:errors:Unauthenticated (HTTP 401) The client has to authenticate to access the requested resource.

  • urn:openproject-org:api:v3:errors:MissingPermission (HTTP 403) The client does not have the needed permissions to perform the requested action

  • urn:openproject-org:api:v3:errors:NotFound (HTTP 404) Default for HTTP 404 when no further information is available

  • urn:openproject-org:api:v3:errors:UpdateConflict (HTTP 409) The resource changed between GET-ing it and performing an update on it

  • urn:openproject-org:api:v3:errors:TypeNotSupported (HTTP 415) The request contained data in an unsupported media type (Content-Type)

  • urn:openproject-org:api:v3:errors:PropertyConstraintViolation (HTTP 422) The client tried to set a property to an invalid value

  • urn:openproject-org:api:v3:errors:PropertyIsReadOnly (HTTP 422) The client tried to set or change a property that is not writable

  • urn:openproject-org:api:v3:errors:PropertyFormatError (HTTP 422) A property value was provided in a format that the server does not understand or accept

  • urn:openproject-org:api:v3:errors:PropertyMissingError (HTTP 422) The request is syntactically correct, but is missing a property to perform the requested action

  • urn:openproject-org:api:v3:errors:PropertyValueNotAvailableAnymore (HTTP 422) An unchanged property needs to be changed, because other changes to the resource make it unavailable

  • urn:openproject-org:api:v3:errors:ResourceTypeMismatch (HTTP 422) A link to a resource of a specific type was expected, but the link to another type of resource was provided

  • urn:openproject-org:api:v3:errors:InternalServerError (HTTP 500) Default for HTTP 500 when no further information is available

  • urn:openproject-org:api:v3:errors:MultipleErrors Multiple errors occurred. See the embedded errors array for more details.

Formattable Text

OpenProject supports text formatting in Markdown. Properties that contain formattable text have a special representation in this API. In this specification their type is indicated as Formattable. Their representation contains the following properties:

Property Description Type Example Supported operations
format Indicates the formatting language of the raw text String markdown READ
raw The raw text, as entered by the user String I **am** formatted! READ / WRITE
html The text converted to HTML according to the format String I <strong>am</strong> formatted! READ

format can as of today have one of the following values:

  • plain - only basic formatting, e.g. inserting paragraphs and line breaks into HTML

  • markdown - formatting using Markdown

  • custom - There is no apparent formatting rule that transforms the raw version to HTML (only used for read only properties)

Note that raw is the only property supporting the write operation. A property of type Formattable that is marked as read and write, will only accept changes to the raw property. Changes to format and html will be silently ignored. It is thus sufficient to solely provide the raw property for changes.

If the Formattable is marked as read only, the raw attribute also becomes read only.

Example
{
  "format": "markdown",
  "raw": "I **am** formatted!",
  "html": "I <strong>am</strong> formatted!"
}

Dates, Times, Durations and Timestamps

Representation of time related values in this API is done according to ISO 8601. In this specification the following terms will be used as type specifiers (e.g. in tables):

  • Date - refers to an ISO 8601 date, e.g. “2014-05-21”

  • DateTime - refers to an ISO 8601 combined date and time, optionally with milliseconds, e.g. “2014-05-21T13:37:00Z” or “2014-05-21T13:37:00.396Z”

  • Duration - refers to an ISO 8601 duration, e.g. “P1DT18H”

  • Timestamp - refers to an ISO 8601 combined date and time, e.g. “2014-05-21T13:37:00Z” or to an ISO 8601 duration, e.g. “P1DT18H”. The following shorthand values are also being parsed as duration: “1d”, “1w”, “1m”, “1y”, “1y-2m”, “-2y”. It can also refer the following relative date keywords: "oneDayAgo@HH:MM+HH:MM", "lastWorkingDay@HH:MM+HH:MM", "oneWeekAgo@HH:MM+HH:MM", "oneMonthAgo@HH:MM+HH:MM". The "HH:MM" part represents the zero padded hours and minutes, e.g. "oneMonthAgo@21:00+00:00". The last “+HH:MM” part represents the timezone offset from UTC associated with the time, e.g. "oneMonthAgo@21:00+02:00" means a +2 hour timezone offset from UTC. The offset can be positive or negative e.g.“oneDayAgo@01:00+01:00”, “oneDayAgo@01:00-01:00”. Values older than 1 day are accepted only with valid Enterprise Token available.

Colors

Colors are represented in RGB using hexadecimal notation as specified in CSS Color Module Level 3. That is a # followed by either three or six hexadecimal digits.

Example
    red:   #ff0000 or #f00
    green: #00ff00 or #0f0
    black: #000000 or #000
    white: #ffffff or #fff

Digests

Digests (or Hashes) are one way functions that map data of arbitrary size to data of a fixed size. In OpenProject they are for example used to calculate checksums for (attachment) files. The checksum calculated depends on the hashed data and the algorithm used as hash function.

Therefore all digests are represented in the following form:

Property Description Type Example
algorithm The algorithm used to compute the digest String md5
hash The calculated digest in hexadecimal notation String 64c26a8403cd796ea4cf913cda2ee4a9
Example
{
  "algorithm": "md5",
  "hash": "64c26a8403cd796ea4cf913cda2ee4a9"
}