Interact with Confluence Server via REST API using NodeJS(JS)
Tags: javascript, restapi, confluence, atlassian
Published: 2022-05-06 09:04:52

Sometimes there can be a need to automate some actions in Confluence or perform some action multiple times, etc. For this Confluence REST API can be used together with the programming language and API to interact via HTTP.

Previous example using Groovy - https://dev.to/andriimaliuta/how-to-update-several-pages-in-confluence-via-rest-api-k6c.

In this example we will use JavaScript and axios library (you do not need the very axios and can use core FETCH if you want - this is just one of ways) to initiate Confluence REST endpoints to:

- getPage.js
- getChildren.js 
- getDescendants.js
- createComment.js
- createPage.js
- deleteLabel.js
- getPageLabels.js
 
Git repo - https://github.com/ahndmal/js-atlassian-rest-client

## Data file

Approximate file structure:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1lsokm57607ce2cyye1e.png)


First we create data.js file to store constants with data:

```js
const dotenv = require('dotenv');
dotenv.config();
const username = process.env.username;
const password = process.env.password;
const CONF_URL = process.env.CONF_URL;

module.exports = {
  authData: Buffer.from(`${username}:${password}`).toString('base64'),
  CONF_URL
};
```

We create Basic Auth Base64 token from username and password.

## Get Page information

Request:
``` 
GET /rest/content
```
CONTENT is the entity that represents:
- page
- comment
- blogpost

The example of **getPage.js** file: 

```js  
const axios = require('axios');
const https = require('https');
const { authData, CONF_URL } = require('./data');

module.exports = async function getPage(pageId) {
  console.log('>>> Initiating REST request...');

  return axios.get(`${CONF_URL}/rest/api/content/${pageId}`, {
    headers: {
      Authorization: `Basic ${authData}`,
    },
    httpsAgent: new https.Agent({
      rejectUnauthorized: false,
    }),
  });
};
```

## getChildren.js

Request:
``` 
GET ${CONF_URL}/rest/api/content/${pageId}/child/page
```

```js
const axios = require("axios");
const https = require("https");
const { authData, CONF_URL } = require("./data");

module.exports = async function getPageChildren(pageId) {
  console.log(" Initiating REST request...");

  return await axios.get(`${CONF_URL}/rest/api/content/${pageId}/child/page`, {
    headers: {
      Authorization: `Basic ${authData}`,
    },
    httpsAgent: new https.Agent({
      rejectUnauthorized: false,
    }),
  });
};
```

## getDescendants.js

``` js
const axios = require("axios");
const https = require("https");
const { authData, CONF_URL } = require("./data");

module.exports = async function getPageChildren(pageId) {
  console.log(">>> Initiating REST request...");

  return await axios.get(
    `${CONF_URL}/rest/api/search?cql=type+=+"page"+and+ancestor+%3D+"${pageId}"`,
    {
      headers: {
        Authorization: `Basic ${authData}`,
      },
      httpsAgent: new https.Agent({
        rejectUnauthorized: false,
      }),
    }
  );
};
```
## Create Page (Blogpost / Comment)

**createPage.js**

```js
const axios = require('axios');
const https = require('https');
const { authData, CONF_URL } = require('./data');

module.exports = async function createPage(space, title, body, parent_id) {
  console.log(' Initiating REST request...');
  data = {
    type: 'page',
    title: title,
    space: { key: space },
    body: {
      storage: {
        value: body,
        representation: 'storage',
      },
    },
    ancestors: [{ id: parent_id }],
  };

  return await axios.post(`${CONF_URL}/rest/api/content`, {
    headers: {
      Authorization: `Basic ${authData}`,
      'Content-Type': 'application/json',
    },
    httpsAgent: new https.Agent({
      rejectUnauthorized: false,
    }),
    data: data,
  });
};
```

## Making requests

Now we craete **index.js** file (name is up to you :), of course ) and perform necessary actions. Here we will CONSOLE.LOG the result of requests, but of course you can further adjust, combine and expand code to do what you need.

```js
const getPage = require('./getPage');
const getChildren = require('./getChildren');
const getDescendants = require('./getDescendants');
const createPage = require('./createPage');
const getPageLabels = require('./getPageLabels');
const createComment = require('./createComment');

const PAGE_ID = 123456; // specify the PAGE ID

async function init() {

// GET PAGE
   getPage(PAGE_ID)
     .then((res) => console.log(res.data))
     .catch((err) => console.log(err));
   
  // GET all descendant pages of the root one
   getDescendants(PAGE_ID).then((res) => console.log(res.data));

  // ====== Create Page =====
const SPACE_KEY = "TEST";
  createPage(SPACE_KEY, 'MY PAGE TITLE', 'this is body', PAGE_ID).then((res) =>
    console.log(res.data)
  );

  // ====== Create comment ======
   createComment('TEST', 'test title', 'rest comment!', 1000, PAGE_ID).then(
     (res) => console.log(res.data)
   );

// labels

   const PAGE_ID = 12345;
   getPageLabels(PAGE_ID).then((res) => {
     for (label of res.data.results) {
       deleteLabel(PAGE_ID, label.name);
     }
   });

   deleteLabel(labelId, "error-template").then((res) => console.log(res.data));
  
}

// ========= initiate the code !!
init();

```

That is all. Of course , these are promitive examples , but the sooth is to understand the very principles and then further do almost any actions you need via REST API that to ease your work with Confluence :)

Please let me know if it is helpful.

Thanks!