How to store configuration properties in a Confluence Cloud app?

I followed the tutorial ti add a new Confluence cloud app: https://developer.atlassian.com/cloud/confluence/tutorials-and-guides/

I am looking for a way to store configration data (simple key.value pairs) in Confluence Cloud app. So I’ve found this: https://developer.atlassian.com/cloud/confluence/app-properties-api/

I am writing a expressjs app and added the following snippet into my index.js

app.get('/random-page-admin', addon.authenticate(), function (req, res) {
   var userKey = req.query['user_key'];
   var clientKey = req.context.clientKey;

   getHTTPClient(clientKey, userKey).put(
      '/rest/atlassian-connect/1/addons/random-page-cloud/properties/pages-limit',
      function (err, response, contents) {

         if (err || (response.statusCode < 200 || response.statusCode > 299)) {
            res.render('<strong>An error has occurred :( ' + response.statusCode + '</strong>');
            return;
         }

         contents = JSON.parse(contents);

         res.render('admin/random-page-admin', {});
      }
   );

});

Result:

{"status-code":404,"message":"Add-on with key does not exist."}

Although the answer “Add-on with key does not exist.” points to a wrong add-on key, in my case the problem was the context. As the app-properties-api documentation sais

Request issued by a user with insufficient credentials, e.g. for an app’s data by anyone but the app itself, or for a app that does not exist.

Where the interesting part in my case was “for an app’s data by anyone but the app itself” meaning that the requests have to be send within the app (a simple GET request from the browser will fail with the given error)

I had to send the request from within the app (index.js). First a PUT and then a GET for the property

app.get('/store', addon.authenticate(), function (req, res) {
   var userKey = req.query['user_key'];
   var clientKey = req.context.clientKey;

   var options = {
      headers: {
         'X-Atlassian-Token': 'nocheck'
      },
      url: '/rest/atlassian-connect/1/addons/<add-on-key>/properties/<property-key>',
      json: 'true'
   };

   getHTTPClient(clientKey, userKey).put(options,
      function (err, response, contents) {
         getHTTPClient(clientKey, userKey).get(
            '/rest/atlassian-connect/1/addons/<add-on-key>/properties/<property-key>',
            function (err, response, contents) {
               contents = JSON.parse(contents);
               res.render('test', {
                  'test': contents,
                  'status': response.statusCode
               });
            });
      });
});

function getHTTPClient(clientKey, userKey) {
   return addon.httpClient({
      clientKey: clientKey,
      userKey: userKey,
      appKey: addon.key
   });
}

This just a simple example and not meatn for production :slight_smile: