diff --git a/dbrepo-ui/api/database.service.js b/dbrepo-ui/api/database.service.js
index fdbaf1ef94899166eb9a990aa044a10764bb39fe..17cbf65479badd1aeb6c21d61e9828d22115ab8f 100644
--- a/dbrepo-ui/api/database.service.js
+++ b/dbrepo-ui/api/database.service.js
@@ -51,6 +51,19 @@ class DatabaseService {
     })
   }
 
+  delete (id, databaseId) {
+    return new Promise((resolve, reject) => {
+      api.delete(`/api/container/${id}/database/${databaseId}`, { headers: { Accept: 'application/json' } })
+        .then(() => resolve())
+        .catch((error) => {
+          const { code, message } = error
+          console.error('Failed to delete database', error)
+          Vue.$toast.error(`[${code}] Failed to delete database: ${message}`)
+          reject(error)
+        })
+    })
+  }
+
   modifyVisibility (id, databaseId, isPublic) {
     return new Promise((resolve, reject) => {
       api.put(`/api/container/${id}/database/${databaseId}/visibility`, { is_public: isPublic }, { headers: { Accept: 'application/json' } })
diff --git a/dbrepo-ui/components/dialogs/EditAccess.vue b/dbrepo-ui/components/dialogs/EditAccess.vue
index 4f30ef9d85c74d9efbd52f6181a00840e999f9d7..1ba70270745992a29236b81d58b561d1cfc140b0 100644
--- a/dbrepo-ui/components/dialogs/EditAccess.vue
+++ b/dbrepo-ui/components/dialogs/EditAccess.vue
@@ -73,6 +73,8 @@
 </template>
 
 <script>
+import DatabaseService from '@/api/database.service'
+import UserService from '@/api/user.service'
 export default {
   props: {
     username: {
@@ -195,69 +197,49 @@ export default {
         await this.giveAccess()
       }
     },
-    async revokeAccess () {
+    revokeAccess () {
       this.loading = true
-      try {
-        const res = await this.$axios.delete(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/access/${this.username}`, this.config)
-        console.debug('revoke access', res.data)
-        this.$toast.success(`Successfully revoked access of ${this.username}`)
-        this.$emit('close-dialog', { success: true })
-      } catch (err) {
-        console.log('revoke access', err)
-        this.$toast.error('Could not revoke access to database')
-      }
-      this.loading = false
+      DatabaseService.revokeAccess(this.$route.params.container_id, this.$route.params.database_id, this.username)
+        .then(() => {
+          this.$toast.success(`Successfully revoked access of ${this.username}`)
+          this.$emit('close-dialog', { success: true })
+        })
+        .finally(() => {
+          this.loading = false
+        })
     },
-    async modifyAccess () {
+    modifyAccess () {
       this.loading = true
-      try {
-        const res = await this.$axios.put(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/access/${this.username}`, {
-          type: this.modify.type
-        }, this.config)
-        console.debug('give access', res.data)
-        this.$toast.success('Successfully modified access')
-        this.$emit('close-dialog', { success: true })
-      } catch (err) {
-        console.log('modify access', err)
-        this.$toast.error('Could not modify access to database')
-      }
-      this.loading = false
+      DatabaseService.modifyAccess(this.$route.params.container_id, this.$route.params.database_id, this.username, this.modify.type)
+        .then(() => {
+          this.$toast.success('Successfully modified access')
+          this.$emit('close-dialog', { success: true })
+        })
+        .finally(() => {
+          this.loading = false
+        })
     },
-    async giveAccess () {
+    giveAccess () {
       const username = this.modify.username
       this.loading = true
-      try {
-        const res = await this.$axios.post(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/access`, this.modify, this.config)
-        console.debug('give access', res.data)
-        this.$toast.success(`Successfully gave ${username} access`)
-        this.$emit('close-dialog', { success: true })
-      } catch (err) {
-        if (err.response.status === 405) {
-          this.$toast.error(`User ${username} already has access`)
-          this.loading = false
-          return
-        } else if (err.response.status === 404) {
-          this.$toast.error(`User ${username} does not exist`)
+      DatabaseService.giveAccess(this.$route.params.container_id, this.$route.params.database_id, this.username, this.modify.type)
+        .then(() => {
+          this.$toast.success(`Successfully gave ${username} access`)
+          this.$emit('close-dialog', { success: true })
+        })
+        .finally(() => {
           this.loading = false
-          return
-        }
-        console.log('give access', err)
-        this.$toast.error('Could not give access to database')
-      }
-      this.loading = false
+        })
     },
-    async loadUsers () {
+    loadUsers () {
       this.loadingUsers = true
-      try {
-        const res = await this.$axios.get('/api/user', this.config)
-        this.users = res.data.filter(u => u.username !== this.database.creator.username)
-        console.debug('users', this.users)
-      } catch (error) {
-        console.error('Failed to load users', error)
-        const { message } = error.response.data
-        this.$toast.error(`Failed to load users: ${message}`)
-      }
-      this.loadingUsers = false
+      UserService.findAll()
+        .then((users) => {
+          this.users = users.filter(u => u.username !== this.database.creator.username)
+        })
+        .finally(() => {
+          this.loading = false
+        })
     },
     init () {
       if (!this.username) {
diff --git a/dbrepo-ui/components/identifier/Citation.vue b/dbrepo-ui/components/identifier/Citation.vue
index 5701cfa672deef809690770509286455bff023c3..9d3037905c1e43eb593f003c21fab7ec4f9bc88f 100644
--- a/dbrepo-ui/components/identifier/Citation.vue
+++ b/dbrepo-ui/components/identifier/Citation.vue
@@ -35,6 +35,7 @@
 </template>
 
 <script>
+import IdentifierService from '@/api/identifier.service'
 
 export default {
   props: {
diff --git a/dbrepo-ui/components/identifier/DownloadButton.vue b/dbrepo-ui/components/identifier/DownloadButton.vue
index 0ccc07b8afc299d1f1626ddc0ed74e24bd7f49b4..495d2b0a8421da07f783dea5e29ddd8554a0c9dc 100644
--- a/dbrepo-ui/components/identifier/DownloadButton.vue
+++ b/dbrepo-ui/components/identifier/DownloadButton.vue
@@ -8,6 +8,7 @@
 </template>
 
 <script>
+import IdentifierService from '@/api/identifier.service'
 
 export default {
   props: {
@@ -35,41 +36,21 @@ export default {
       loading: false
     }
   },
-  computed: {
-    token () {
-      return this.$store.state.token
-    },
-    config () {
-      if (this.token === null) {
-        return {
-          headers: { Accept: 'application/json' }
-        }
-      }
-      return {
-        headers: { Authorization: `Bearer ${this.token}`, Accept: 'application/json' }
-      }
-    }
-  },
   methods: {
-    async download () {
+    download () {
       this.loading = true
-      try {
-        const config = this.config
-        config.headers.Accept = this.contentType
-        const res = await this.$axios.get(`/api/pid/${this.pid}`, config)
-        console.debug('export identifier', res)
-        const url = window.URL.createObjectURL(new Blob([res.data]))
-        const link = document.createElement('a')
-        link.href = url
-        link.setAttribute('download', this.filename)
-        document.body.appendChild(link)
-        link.click()
-      } catch (err) {
-        console.error('Could not export identifier', err)
-        this.$toast.error('Could not export identifier')
-        this.error = true
-      }
-      this.loading = false
+      IdentifierService.export(this.pid)
+        .then((data) => {
+          const url = window.URL.createObjectURL(new Blob([data]))
+          const link = document.createElement('a')
+          link.href = url
+          link.setAttribute('download', this.filename)
+          document.body.appendChild(link)
+          link.click()
+        })
+        .finally(() => {
+          this.loading = false
+        })
     }
   }
 }
diff --git a/dbrepo-ui/pages/container/_container_id/database/_database_id/admin.vue b/dbrepo-ui/pages/container/_container_id/database/_database_id/admin.vue
index 6b9a9ba6cb5abceeb7e4d5cc0d2b38251efbdafc..c3d1f0f47fedc994be074e05d0d3d6c5fa3f88c8 100644
--- a/dbrepo-ui/pages/container/_container_id/database/_database_id/admin.vue
+++ b/dbrepo-ui/pages/container/_container_id/database/_database_id/admin.vue
@@ -38,6 +38,7 @@
 
 <script>
 import DBToolbar from '@/components/DBToolbar'
+import DatabaseService from '@/api/database.service'
 
 export default {
   components: {
@@ -71,34 +72,14 @@ export default {
       return this.confirm !== this.db.internalName
     }
   },
-  mounted () {
-    this.init()
-  },
   methods: {
-    async deleteDatabase () {
-      try {
-        await this.$axios.delete(`/api/database/${this.$route.params.database_id}`)
-        this.$router.push({ path: '/databases' })
-        this.$toast.success(`Database "${this.db.name}" deleted.`)
-      } catch (err) {
-        this.$toast.error('Could not delete database')
-      }
-      this.dialogDelete = false
-    },
-    async init () {
-      if (this.db != null) {
-        return
-      }
-      try {
-        this.loading = true
-        const res = await this.$axios.get(`/api/database/${this.$route.params.database_id}`)
-        console.debug('database', res.data)
-        this.$store.commit('SET_DATABASE', res.data)
-        this.loading = false
-      } catch (err) {
-        this.$toast.error('Could not load database')
-        this.loading = false
-      }
+    deleteDatabase () {
+      DatabaseService.delete(this.$route.params.container_id, this.$route.params.database_id)
+        .then(async () => {
+          this.$toast.success(`Database "${this.db.name}" deleted.`)
+          await this.$router.push({ path: '/databases' })
+          this.dialogDelete = false
+        })
     }
   }
 }