Orderly does not provide an API yet, although there are plans to do this in the future. However, the databases are entirely stored in Confluence, and Confluence does provide an API to access the data. If you want to access and/or edit the data of an Orderly Database programmatically, for example to integrate your database with other software, this page gives you a rough overview over the data model so that you can implement an (experimental) solution already today. Note that the data model is considered internal and there is no guarantee that no breaking changes are introduced at any point.

To use the Confluence REST API programmatically, you need to set up OAuth 2.0 (3LO) authentication. For test purposes, you can also access the REST endpoints directly in the browser without the need for separate authentication, making use of the session cookie from logging in through the Confluence UI.

Method 1: Access a Database Using the Export View

If you just want to extract the contents of a database without needing to update it, an easy way is to use the export view. The export view is a static HTML rendering of the database contents, separate but similar to the database details UI. It is used when exporting Orderly macros to PDF or to a Scroll Viewport, and for the print preview that can be opened from the database details UI.

When accessing a Confluence page through the Get Content API, its body.export_view.value property contains a static HTML rendering of the page. If the page contains an Orderly Database macro, the export view will contain a static HTML rendering of the database. Try this out by opening https://x.atlassian.net/wiki/rest/api/content/1234?expand=body.export_view for a page containing an Orderly Database macro (1234 needs to be replaced by the ID of your page).

Using the Convert Body API, we can get the export view for any arbitrary page content, without needing to save that content on an actual Confluence page. By converting an Orderly Database macro to export format, we can get the export view of the database. Here is an example requesting using the JavaScript Fetch API:

fetch("https://x.atlassian.net/wiki/rest/api/contentbody/convert/export_view", {
  method: "POST",
  headers: {
    "content-type": "application/json"
  },
  body: JSON.stringify({
    representation: "storage",
    value: `<ac:structured-macro ac:name="orderly-database"><ac:parameter ac:name="databaseSpace"><ri:space ri:space-key="SPACE"/></ac:parameter><ac:parameter ac:name="databaseId">9fbcb199-0f25-4cb4-8e3c-06b16b9292f2</ac:parameter></ac:structured-macro>`
  })
})
CODE

In the macro parameters in the body, you need to provide the space key of the space where the database resides and the database ID. To find out the database ID, open the database details UI and extract the database content ID from its URL. For example, if the URL is https://x.atlassian.net/wiki/display/SPACE/customcontent/list/ac%3Acom.k15t.orderly.databases%3Adatabase#!/database/1234, then the content ID of the database is 1234. Then open https://x.atlassian.net/wiki/rest/api/content/1234/property/K15tOrderlyDatabase (replacing 1234 with your actual content ID) and find the database ID in the value.id  property (it is in UUID format).

The database export view contains a HTML table with the contents of the whole database. You can use a HTML parser to extract whatever data you need.

Method 2: Access and Update a Database Using Storage Format

Orderly Databases are entirely stored in Confluence as custom content. Custom content types can be set up by Confluence apps in addition to existing content types such as pages and blog posts, and they can make use of many Confluence features such as the Confluence storage format, content restrictions and attachments. Custom content objects are mostly hidden from the Confluence UI, but they can be found by selecting the respective content type in the Confluence search.

Each Orderly Database consists of two custom content objects:

  1. An object of the type ac:com.k15t.orderly.databases:database contains the database metadata, such as the database name, cover image and fields. This object is saved directly on the space level.
  2. An object of the type ac:com.k15t.orderly.databases:database-entries contains the database content, such as the database entries and values. This object is saved as a child of the database custom content object.

Each content object in Confluence is identified by an integer ID (in string notation as they can get bigger than the biggest supported number in JavaScript). One way of finding out the content ID of your database is by looking at the URL of its database details UI. For example, if the database details UI has the URL https://x.atlassian.net/wiki/display/SPACE/customcontent/list/ac%3Acom.k15t.orderly.databases%3Adatabase#!/database/1234, then the content ID of the database is 1234.

The Content API can be used to access custom content through the Confluence REST API. To load a database with the content ID 1234, open the URL https://x.atlassian.net/wiki/rest/api/content/1234?expand=body.storage%2Cmetadata.properties.K15tOrderlyDatabase%2Cchildren.ac__com_k15t_orderly_databases__database_entries.body.storage%2Cversion. The expand parameter contains the expansions to include all the necessary data in the response.

Most of the data of an Orderly Database is stored in the storage format body of the custom content objects. The Confluence storage format is XHTML with a few additions. To be able to parse the storage format correctly, your HTML/XML parser must be configured to support self-closing elements, HTML entities and CDATA blocks (these are a mix of HTML and XML features). The storage format for Confluence Cloud is not documented, but it mostly resembles the Confluence Storage Format on Confluence Server.

An Orderly Database mostly consists of its database settings (such as database name, cover image, main field ID), a list of database fields (containing a field type, name, ID and type-specific settings), a list of database entries (containing an ID) and a list of database values (containing the referenced field ID and entry ID and the actual content). Orderly stores these objects as Confluence macros in the storage format bodies of the database custom content objects. The storage format bodies are simply a sequence of (internal, not available through the Confluence UI) Orderly macros that have the data stored in their macro parameters and body. The following internal Orderly macros exist:

  • orderly-db occurs once in the database custom content object and contains some database metadata such as the main field ID.
  • orderly-db-field occurs once for each database field in the database custom content object. It contains the field metadata such as field ID, field type and field settings in its parameters and the field name as its body. The order of occurrence of the macros determines the order of the fields.
  • orderly-db-entry occurs once for each entry in the database entries custom content object. It contains the entry ID in its parameters. The order of occurrence of the macros determines the order of the entries in the database. In addition to the entry macros in the database entries custom content object, there is one entry macro in the database custom content object that represents the “default entry”, a virtual entry representing the default values for each database field.
  • orderly-db-value occurs once for each database value in the database entries custom content object (and in the database custom content object for the default values). It contains the field ID and entry ID that it belongs to and some metadata (depending on the particular field type) in its parameters and its content in its body (the exact body format depends on the field type). The order of occurrence is not important since it is determined by the order of the corresponding fields and entries, but Orderly always puts the value macros behind their corresponding entry macro, in order of their corresponding fields. Note that in addition to the macro parameters and body, some field types (such as the image field type) may create attachments on their respective custom content object and reference them in their parameters or body.

Looking at the body.storage.value property of an existing Orderly Database, you will see how it is a sequence of one orderly-db macro, multiple orderly-db-field macros, one orderly-db-entry macro (for the default entry) and multiple orderly-db-value macros (for the default values). The children['ac:com.k15t.orderly.databases:database-entries'].results[0].body.storage.value property (the body of the database entries custom content object) is a sequence of multiple orderly-db-entry macros, each followed by multiple orderly-db-value macros.

To modify an existing database, the Update Content API can be used. One request each is needed to update the database custom content object and the database entries custom content object, although it is perfectly fine to update only one of them if only that part of the database needs to be changed. Note that the documentation of the Confluence API is often not complete, and the resulting error messages are often not very descriptive. Here is a minimal example request to update the database entries custom content object using the JavaScript Fetch API:

fetch("https://x.atlassian.net/wiki/rest/api/content/12345?expand=", {
  "method": "PUT", 
  "headers": {
    "content-type": "application/json"
  },
  "body": JSON.stringify({
    id: "12345", // The content ID of the database entries custom content object
    space: { key: "SPACE" },
    container: { id: "1234", type: "ac:com.k15t.orderly.databases:database" }, // The content ID of the corresponding database custom content object
    title: "Test database (Orderly Database Content)", // The suffix (Orderly Database) for the database and (Orderly Database Content) for the database entries must be kept due to a Confluence bug
    type: "ac:com.k15t.orderly.databases:database-entries",
    version: { number: 123 }, // The version number must be 1 higher than the currently saved version number
    body: {
      storage: {
        representation: "storage",
        value: "..."
      }
    }
  })
});
JS