diff --git a/CMakeLists.txt b/CMakeLists.txt
index 60c1c841852a8a48d3bc4a3c9a9ee6e8cb94eef5..067d2d70d8679f6139c056d1b79854ee7378fbc8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -72,9 +72,9 @@ add_library(msi_json_objops           SHARED src/msi_json_objops.cc)
 
 target_link_libraries(msiCurlMail               LINK_PUBLIC ${CURL_LIBRARIES})
 target_link_libraries(msiStrToUpper             LINK_PUBLIC ${Boost_LIBRARIES})
-target_link_libraries(msiRegisterDataCiteDOI    LINK_PUBLIC ${CURL_LIBRARIES})
-target_link_libraries(msiGetDataCiteDOI         LINK_PUBLIC ${CURL_LIBRARIES})
-target_link_libraries(msiRemoveDataCiteMetadata LINK_PUBLIC ${CURL_LIBRARIES})
+target_link_libraries(msiRegisterDataCiteDOI    LINK_PUBLIC ${CURL_LIBRARIES} ${JANSSON_LIBRARIES})
+target_link_libraries(msiGetDataCiteDOI         LINK_PUBLIC ${CURL_LIBRARIES} ${JANSSON_LIBRARIES})
+target_link_libraries(msiRemoveDataCiteMetadata LINK_PUBLIC ${CURL_LIBRARIES} ${JANSSON_LIBRARIES})
 target_link_libraries(msiLoadMetadataFromXml    LINK_PUBLIC ${LIBXML2_LIBRARIES})
 target_link_libraries(msiXmlDocSchemaValidate   LINK_PUBLIC ${LIBXML2_LIBRARIES})
 target_link_libraries(msiXsltApply              LINK_PUBLIC ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${LIBXSLT_EXSLT_LIBRARIES})
diff --git a/src/CredentialsStore.hh b/src/CredentialsStore.hh
new file mode 100644
index 0000000000000000000000000000000000000000..ef39ef84226fee7cd8655b4571a4cdb5d44e5c81
--- /dev/null
+++ b/src/CredentialsStore.hh
@@ -0,0 +1,41 @@
+#include "jansson.h"
+
+# define CREDS_STORE	"/var/lib/irods/.credentials_store/store_config.json"
+
+
+/*
+ * keep it simple
+ */
+class CredentialsStore {
+public:
+    // load stored values
+    CredentialsStore() {
+	json_error_t error;
+
+	store = json_load_file(CREDS_STORE, 0, &error);
+	// store is returned with refcount 1
+    }
+    // free stored values
+    ~CredentialsStore() {
+	if (store != NULL) {
+	    json_decref(store);
+	}
+    }
+
+    // get a credential from the store
+    const char *get(const char *key) {
+	if (store != NULL) {
+	    json_t *value;
+
+	    value = json_object_get(store, key);
+	    if (value != NULL && json_is_string(value)) {
+		return json_string_value(value);
+	    }
+	}
+
+	return NULL;
+    }
+
+private:
+    json_t *store;	// in-memory copy of credentials store
+};
diff --git a/src/msiGetDataCiteDOI.cc b/src/msiGetDataCiteDOI.cc
index a7fb4fb15f44a99d20c3035c5e8e3cb92191040c..d43169863c7741e0183a304205ed7039a92e2c41 100644
--- a/src/msiGetDataCiteDOI.cc
+++ b/src/msiGetDataCiteDOI.cc
@@ -25,6 +25,7 @@
  */
 
 #include "irods_includes.hh"
+#include "CredentialsStore.hh"
 
 #include <string>
 #include <fstream>
@@ -34,6 +35,8 @@
 
 namespace DataCite {
 
+static CredentialsStore credentials;
+
   /* Curl requires a static callback function to write the output of a GET request to.
    * This callback simply puts the result in a std::string at *userp */
   static size_t writeCallback(void *contents, size_t size, size_t nmemb, void *userp)
@@ -43,10 +46,8 @@ namespace DataCite {
   }
 
 
-  int getDOI(msParam_t* urlIn,
-             msParam_t* usernameIn,
-             msParam_t* passwordIn,
-             msParam_t* resultOut,
+  int getDOI(msParam_t* doiIn,
+	     msParam_t* resultOut,
              msParam_t* httpCodeOut,
              ruleExecInfo_t *rei)
   {
@@ -55,20 +56,18 @@ namespace DataCite {
 
 
     /* Check input parameters. */
-    if (strcmp(urlIn->type, STR_MS_T)) {
-      return SYS_INVALID_INPUT_PARAM;
-    }
-    if (strcmp(usernameIn->type, STR_MS_T)) {
-      return SYS_INVALID_INPUT_PARAM;
-    }
-    if (strcmp(passwordIn->type, STR_MS_T)) {
+    if (strcmp(doiIn->type, STR_MS_T)) {
       return SYS_INVALID_INPUT_PARAM;
     }
 
     /* Parse input paramaters. */
-    std::string url      = parseMspForStr(urlIn);
-    std::string username = parseMspForStr(usernameIn);
-    std::string password = parseMspForStr(passwordIn);
+    std::string doi      = parseMspForStr(doiIn);
+
+    /* obtain parameters from the credentials store */
+    std::string url(credentials.get("datacite_url"));
+    url += "/doi/" + doi;
+    std::string username(credentials.get("datacite_username"));
+    std::string password(credentials.get("datacite_password"));
 
     /* declare result buffer for result */ 
     std::string resultBuffer;
@@ -155,29 +154,23 @@ namespace DataCite {
 
 extern "C" {
 
-  int msiGetDataCiteDOI(msParam_t* urlIn,
-                        msParam_t* usernameIn,
-                        msParam_t* passwordIn,
-                        msParam_t* resultOut,
+  int msiGetDataCiteDOI(msParam_t* doiIn,
+			msParam_t* resultOut,
                         msParam_t* httpCodeOut,
 		        ruleExecInfo_t *rei) {
-       return DataCite::getDOI(urlIn, usernameIn, passwordIn, resultOut, httpCodeOut, rei);
+       return DataCite::getDOI(doiIn, resultOut, httpCodeOut, rei);
   }
 
 
   irods::ms_table_entry* plugin_factory() {
-    irods::ms_table_entry *msvc = new irods::ms_table_entry(5);
+    irods::ms_table_entry *msvc = new irods::ms_table_entry(3);
 
     msvc->add_operation<
-      msParam_t*,
-      msParam_t*,
       msParam_t*,
       msParam_t*,
       msParam_t*,
       ruleExecInfo_t*>("msiGetDataCiteDOI",
 		       std::function<int(
-					 msParam_t*,
-					 msParam_t*,
 					 msParam_t*,
 					 msParam_t*,
 					 msParam_t*,
diff --git a/src/msiRegisterDataCiteDOI.cc b/src/msiRegisterDataCiteDOI.cc
index ce576b0bfbd5084d60f074c8b6c572402288362c..dde08eadc96c57b4d0b5bc8136bdba9e80ed068a 100644
--- a/src/msiRegisterDataCiteDOI.cc
+++ b/src/msiRegisterDataCiteDOI.cc
@@ -22,17 +22,17 @@
  */
 
 #include "irods_includes.hh"
+#include "CredentialsStore.hh"
 
 #include <string>
 #include <fstream>
 #include <streambuf>
 #include <curl/curl.h>
 
+static CredentialsStore credentials;
+
 extern "C" {
-  int msiRegisterDataCiteDOI(msParam_t* urlIn,
-			     msParam_t* usernameIn,
-			     msParam_t* passwordIn,
-			     msParam_t* payloadIn,
+  int msiRegisterDataCiteDOI(msParam_t* payloadIn,
 			     msParam_t* httpCodeOut,
 			     ruleExecInfo_t *rei)
   {
@@ -45,25 +45,28 @@ extern "C" {
     }
 
     /* Check input parameters. */
-    if (strcmp(urlIn->type, STR_MS_T)) {
-      return SYS_INVALID_INPUT_PARAM;
-    }
-    if (strcmp(usernameIn->type, STR_MS_T)) {
-      return SYS_INVALID_INPUT_PARAM;
-    }
-    if (strcmp(passwordIn->type, STR_MS_T)) {
-      return SYS_INVALID_INPUT_PARAM;
-    }
     if (strcmp(payloadIn->type, STR_MS_T)) {
       return SYS_INVALID_INPUT_PARAM;
     }
 
     /* Parse input paramaters. */
-    std::string url      = parseMspForStr(urlIn);
-    std::string username = parseMspForStr(usernameIn);
-    std::string password = parseMspForStr(passwordIn);
     std::string payload  = parseMspForStr(payloadIn);
 
+    /* Check if payload is XML */
+    bool isXml;
+    std::string xmlPrefix = "<?xml";
+    if (payload.substr(0, xmlPrefix.size()) == xmlPrefix) {
+      isXml = true;
+    } else {
+      isXml = false;
+    }
+
+    /* Get parameters from credentials store. */
+    std::string url(credentials.get("datacite_url"));
+    url += (isXml) ? "/metadata" : "/doi";
+    std::string username(credentials.get("datacite_username"));
+    std::string password(credentials.get("datacite_password"));
+
     /* Get a curl handle. */
     curl = curl_easy_init();
 
@@ -78,15 +81,6 @@ extern "C" {
       curl_easy_setopt(curl, CURLOPT_USERNAME, username.c_str());
       curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str());
 
-      /* Check if payload is XML */
-      bool isXml;
-      std::string xmlPrefix = "<?xml";
-      if (payload.substr(0, xmlPrefix.size()) == xmlPrefix) {
-        isXml = true;
-      } else {
-        isXml = false;
-      }
-
       /* Set HTTP header Content-Type. */
       struct curl_slist *list = NULL;
       if (isXml) {
@@ -171,19 +165,13 @@ extern "C" {
   }
 
   irods::ms_table_entry* plugin_factory() {
-    irods::ms_table_entry *msvc = new irods::ms_table_entry(5);
+    irods::ms_table_entry *msvc = new irods::ms_table_entry(2);
 
     msvc->add_operation<
-        msParam_t*,
-        msParam_t*,
-        msParam_t*,
         msParam_t*,
         msParam_t*,
         ruleExecInfo_t*>("msiRegisterDataCiteDOI",
                          std::function<int(
-                             msParam_t*,
-                             msParam_t*,
-                             msParam_t*,
                              msParam_t*,
                              msParam_t*,
                              ruleExecInfo_t*)>(msiRegisterDataCiteDOI));
diff --git a/src/msiRemoveDataCiteMetadata.cc b/src/msiRemoveDataCiteMetadata.cc
index f59d6e433273f79eca31ad30315aa3d12077f18d..9573008b64dd66fa769913b58f7a33b796e97746 100644
--- a/src/msiRemoveDataCiteMetadata.cc
+++ b/src/msiRemoveDataCiteMetadata.cc
@@ -25,16 +25,17 @@
  */
 
 #include "irods_includes.hh"
+#include "CredentialsStore.hh"
 
 #include <string>
 #include <fstream>
 #include <streambuf>
 #include <curl/curl.h>
 
+static CredentialsStore credentials;
+
 extern "C" {
-  int msiRemoveDataCiteMetadata(msParam_t* urlIn,
-				msParam_t* usernameIn,
-				msParam_t* passwordIn,
+  int msiRemoveDataCiteMetadata(msParam_t* doiIn,
 				msParam_t* httpCodeOut,
 				ruleExecInfo_t *rei)
   {
@@ -47,20 +48,19 @@ extern "C" {
     }
 
     /* Check input parameters. */
-    if (strcmp(urlIn->type, STR_MS_T)) {
-      return SYS_INVALID_INPUT_PARAM;
-    }
-    if (strcmp(usernameIn->type, STR_MS_T)) {
-      return SYS_INVALID_INPUT_PARAM;
-    }
-    if (strcmp(passwordIn->type, STR_MS_T)) {
+    if (strcmp(doiIn->type, STR_MS_T)) {
       return SYS_INVALID_INPUT_PARAM;
     }
 
     /* Parse input paramaters. */
-    std::string url      = parseMspForStr(urlIn);
-    std::string username = parseMspForStr(usernameIn);
-    std::string password = parseMspForStr(passwordIn);
+    std::string doi = parseMspForStr(doiIn);
+
+    /* Get parameters from credentials store. */
+    std::string url(credentials.get("datacite_url"));
+    url += "/metadata/" + doi;
+    std::string username(credentials.get("datacite_username"));
+    std::string password(credentials.get("datacite_password"));
+
 
     /* Get a curl handle. */
     curl = curl_easy_init();
@@ -131,17 +131,13 @@ extern "C" {
   }
 
   irods::ms_table_entry* plugin_factory() {
-    irods::ms_table_entry *msvc = new irods::ms_table_entry(4);
+    irods::ms_table_entry *msvc = new irods::ms_table_entry(2);
 
     msvc->add_operation<
-        msParam_t*,
-        msParam_t*,
         msParam_t*,
         msParam_t*,
         ruleExecInfo_t*>("msiRemoveDataCiteMetadata",
                          std::function<int(
-                             msParam_t*,
-                             msParam_t*,
                              msParam_t*,
                              msParam_t*,
                              ruleExecInfo_t*)>(msiRemoveDataCiteMetadata));